]> jfr.im git - irc/quakenet/newserv.git/blob - lpart/lpart.c
merge
[irc/quakenet/newserv.git] / lpart / lpart.c
1 /*
2 * lpart: simple newserv module to instruct L to leave a channel
3 * after it has had no other users for a certain time.
4 */
5
6 #include "../lib/sstring.h"
7 #include "../channel/channel.h"
8 #include "../core/config.h"
9 #include "../core/hooks.h"
10 #include "../nick/nick.h"
11 #include "../core/schedule.h"
12 #include "../control/control.h"
13 #include "../core/error.h"
14
15 sstring *targetnick; /* Name of the service to talk to */
16 int lpartext; /* Our chanext index */
17 int timeout; /* How long to wait for */
18 int shorttimeout; /* How long to wait if there are no interesting modes */
19
20 void lp_handlepart(int hooknum, void *arg);
21 void lp_dopart(void *arg);
22 void lp_schedpart(channel *cp);
23
24 void _init() {
25 sstring *tss;
26 int i;
27 chanindex *cip;
28 nick *np;
29
30 lpartext=registerchanext("lpart");
31
32 /* Set up the targetnick */
33 targetnick=getcopyconfigitem("lpart","servicenick","L",NICKLEN);
34
35 /* Set up the timeout */
36 tss=getcopyconfigitem("lpart","timeout","86400",6);
37 timeout=strtol(tss->content,NULL,10);
38 freesstring(tss);
39
40 tss=getcopyconfigitem("lpart","shorttimeout","300",6);
41 shorttimeout=strtol(tss->content,NULL,10);
42 freesstring(tss);
43
44 if ((np=getnickbynick(targetnick->content))) {
45 for(i=0;i<CHANNELHASHSIZE;i++) {
46 for (cip=chantable[i];cip;cip=cip->next) {
47 if (cip->channel && cip->channel->users->totalusers==1 &&
48 getnumerichandlefromchanhash(cip->channel->users,np->numeric)) {
49 lp_schedpart(cip->channel);
50 }
51 }
52 }
53 }
54
55 registerhook(HOOK_CHANNEL_LOSTNICK,&lp_handlepart);
56 }
57
58 void _fini() {
59 /* We need to clean up any outstanding callbacks we have */
60 deleteallschedules(&lp_dopart);
61 releasechanext(lpartext);
62 deregisterhook(HOOK_CHANNEL_LOSTNICK,&lp_handlepart);
63 }
64
65 void lp_handlepart(int hooknum, void *arg) {
66 void **args=(void **)arg;
67 channel *cp;
68 nick *np;
69
70 /* For a part, first arg is channel and second is nick */
71 cp=(channel *)args[0];
72
73 /* We're only interested if there is now one user on the channel.
74 Note that the parting user is STILL ON THE CHANNEL at this point,
75 so we're interested if there are two or fewer users left. */
76
77 if (cp->users->totalusers!=2)
78 return;
79
80 /* Let's see if our user is even on the network */
81 if ((np=getnickbynick(targetnick->content))==NULL)
82 return;
83
84 /* And if it's on the channel in question */
85 if (getnumerichandlefromchanhash(cp->users,np->numeric)==NULL)
86 return;
87
88 /* OK, now let's see if we already had something scheduled for this channel */
89 if (cp->index->exts[lpartext]!=NULL) {
90 /* We delete the old schedule at this point */
91 deleteschedule(cp->index->exts[lpartext],&lp_dopart, (void *)cp->index);
92 }
93
94 /* Error("lpart",ERR_DEBUG,"Scheduling part of channel %s",cp->index->name->content); */
95 lp_schedpart(cp);
96 }
97
98 void lp_schedpart(channel *cp) {
99 int thetimeout;
100
101 /* If the channel has anything that might be worth preserving, use the full timeout.
102 * Otherwise, use the shorter one
103 */
104
105 if ((cp->flags & ~(CHANMODE_NOEXTMSG | CHANMODE_TOPICLIMIT | CHANMODE_NOCTCP | CHANMODE_NONOTICE)) || cp->topic || cp->bans) {
106 thetimeout=timeout;
107 } else {
108 thetimeout=shorttimeout;
109 }
110
111 cp->index->exts[lpartext]=scheduleoneshot(time(NULL)+thetimeout,&lp_dopart,(void *)cp->index);
112 }
113
114 void lp_dopart(void *arg) {
115 chanindex *cip;
116 nick *np;
117
118 cip=(chanindex *)arg;
119 cip->exts[lpartext]=NULL;
120
121 /* Check the chan still exists */
122 if (cip->channel==NULL) {
123 releasechanindex(cip);
124 return;
125 }
126
127 /* Check the usercount is 1 */
128 if (cip->channel->users->totalusers>1)
129 return;
130
131 /* Let's see if our user is even on the network */
132 if ((np=getnickbynick(targetnick->content))==NULL)
133 return;
134
135 /* And if it's on the channel in question */
136 if (getnumerichandlefromchanhash(cip->channel->users,np->numeric)==NULL)
137 return;
138
139 /* OK, we've established that the channel is of size 1 and has our nick on it. Send the part command.
140 Use controlreply() for this */
141
142 /* Error("lpart",ERR_DEBUG,"Telling L to part %s",cip->name->content); */
143 controlmessage(np,"part %s",cip->name->content);
144 }