]>
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
;
169 /* If not registered or suspended, ignore */
170 if (!(rcp
=cp
->index
->exts
[chanservext
]) || CIsSuspended(rcp
))
177 if (cp
->users
->totalusers
> rcp
->maxusers
)
178 rcp
->maxusers
=cp
->users
->totalusers
;
179 if (cp
->users
->totalusers
> rcp
->tripusers
)
180 rcp
->tripusers
=cp
->users
->totalusers
;
182 /* If their auth is deleted, pretend they don't exist */
183 rup
=getreguserfromnick(np
);
184 if (rup
&& (rup
->status
& QUSTAT_DEAD
))
187 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
)) && CUKnown(rcup
) && cp
->users
->totalusers
>= 3)
188 rcp
->lastactive
=time(NULL
);
190 if (rcp
->lastcountersync
< (time(NULL
) - COUNTERSYNCINTERVAL
)) {
191 csdb_updatechannelcounters(rcp
);
192 rcp
->lastcountersync
=time(NULL
);
195 if (hooknum
==HOOK_CHANNEL_CREATE
) {
201 /* Check for "Q ban" */
202 if (!IsService(np
) && cs_bancheck(np
,cp
)) {
203 /* They got kicked.. */
207 /* Check for other ban lurking on channel which we are enforcing */
208 if (!IsService(np
) && CIsEnforce(rcp
) && nickbanned(np
,cp
)) {
209 localkickuser(chanservnick
,cp
,np
,"Banned.");
213 /* Check for +b chanlev flag */
214 if (!IsService(np
) && rcup
&& CUIsBanned(rcup
)) {
215 cs_banuser(NULL
, cip
, np
, NULL
);
220 /* Check for +k chan flag */
221 if (!IsService(np
) && CIsKnownOnly(rcp
) && !(rcup
&& CUKnown(rcup
))) {
222 if (IsInviteOnly(cp
) || (IsRegOnly(cp
) && !IsAccount(np
))) {
223 localkickuser(chanservnick
,cp
,np
,"Authorised users only.");
225 cs_banuser(NULL
, cip
, np
, "Authorised users only.");
232 /* They're not a registered user, so deop if it is a create */
233 if (iscreate
&& !IsService(np
)) {
236 if (CIsVoiceAll(rcp
)) {
240 if (CIsWelcome(rcp
)) {
241 dowelcome
=1; /* Send welcome message */
242 } else if (!CIsJoined(rcp
) && iscreate
) {
243 dowelcome
=2; /* Send a generic warning */
246 /* Update last use time */
247 rcup
->usetime
=getnettime();
249 /* DB update removed for efficiency..
250 * csdb_updatelastjoin(rcup); */
252 /* They are registered, let's see what to do with them */
253 if (CUIsOp(rcup
) && (CIsAutoOp(rcp
) || CUIsAutoOp(rcup
) || CUIsProtect(rcup
) || CIsProtect(rcp
)) &&
261 if (iscreate
&& !CUIsOp(rcup
) && !IsService(np
)) {
265 if (!CUIsQuiet(rcup
) && /* Not +q */
266 ((CUIsVoice(rcup
) && (CIsAutoVoice(rcp
) || CUIsAutoVoice(rcup
) ||
267 CIsProtect(rcp
) || CUIsProtect(rcup
))) || /* +[gp]v */
268 (CIsVoiceAll(rcp
)))) { /* Or voice-all chan */
273 if (CIsWelcome(rcp
) && !CUIsHideWelcome(rcup
)) {
278 /* Actually do the mode change, if any */
280 localsetmodes(chanservnick
, cp
, np
, modes
);
285 case 1: if (rcp
->welcome
)
286 chanservsendmessage(np
,"[%s] %s",cip
->name
->content
, rcp
->welcome
->content
);
289 case 2: if (chanservnick
) {
290 /* Channel x is protected by y */
291 chanservstdmessage(np
,QM_PROTECTED
,cip
->name
->content
,chanservnick
->nick
);
296 if (rup
&& rcup
&& CIsInfo(rcp
) && UIsInfo(rcup
->user
) && !CUIsHideInfo(rcup
) && chanservnick
) {
298 /* Chan-specific info */
299 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rcup
->info
->content
);
300 } else if (rup
->info
) {
302 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rup
->info
->content
);
307 /* cs_handlemodechange:
308 * Handle mode change on channel
311 void cs_handlemodechange(int hooknum
, void *arg
) {
312 void **arglist
=(void **)arg
;
313 channel
*cp
=(channel
*)arglist
[0];
314 int changeflags
=(int)arglist
[2];
317 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
320 if (changeflags
& MODECHANGE_MODES
)
321 rcp
->status
|= QCSTAT_MODECHECK
;
323 if (changeflags
& MODECHANGE_USERS
)
324 rcp
->status
|= QCSTAT_OPCHECK
;
326 if (changeflags
& MODECHANGE_BANS
)
327 rcp
->status
|= QCSTAT_BANCHECK
;
329 cs_timerfunc(rcp
->index
);
332 void cs_handleburst(int hooknum
, void *arg
) {
333 channel
*cp
=(channel
*)arg
;
336 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
339 /* Check everything at some future time */
340 /* If autolimit is on, make sure the limit gets reset at that point too */
341 if (CIsAutoLimit(rcp
)) {
344 cs_schedupdate(cp
->index
, 1, 5);
345 rcp
->status
|= (QCSTAT_OPCHECK
| QCSTAT_MODECHECK
| QCSTAT_BANCHECK
);
346 rcp
->lastbancheck
=0; /* Force re-check of all bans on channel */
349 /* cs_handleopchange:
350 * Handle [+-][ov] event
353 void cs_handleopchange(int hooknum
, void *arg
) {
354 void **arglist
=(void **)arg
;
355 channel
*cp
=(channel
*)arglist
[0];
359 nick
*target
=(nick
*)arglist
[2];
362 /* Check that the channel is registered and active */
363 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
366 rup
=getreguserfromnick(target
);
369 case HOOK_CHANNEL_OPPED
:
370 if (CIsBitch(rcp
) && !IsService(target
)) {
371 if (!rup
|| (rcup
=findreguseronchannel(rcp
,rup
))==NULL
|| !CUIsOp(rcup
) || CUIsDeny(rcup
))
377 * Should +b prevent extra voices?
378 * If not, should we have a seperate mode that does?
381 case HOOK_CHANNEL_DEOPPED
:
382 if (CIsProtect(rcp
)) {
383 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsOp(rcup
) && !CUIsDeny(rcup
))
388 case HOOK_CHANNEL_DEVOICED
:
389 if (CIsProtect(rcp
)) {
390 if (rcp
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsVoice(rcup
) && !CUIsQuiet(rcup
))
397 localsetmodes(chanservnick
, cp
, target
, modes
);
401 * Handle ban being added to channel
404 void cs_handlenewban(int hooknum
, void *arg
) {
405 void **arglist
=(void **)arg
;
407 channel
*cp
=(channel
*)arglist
[0];
412 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
415 if ((cbp
=cp
->bans
)==NULL
) {
416 Error("chanserv",ERR_WARNING
,"Told ban added but no bans on channel?");
420 if (CIsEnforce(rcp
)) {
421 for (i
=0;i
<cp
->users
->hashsize
;i
++) {
422 if (cp
->users
->content
[i
]!=nouser
) {
423 if ((np
=getnickbynumeric(cp
->users
->content
[i
]))==NULL
) {
424 Error("chanserv",ERR_WARNING
,"Found user on channel %s who doesn't exist!",cp
->index
->name
->content
);
427 if (!IsService(np
) && nickmatchban(np
,cbp
)) {
428 localkickuser(chanservnick
,cp
,np
,"Banned.");
435 /* cs_handletopicchange:
436 * Handle topic change on channel
439 void cs_handletopicchange(int hooknum
, void *arg
) {
440 void **arglist
=(void **)arg
;
441 channel
*cp
=(channel
*)arglist
[0];
444 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
447 if (CIsForceTopic(rcp
)) {
449 /* Forced topic: change it back */
450 localsettopic(chanservnick
, cp
, rcp
->topic
->content
);
452 } else if (CIsTopicSave(rcp
)) {
454 freesstring(rcp
->topic
);
457 rcp
->topic
=getsstring(cp
->topic
->content
,TOPICLEN
);
461 csdb_updatetopic(rcp
);