]>
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
) {
37 if ((rup
=getreguserfromnick(np
))) {
38 /* Clean up if this is the last user. auth->usercount is decremented
39 * AFTER the hook is sent... */
40 if ((rup
->status
& QUSTAT_DEAD
) && (np
->auth
->usercount
==1)) {
45 if (getactiveuserfromnick(np
))
46 freeactiveuser(getactiveuserfromnick(np
));
50 * cs_handlenewchannel:
51 * This is for the HOOK_CHANNEL_NEWCHANNEL message.
52 * A new channel has just been created on the network, associate
53 * with the registered channel (if one exists) unless it's suspended.
56 void cs_handlenewchannel(int hooknum
, void *arg
) {
57 channel
*cp
=(channel
*)arg
;
60 /* Get the registered channel */
61 if ((rcp
=(regchan
*)cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
64 /* chanservjoinchan() will deal with joining the channel and/or setting the timestamp */
67 /* Make sure the right modes are set/cleared */
68 cs_checkchanmodes(cp
);
70 /* Start the timer rolling */
71 cs_timerfunc(cp
->index
);
73 /* If topicsave or forcetopic is set, update the topic */
74 if (CIsForceTopic(rcp
) || CIsTopicSave(rcp
)) {
75 localsettopic(chanservnick
, cp
, (rcp
->topic
) ? rcp
->topic
->content
: "");
79 void cs_handlechanlostuser(int hooknum
, void *arg
) {
80 void **args
=(void **)arg
;
84 if (!(rcp
=cp
->index
->exts
[chanservext
]) || CIsSuspended(rcp
) || !chanservnick
||
85 (chanservnick
==args
[1]))
91 if (cp
->users
->totalusers
==2 &&
92 getnumerichandlefromchanhash(cp
->users
, chanservnick
->numeric
)) {
93 /* OK, Q is on the channel and not the one leaving.. */
94 rcp
->lastpart
=time(NULL
);
95 cs_schedupdate(cp
->index
, 1, 5);
101 * cs_handlelostchannel:
102 * This is for the HOOK_CHANNEL_LOSTCHANNEL message.
103 * A channel has just disappeared, clear our association with it.
106 void cs_handlelostchannel(int hooknum
, void *arg
) {
107 /* channel *cp=(channel *)arg; */
109 /* Do we actually need to do anything here? */
114 * A user joined a channel. See if we need to op/etc. them.
115 * Use this for JOIN or CREATE.
118 void cs_handlejoin(int hooknum
, void *arg
) {
119 void **arglist
=(void **)arg
;
120 channel
*cp
=(channel
*)arglist
[0];
121 nick
*np
=(nick
*)arglist
[1];
124 regchanuser
*rcup
=NULL
;
126 int iscreate
, isopped
;
132 /* If not registered or suspended, ignore */
133 if (!(rcp
=cp
->index
->exts
[chanservext
]) || CIsSuspended(rcp
))
140 if (cp
->users
->totalusers
> rcp
->maxusers
)
141 rcp
->maxusers
=cp
->users
->totalusers
;
142 if (cp
->users
->totalusers
> rcp
->tripusers
)
143 rcp
->tripusers
=cp
->users
->totalusers
;
145 /* If their auth is deleted, pretend they don't exist */
146 rup
=getreguserfromnick(np
);
147 if (rup
&& (rup
->status
& QUSTAT_DEAD
))
150 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
)) && CUKnown(rcup
) && cp
->users
->totalusers
>= 3)
151 rcp
->lastactive
=time(NULL
);
153 /* Update last use time */
155 rcup
->usetime
=getnettime();
157 if (rcp
->lastcountersync
< (time(NULL
) - COUNTERSYNCINTERVAL
)) {
158 csdb_updatechannelcounters(rcp
);
159 rcp
->lastcountersync
=time(NULL
);
162 /* OK, this may be a CREATE but it's possible we have already bursted onto
163 * the channel and deopped them. So let's just check that out now.
165 * There's a distinction between "is it a create?" and "are they opped
166 * already?", since we need to send the generic "This is a Q9 channel"
167 * message on create even if we already deopped them. */
168 if (hooknum
==HOOK_CHANNEL_CREATE
) {
170 if ((lp
=getnumerichandlefromchanhash(cp
->users
, np
->numeric
)) && (*lp
& CUMODE_OP
))
178 /* Various things that can ban the user on join. Don't apply these to anyone
179 * with one of +k, +X, +o */
180 if (!IsService(np
) && !IsOper(np
) && !IsXOper(np
)) {
181 /* Check for "Q ban" */
182 if (cs_bancheck(np
,cp
)) {
183 /* They got kicked.. */
187 /* Check for other ban lurking on channel which we are enforcing */
188 if (CIsEnforce(rcp
) && nickbanned(np
,cp
,1)) {
189 localkickuser(chanservnick
,cp
,np
,"Banned.");
193 /* Check for +b chanlev flag */
194 if (rcup
&& CUIsBanned(rcup
)) {
195 cs_banuser(NULL
, cip
, np
, NULL
);
200 /* Check for +k chan flag */
201 if (CIsKnownOnly(rcp
) && !(rcup
&& CUKnown(rcup
))) {
202 /* Don't ban if they are already "visibly" banned for some reason. */
203 if (IsInviteOnly(cp
) || (IsRegOnly(cp
) && !IsAccount(np
))) {
204 localkickuser(chanservnick
,cp
,np
,"Authorised users only.");
206 cs_banuser(NULL
, cip
, np
, "Authorised users only.");
214 /* They're not a registered user, so deop if it is a create */
215 if (isopped
&& !IsService(np
)) {
218 if (CIsVoiceAll(rcp
)) {
222 if (CIsWelcome(rcp
)) {
223 dowelcome
=1; /* Send welcome message */
224 } else if (!CIsJoined(rcp
) && iscreate
) {
225 dowelcome
=2; /* Send a generic warning */
229 /* DB update removed for efficiency..
230 * csdb_updatelastjoin(rcup); */
232 /* They are registered, let's see what to do with them */
233 if (CUIsOp(rcup
) && (CIsAutoOp(rcp
) || CUIsAutoOp(rcup
) || CUIsProtect(rcup
) || CIsProtect(rcp
)) &&
238 cs_logchanop(rcp
, np
->nick
, rup
);
241 /* Not auto op; deop them if they are opped and are not allowed them */
242 if (isopped
&& !CUHasOpPriv(rcup
) && !IsService(np
)) {
246 if (!CUIsQuiet(rcup
) && /* Not +q */
247 ((CUIsVoice(rcup
) && (CIsAutoVoice(rcp
) || CUIsAutoVoice(rcup
) ||
248 CIsProtect(rcp
) || CUIsProtect(rcup
))) || /* +[gp]v */
249 (CIsVoiceAll(rcp
)))) { /* Or voice-all chan */
254 if (CIsWelcome(rcp
) && !CUIsHideWelcome(rcup
)) {
259 /* Actually do the mode change, if any */
261 localsetmodes(chanservnick
, cp
, np
, modes
);
266 case 1: if (rcp
->welcome
)
267 chanservsendmessage(np
,"[%s] %s",cip
->name
->content
, rcp
->welcome
->content
);
270 case 2: if (chanservnick
) {
271 /* Channel x is protected by y */
272 chanservstdmessage(np
,QM_PROTECTED
,cip
->name
->content
,chanservnick
->nick
);
277 /* Display infoline if... (deep breath) user is registered, known on channel,
278 * user,channel,chanlev all +i and user,channel,chanlev all -s AND Q online */
280 CIsInfo(rcp
) && UIsInfo(rcup
->user
) && CUIsInfo(rcup
) &&
281 !CIsNoInfo(rcp
) && !UIsNoInfo(rcup
->user
) && !CUIsNoInfo(rcup
) && chanservnick
) {
282 if (rcup
->info
&& *(rcup
->info
->content
)) {
283 /* Chan-specific info */
284 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rcup
->info
->content
);
285 } else if (rup
->info
&& *(rup
->info
->content
)) {
287 sendmessagetochannel(chanservnick
, cp
, "[%s] %s",np
->nick
, rup
->info
->content
);
292 /* cs_handlemodechange:
293 * Handle mode change on channel
296 void cs_handlemodechange(int hooknum
, void *arg
) {
297 void **arglist
=(void **)arg
;
298 channel
*cp
=(channel
*)arglist
[0];
299 long changeflags
=(long)arglist
[2];
302 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
305 if (changeflags
& MODECHANGE_MODES
)
306 rcp
->status
|= QCSTAT_MODECHECK
;
308 if (changeflags
& MODECHANGE_USERS
)
309 rcp
->status
|= QCSTAT_OPCHECK
;
311 if (changeflags
& MODECHANGE_BANS
)
312 rcp
->status
|= QCSTAT_BANCHECK
;
314 cs_timerfunc(rcp
->index
);
317 void cs_handleburst(int hooknum
, void *arg
) {
318 channel
*cp
=(channel
*)arg
;
321 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
324 /* Check everything at some future time */
325 /* If autolimit is on, make sure the limit gets reset at that point too */
326 if (CIsAutoLimit(rcp
)) {
329 cs_schedupdate(cp
->index
, 1, 5);
330 rcp
->status
|= (QCSTAT_OPCHECK
| QCSTAT_MODECHECK
| QCSTAT_BANCHECK
);
331 rcp
->lastbancheck
=0; /* Force re-check of all bans on channel */
334 /* cs_handleopchange:
335 * Handle [+-][ov] event
338 void cs_handleopchange(int hooknum
, void *arg
) {
339 void **arglist
=(void **)arg
;
340 channel
*cp
=(channel
*)arglist
[0];
344 nick
*target
=(nick
*)arglist
[2];
347 /* Check that the channel is registered and active */
348 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
351 rup
=getreguserfromnick(target
);
354 case HOOK_CHANNEL_OPPED
:
355 if (CIsBitch(rcp
) && !IsService(target
)) {
356 if (!rup
|| (rcup
=findreguseronchannel(rcp
,rup
))==NULL
|| !CUIsOp(rcup
) || CUIsDeny(rcup
))
362 * Should +b prevent extra voices?
363 * If not, should we have a seperate mode that does?
366 case HOOK_CHANNEL_DEOPPED
:
367 if (CIsProtect(rcp
)) {
368 if (rup
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsOp(rcup
) && !CUIsDeny(rcup
))
373 case HOOK_CHANNEL_DEVOICED
:
374 if (CIsProtect(rcp
)) {
375 if (rcp
&& (rcup
=findreguseronchannel(rcp
,rup
))!=NULL
&& CUIsVoice(rcup
) && !CUIsQuiet(rcup
))
382 localsetmodes(chanservnick
, cp
, target
, modes
);
386 * Handle ban being added to channel
389 void cs_handlenewban(int hooknum
, void *arg
) {
390 void **arglist
=(void **)arg
;
392 channel
*cp
=(channel
*)arglist
[0];
397 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
400 if ((cbp
=cp
->bans
)==NULL
) {
401 Error("chanserv",ERR_WARNING
,"Told ban added but no bans on channel?");
405 if (CIsEnforce(rcp
)) {
406 for (i
=0;i
<cp
->users
->hashsize
;i
++) {
407 if (cp
->users
->content
[i
]!=nouser
) {
408 if ((np
=getnickbynumeric(cp
->users
->content
[i
]))==NULL
) {
409 Error("chanserv",ERR_WARNING
,"Found user on channel %s who doesn't exist!",cp
->index
->name
->content
);
412 if (!IsService(np
) && nickmatchban(np
,cbp
,1)) {
413 localkickuser(chanservnick
,cp
,np
,"Banned.");
420 /* cs_handletopicchange:
421 * Handle topic change on channel
424 void cs_handletopicchange(int hooknum
, void *arg
) {
425 void **arglist
=(void **)arg
;
426 channel
*cp
=(channel
*)arglist
[0];
429 if ((rcp
=cp
->index
->exts
[chanservext
])==NULL
|| CIsSuspended(rcp
))
432 if (CIsForceTopic(rcp
)) {
433 /* Forced topic: change it back even if blank */
434 localsettopic(chanservnick
, cp
, (rcp
->topic
)?rcp
->topic
->content
:"");
435 } else if (CIsTopicSave(rcp
)) {
437 freesstring(rcp
->topic
);
440 rcp
->topic
=getsstring(cp
->topic
->content
,TOPICLEN
);
444 csdb_updatetopic(rcp
);