]> jfr.im git - irc/quakenet/newserv.git/blame - lpart/lpart.c
merge
[irc/quakenet/newserv.git] / lpart / lpart.c
CommitLineData
c86edd1d
Q
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
15sstring *targetnick; /* Name of the service to talk to */
16int lpartext; /* Our chanext index */
17int timeout; /* How long to wait for */
18int shorttimeout; /* How long to wait if there are no interesting modes */
19
20void lp_handlepart(int hooknum, void *arg);
21void lp_dopart(void *arg);
22void lp_schedpart(channel *cp);
23
24void _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
58void _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
65void 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
98void 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
b3637a8a 105 if ((cp->flags & ~(CHANMODE_NOEXTMSG | CHANMODE_TOPICLIMIT | CHANMODE_NOCTCP | CHANMODE_NONOTICE)) || cp->topic || cp->bans) {
c86edd1d
Q
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
114void 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); */
9db94003 143 controlmessage(np,"part %s",cip->name->content);
c86edd1d 144}