]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanservnetevents.c
3 * Handles the bot reaction to network events (joins, parts, mode changes
9 #include "../channel/channel.h"
10 #include "../nick/nick.h"
11 #include "../localuser/localuser.h"
12 #include "../localuser/localuserchannel.h"
17 * This is for HOOK_NICK_NEWNICK and HOOK_NICK_ACCOUNT.
18 * Associate the nick with it's correct account.
21 void cs_handlenick(int hooknum
, void *arg
) {
27 void cs_handlesethost(int hooknum
, void *arg
) {
33 void cs_handlelostnick(int hooknum
, void *arg
) {
39 if ((rup
=getreguserfromnick(np
))) {
40 for (nlh
=&(rup
->nicks
);*nlh
;nlh
=&((*nlh
)->next
)) {
48 if ((rup
->status
& QUSTAT_DEAD
) && !rup
->nicks
) {
53 if (getactiveuserfromnick(np
))
54 freeactiveuser(getactiveuserfromnick(np
));
58 * cs_handlenewchannel:
59 * This is for the HOOK_CHANNEL_NEWCHANNEL message.
60 * A new channel has just been created on the network, associate
61 * with the registered channel (if one exists) unless it's suspended.
64 void cs_handlenewchannel(int hooknum
, void *arg
) {
65 channel
*cp
=(channel
*)arg
;
72 /* Get the registered channel */
73 if ((rcp
=(regchan
*)cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
77 * If we're supposed to be joined, join ourselves..
80 if (CIsJoined(rcp
) && (chanservnick
!=NULL
)) {
84 /* This code interacts badly with bursts.. need to fix */
87 /* We need to watch out for people sneaking into +k/i channels..
88 * This code relies on the fact that that user will already be in
89 * the channel at this point in time.. */
90 if (rcp
->forcemodes
& (CHANMODE_KEY
| CHANMODE_INVITEONLY
)) {
91 /* OK, this channel is keyed.. let's find out if the user is allowed to be here */
92 for (i
=0;i
<cp
->users
->hashsize
;i
++) {
93 if (cp
->users
->content
[i
]!=nouser
&& (np
=getnickbynumeric(cp
->users
->content
[i
]))) {
95 /* service (might even be us..) */
98 if ((rup
=getreguserfromnick(np
)) && (rcup
=findreguseronchannel(rcp
, rup
)) &&
99 CUKnown(rcup
) && !CUIsBanned(rcup
))
103 localkickuser(chanservnick
, cp
, np
, "Private channel.");
109 /* Make sure the right modes are set/cleared */
110 cs_checkchanmodes(cp
);
112 /* Start the timer rolling */
113 cs_timerfunc(cp
->index
);
115 /* If topicsave or forcetopic is set, update the topic */
116 if (CIsForceTopic(rcp
) || CIsTopicSave(rcp
)) {
117 localsettopic(chanservnick
, cp
, (rcp
->topic
) ? rcp
->topic
->content
: "");
121 void cs_handlechanlostuser(int hooknum
, void *arg
) {
122 void **args
=(void **)arg
;
126 if (!(rcp
=cp
->index
->exts
[chanservext
]) || CIsSuspended(rcp
) || !chanservnick
||
127 (chanservnick
==args
[1]))
133 if (cp
->users
->totalusers
==2 &&
134 getnumerichandlefromchanhash(cp
->users
, chanservnick
->numeric
)) {
135 /* OK, Q is on the channel and not the one leaving.. */
136 rcp
->lastpart
=time(NULL
);
137 cs_schedupdate(cp
->index
, 1, 5);
143 * cs_handlelostchannel:
144 * This is for the HOOK_CHANNEL_LOSTCHANNEL message.
145 * A channel has just disappeared, clear our association with it.
148 void cs_handlelostchannel(int hooknum
, void *arg
) {
149 /* channel *cp=(channel *)arg; */
151 /* Do we actually need to do anything here? */
156 * A user joined a channel. See if we need to op/etc. them.
157 * Use this for JOIN or CREATE.
160 void cs_handlejoin(int hooknum
, void *arg
) {
161 void **arglist
=(void **)arg
;
162 channel
*cp
=(channel
*)arglist
[0];
163 nick
*np
=(nick
*)arglist
[1];
166 regchanuser
*rcup
=NULL
;
172 /* If not registered or suspended, ignore */
173 if (!(rcp
=cp
->index
->exts
[chanservext
]) || CIsSuspended(rcp
))
178 if (cp
->users
->totalusers
> rcp
->maxusers
)
179 rcp
->maxusers
=cp
->users
->totalusers
;
180 if (cp
->users
->totalusers
> rcp
->tripusers
)
181 rcp
->tripusers
=cp
->users
->totalusers
;
183 /* If their auth is deleted, pretend they don't exist */
184 rup
=getreguserfromnick(np
);
185 if (rup
&& (rup
->status
& QUSTAT_DEAD
))
188 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
)) && CUKnown(rcup
) && cp
->users
->totalusers
>= 3)
189 rcp
->lastactive
=time(NULL
);
191 if (rcp
->lastcountersync
< (time(NULL
) - COUNTERSYNCINTERVAL
)) {
192 csdb_updatechannelcounters(rcp
);
193 rcp
->lastcountersync
=time(NULL
);
196 if (hooknum
==HOOK_CHANNEL_CREATE
) {
202 /* Check for "Q ban" */
203 if (!IsService(np
) && cs_bancheck(np
,cp
)) {
204 /* They got kicked.. */
208 /* Check for other ban lurking on channel which we are enforcing */
209 if (!IsService(np
) && CIsEnforce(rcp
) && nickbanned(np
,cp
)) {
210 localkickuser(chanservnick
,cp
,np
,"Banned.");
214 /* Check for +b chanlev flag */
215 if (!IsService(np
) && rcup
&& CUIsBanned(rcup
)) {
216 cs_banuser(NULL
, cp
->index
, np
, NULL
);
217 cs_timerfunc(cp
->index
);
221 /* Check for +k chan flag */
222 if (!IsService(np
) && CIsKnownOnly(rcp
) && !(rcup
&& CUKnown(rcup
))) {
223 if (IsInviteOnly(cp
) || (IsRegOnly(cp
) && !IsAccount(np
))) {
224 localkickuser(chanservnick
,cp
,np
,"Authorised users only.");
226 cs_banuser(NULL
, cp
->index
, np
, "Authorised users only.");
227 cs_timerfunc(cp
->index
);
233 /* They're not a registered user, so deop if it is a create */
234 if (iscreate
&& !IsService(np
)) {
237 if (CIsVoiceAll(rcp
)) {
241 if (CIsWelcome(rcp
)) {
242 dowelcome
=1; /* Send welcome message */
243 } else if (!CIsJoined(rcp
) && iscreate
) {
244 dowelcome
=2; /* Send a generic warning */
247 /* Update last use time */
248 rcup
->usetime
=getnettime();
250 /* DB update removed for efficiency..
251 * csdb_updatelastjoin(rcup); */
253 /* They are registered, let's see what to do with them */
254 if (CUIsOp(rcup
) && (CIsAutoOp(rcp
) || CUIsAutoOp(rcup
) || CUIsProtect(rcup
) || CIsProtect(rcp
)) &&
262 if (iscreate
&& !CUIsOp(rcup
) && !IsService(np
)) {
266 if (!CUIsQuiet(rcup
) && /* Not +q */
267 ((CUIsVoice(rcup
) && (CIsAutoVoice(rcp
) || CUIsAutoVoice(rcup
) ||
268 CIsProtect(rcp
) || CUIsProtect(rcup
))) || /* +[gp]v */
269 (CIsVoiceAll(rcp
)))) { /* Or voice-all chan */
274 if (CIsWelcome(rcp
) && !CUIsHideWelcome(rcup
)) {
279 /* Actually do the mode change, if any */
281 localsetmodes(chanservnick
, cp
, np
, modes
);
286 case 1: if (rcp
->welcome
)
287 chanservsendmessage(np
,"[%s] %s",cp
->index
->name
->content
, rcp
->welcome
->content
);
290 case 2: if (chanservnick
) {
291 /* Channel x is protected by y */
292 chanservstdmessage(np
,QM_PROTECTED
,cp
->index
->name
->content
,chanservnick
->nick
);
297 if (rup
&& rcup
&& CIsInfo(rcp
) && UIsInfo(rcup
->user
) && !CUIsHideInfo(rcup
) && chanservnick
) {
299 /* Chan-specific info */
300 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rcup
->info
->content
);
301 } else if (rup
->info
) {
303 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rup
->info
->content
);
308 /* cs_handlemodechange:
309 * Handle mode change on channel
312 void cs_handlemodechange(int hooknum
, void *arg
) {
313 void **arglist
=(void **)arg
;
314 channel
*cp
=(channel
*)arglist
[0];
315 int changeflags
=(int)arglist
[2];
318 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
321 if (changeflags
& MODECHANGE_MODES
)
322 rcp
->status
|= QCSTAT_MODECHECK
;
324 if (changeflags
& MODECHANGE_USERS
)
325 rcp
->status
|= QCSTAT_OPCHECK
;
327 if (changeflags
& MODECHANGE_BANS
)
328 rcp
->status
|= QCSTAT_BANCHECK
;
330 cs_timerfunc(rcp
->index
);
333 void cs_handleburst(int hooknum
, void *arg
) {
334 channel
*cp
=(channel
*)arg
;
337 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
340 /* Check everything at some future time */
341 /* If autolimit is on, make sure the limit gets reset at that point too */
342 if (CIsAutoLimit(rcp
)) {
345 cs_schedupdate(cp
->index
, 1, 5);
346 rcp
->status
|= (QCSTAT_OPCHECK
| QCSTAT_MODECHECK
| QCSTAT_BANCHECK
);
347 rcp
->lastbancheck
=0; /* Force re-check of all bans on channel */
350 /* cs_handleopchange:
351 * Handle [+-][ov] event
354 void cs_handleopchange(int hooknum
, void *arg
) {
355 void **arglist
=(void **)arg
;
356 channel
*cp
=(channel
*)arglist
[0];
360 nick
*target
=(nick
*)arglist
[2];
363 /* Check that the channel is registered and active */
364 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
367 rup
=getreguserfromnick(target
);
370 case HOOK_CHANNEL_OPPED
:
371 if (CIsBitch(rcp
) && !IsService(target
)) {
372 if (!rup
|| (rcup
=findreguseronchannel(rcp
,rup
))==NULL
|| !CUIsOp(rcup
) || CUIsDeny(rcup
))
378 * Should +b prevent extra voices?
379 * If not, should we have a seperate mode that does?
382 case HOOK_CHANNEL_DEOPPED
:
383 if (CIsProtect(rcp
)) {
384 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsOp(rcup
) && !CUIsDeny(rcup
))
389 case HOOK_CHANNEL_DEVOICED
:
390 if (CIsProtect(rcp
)) {
391 if (rcp
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsVoice(rcup
) && !CUIsQuiet(rcup
))
398 localsetmodes(chanservnick
, cp
, target
, modes
);
402 * Handle ban being added to channel
405 void cs_handlenewban(int hooknum
, void *arg
) {
406 void **arglist
=(void **)arg
;
408 channel
*cp
=(channel
*)arglist
[0];
413 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
416 if ((cbp
=cp
->bans
)==NULL
) {
417 Error("chanserv",ERR_WARNING
,"Told ban added but no bans on channel?");
421 if (CIsEnforce(rcp
)) {
422 for (i
=0;i
<cp
->users
->hashsize
;i
++) {
423 if (cp
->users
->content
[i
]!=nouser
) {
424 if ((np
=getnickbynumeric(cp
->users
->content
[i
]))==NULL
) {
425 Error("chanserv",ERR_WARNING
,"Found user on channel %s who doesn't exist!",cp
->index
->name
->content
);
428 if (!IsService(np
) && nickmatchban(np
,cbp
)) {
429 localkickuser(chanservnick
,cp
,np
,"Banned.");
436 /* cs_handletopicchange:
437 * Handle topic change on channel
440 void cs_handletopicchange(int hooknum
, void *arg
) {
441 void **arglist
=(void **)arg
;
442 channel
*cp
=(channel
*)arglist
[0];
445 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
448 if (CIsForceTopic(rcp
)) {
450 /* Forced topic: change it back */
451 localsettopic(chanservnick
, cp
, rcp
->topic
->content
);
453 } else if (CIsTopicSave(rcp
)) {
455 freesstring(rcp
->topic
);
458 rcp
->topic
=getsstring(cp
->topic
->content
,TOPICLEN
);
462 csdb_updatetopic(rcp
);