]>
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
;
68 /* Get the registered channel */
69 if ((rcp
=(regchan
*)cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
73 * If we're supposed to be joined, join ourselves..
76 if (CIsJoined(rcp
) && (chanservnick
!=NULL
)) {
80 /* This code interacts badly with bursts.. need to fix */
83 /* We need to watch out for people sneaking into +k/i channels..
84 * This code relies on the fact that that user will already be in
85 * the channel at this point in time.. */
86 if (rcp
->forcemodes
& (CHANMODE_KEY
| CHANMODE_INVITEONLY
)) {
87 /* OK, this channel is keyed.. let's find out if the user is allowed to be here */
88 for (i
=0;i
<cp
->users
->hashsize
;i
++) {
89 if (cp
->users
->content
[i
]!=nouser
&& (np
=getnickbynumeric(cp
->users
->content
[i
]))) {
91 /* service (might even be us..) */
94 if ((rup
=getreguserfromnick(np
)) && (rcup
=findreguseronchannel(rcp
, rup
)) &&
95 CUKnown(rcup
) && !CUIsBanned(rcup
))
99 localkickuser(chanservnick
, cp
, np
, "Private channel.");
105 /* Make sure the right modes are set/cleared */
106 cs_checkchanmodes(cp
);
108 /* Start the timer rolling */
109 cs_timerfunc(cp
->index
);
111 /* If topicsave or forcetopic is set, update the topic */
112 if (CIsForceTopic(rcp
) || CIsTopicSave(rcp
)) {
113 localsettopic(chanservnick
, cp
, (rcp
->topic
) ? rcp
->topic
->content
: "");
117 void cs_handlechanlostuser(int hooknum
, void *arg
) {
118 void **args
=(void **)arg
;
122 if (!(rcp
=cp
->index
->exts
[chanservext
]) || CIsSuspended(rcp
) || !chanservnick
||
123 (chanservnick
==args
[1]))
129 if (cp
->users
->totalusers
==2 &&
130 getnumerichandlefromchanhash(cp
->users
, chanservnick
->numeric
)) {
131 /* OK, Q is on the channel and not the one leaving.. */
132 rcp
->lastpart
=time(NULL
);
133 cs_schedupdate(cp
->index
, 1, 5);
139 * cs_handlelostchannel:
140 * This is for the HOOK_CHANNEL_LOSTCHANNEL message.
141 * A channel has just disappeared, clear our association with it.
144 void cs_handlelostchannel(int hooknum
, void *arg
) {
145 /* channel *cp=(channel *)arg; */
147 /* Do we actually need to do anything here? */
152 * A user joined a channel. See if we need to op/etc. them.
153 * Use this for JOIN or CREATE.
156 void cs_handlejoin(int hooknum
, void *arg
) {
157 void **arglist
=(void **)arg
;
158 channel
*cp
=(channel
*)arglist
[0];
159 nick
*np
=(nick
*)arglist
[1];
162 regchanuser
*rcup
=NULL
;
168 /* If not registered or suspended, ignore */
169 if (!(rcp
=cp
->index
->exts
[chanservext
]) || CIsSuspended(rcp
))
174 if (cp
->users
->totalusers
> rcp
->maxusers
)
175 rcp
->maxusers
=cp
->users
->totalusers
;
176 if (cp
->users
->totalusers
> rcp
->tripusers
)
177 rcp
->tripusers
=cp
->users
->totalusers
;
179 /* If their auth is deleted, pretend they don't exist */
180 rup
=getreguserfromnick(np
);
181 if (rup
&& (rup
->status
& QUSTAT_DEAD
))
184 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
)) && CUKnown(rcup
) && cp
->users
->totalusers
>= 3)
185 rcp
->lastactive
=time(NULL
);
187 if (rcp
->lastcountersync
< (time(NULL
) - COUNTERSYNCINTERVAL
)) {
188 csdb_updatechannelcounters(rcp
);
189 rcp
->lastcountersync
=time(NULL
);
192 if (hooknum
==HOOK_CHANNEL_CREATE
) {
198 /* Check for "Q ban" */
199 if (!IsService(np
) && cs_bancheck(np
,cp
)) {
200 /* They got kicked.. */
204 /* Check for other ban lurking on channel which we are enforcing */
205 if (!IsService(np
) && CIsEnforce(rcp
) && nickbanned(np
,cp
)) {
206 localkickuser(chanservnick
,cp
,np
,"Banned.");
210 /* Check for +b chanlev flag */
211 if (!IsService(np
) && rcup
&& CUIsBanned(rcup
)) {
212 cs_banuser(NULL
, cp
->index
, np
, NULL
);
213 cs_timerfunc(cp
->index
);
217 /* Check for +k chan flag */
218 if (!IsService(np
) && CIsKnownOnly(rcp
) && !(rcup
&& CUKnown(rcup
))) {
219 if (IsInviteOnly(cp
) || (IsRegOnly(cp
) && !IsAccount(np
))) {
220 localkickuser(chanservnick
,cp
,np
,"Authorised users only.");
222 cs_banuser(NULL
, cp
->index
, np
, "Authorised users only.");
223 cs_timerfunc(cp
->index
);
229 /* They're not a registered user, so deop if it is a create */
230 if (iscreate
&& !IsService(np
)) {
233 if (CIsVoiceAll(rcp
)) {
237 if (CIsWelcome(rcp
)) {
238 dowelcome
=1; /* Send welcome message */
239 } else if (!CIsJoined(rcp
) && iscreate
) {
240 dowelcome
=2; /* Send a generic warning */
243 /* Update last use time */
244 rcup
->usetime
=getnettime();
246 /* DB update removed for efficiency..
247 * csdb_updatelastjoin(rcup); */
249 /* They are registered, let's see what to do with them */
250 if (CUIsOp(rcup
) && (CIsAutoOp(rcp
) || CUIsAutoOp(rcup
) || CUIsProtect(rcup
) || CIsProtect(rcp
)) &&
258 if (iscreate
&& !CUIsOp(rcup
) && !IsService(np
)) {
262 if (!CUIsQuiet(rcup
) && /* Not +q */
263 ((CUIsVoice(rcup
) && (CIsAutoVoice(rcp
) || CUIsAutoVoice(rcup
) ||
264 CIsProtect(rcp
) || CUIsProtect(rcup
))) || /* +[gp]v */
265 (CIsVoiceAll(rcp
)))) { /* Or voice-all chan */
270 if (CIsWelcome(rcp
) && !CUIsHideWelcome(rcup
)) {
275 /* Actually do the mode change, if any */
277 localsetmodes(chanservnick
, cp
, np
, modes
);
282 case 1: if (rcp
->welcome
)
283 chanservsendmessage(np
,"[%s] %s",cp
->index
->name
->content
, rcp
->welcome
->content
);
286 case 2: if (chanservnick
) {
287 /* Channel x is protected by y */
288 chanservstdmessage(np
,QM_PROTECTED
,cp
->index
->name
->content
,chanservnick
->nick
);
293 if (rup
&& rcup
&& CIsInfo(rcp
) && UIsInfo(rcup
->user
) && !CUIsHideInfo(rcup
) && chanservnick
) {
295 /* Chan-specific info */
296 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rcup
->info
->content
);
297 } else if (rup
->info
) {
299 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rup
->info
->content
);
304 /* cs_handlemodechange:
305 * Handle mode change on channel
308 void cs_handlemodechange(int hooknum
, void *arg
) {
309 void **arglist
=(void **)arg
;
310 channel
*cp
=(channel
*)arglist
[0];
311 int changeflags
=(int)arglist
[2];
314 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
317 if (changeflags
& MODECHANGE_MODES
)
318 rcp
->status
|= QCSTAT_MODECHECK
;
320 if (changeflags
& MODECHANGE_USERS
)
321 rcp
->status
|= QCSTAT_OPCHECK
;
323 if (changeflags
& MODECHANGE_BANS
)
324 rcp
->status
|= QCSTAT_BANCHECK
;
326 cs_timerfunc(rcp
->index
);
329 void cs_handleburst(int hooknum
, void *arg
) {
330 channel
*cp
=(channel
*)arg
;
333 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
336 /* Check everything at some future time */
337 /* If autolimit is on, make sure the limit gets reset at that point too */
338 if (CIsAutoLimit(rcp
)) {
341 cs_schedupdate(cp
->index
, 1, 5);
342 rcp
->status
|= (QCSTAT_OPCHECK
| QCSTAT_MODECHECK
| QCSTAT_BANCHECK
);
343 rcp
->lastbancheck
=0; /* Force re-check of all bans on channel */
346 /* cs_handleopchange:
347 * Handle [+-][ov] event
350 void cs_handleopchange(int hooknum
, void *arg
) {
351 void **arglist
=(void **)arg
;
352 channel
*cp
=(channel
*)arglist
[0];
356 nick
*target
=(nick
*)arglist
[2];
359 /* Check that the channel is registered and active */
360 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
363 rup
=getreguserfromnick(target
);
366 case HOOK_CHANNEL_OPPED
:
367 if (CIsBitch(rcp
) && !IsService(target
)) {
368 if (!rup
|| (rcup
=findreguseronchannel(rcp
,rup
))==NULL
|| !CUIsOp(rcup
) || CUIsDeny(rcup
))
374 * Should +b prevent extra voices?
375 * If not, should we have a seperate mode that does?
378 case HOOK_CHANNEL_DEOPPED
:
379 if (CIsProtect(rcp
)) {
380 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsOp(rcup
) && !CUIsDeny(rcup
))
385 case HOOK_CHANNEL_DEVOICED
:
386 if (CIsProtect(rcp
)) {
387 if (rcp
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsVoice(rcup
) && !CUIsQuiet(rcup
))
394 localsetmodes(chanservnick
, cp
, target
, modes
);
398 * Handle ban being added to channel
401 void cs_handlenewban(int hooknum
, void *arg
) {
402 void **arglist
=(void **)arg
;
404 channel
*cp
=(channel
*)arglist
[0];
409 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
412 if ((cbp
=cp
->bans
)==NULL
) {
413 Error("chanserv",ERR_WARNING
,"Told ban added but no bans on channel?");
417 if (CIsEnforce(rcp
)) {
418 for (i
=0;i
<cp
->users
->hashsize
;i
++) {
419 if (cp
->users
->content
[i
]!=nouser
) {
420 if ((np
=getnickbynumeric(cp
->users
->content
[i
]))==NULL
) {
421 Error("chanserv",ERR_WARNING
,"Found user on channel %s who doesn't exist!",cp
->index
->name
->content
);
424 if (!IsService(np
) && nickmatchban(np
,cbp
)) {
425 localkickuser(chanservnick
,cp
,np
,"Banned.");
432 /* cs_handletopicchange:
433 * Handle topic change on channel
436 void cs_handletopicchange(int hooknum
, void *arg
) {
437 void **arglist
=(void **)arg
;
438 channel
*cp
=(channel
*)arglist
[0];
441 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
444 if (CIsForceTopic(rcp
)) {
446 /* Forced topic: change it back */
447 localsettopic(chanservnick
, cp
, rcp
->topic
->content
);
449 } else if (CIsTopicSave(rcp
)) {
451 freesstring(rcp
->topic
);
454 rcp
->topic
=getsstring(cp
->topic
->content
,TOPICLEN
);
458 csdb_updatetopic(rcp
);