]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/hchannel.c
CHANSERV: fix issue where chanserv_relay doesn't wait for db to be loaded before...
[irc/quakenet/newserv.git] / helpmod2 / hchannel.c
1
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <ctype.h>
6
7 #include "hchannel.h"
8 #include "haccount.h"
9 #include "helpmod.h"
10 #include "hqueue.h"
11 #include "hgen.h"
12 #include "hchanban.h"
13 #include "hban.h"
14
15 hchannel *hchannel_add(const char *cname)
16 {
17 channel *cp;
18 hchannel *hchan;
19
20 cp = findchannel((char*)cname);
21 if (!cp)
22 {
23 localcreatechannel(helpmodnick, (char*)cname);
24 cp = findchannel((char*)cname);
25 }
26 else
27 {
28 localjoinchannel(helpmodnick, cp);
29 localgetops(helpmodnick, cp);
30 }
31
32 hchan = (hchannel*)malloc(sizeof(hchannel));
33
34 hchan->welcome[0] = '\0';
35 hchan->real_channel = cp;
36 hchan->flags = H_CHANFLAGS_DEFAULT;
37 hchan->channel_users = NULL;
38 hchan->channel_hterms = NULL;
39 hchan->max_idle = 5 * HDEF_m;
40 hchan->topic = NULL;
41 hchan->report_to = NULL;
42
43 hchan->autoqueue = 0;
44 hchan->jf_control = time(NULL);
45 hchan->lc_profile = NULL;
46 hchan->censor = NULL;
47
48 hchan->htickets = NULL;
49 hchan->ticket_message = NULL;
50
51 hchan->last_activity = time(NULL);
52 hchan->last_staff_activity = time(NULL);
53 hchan->stats = get_hstat_channel();
54
55 hchan->next = hchannels;
56 hchannels = hchan;
57
58 {
59 int i;
60 nick *nck;
61 huser *husr;
62 huser_channel *tmp;
63 for (i=0;i < hchan->real_channel->users->hashsize;i++)
64 {
65 nck = getnickbynumeric(hchan->real_channel->users->content[i]);
66 if (!nck) /* it's a hash, not an array */
67 continue;
68
69 if ((husr = huser_get(nck)) == NULL)
70 husr = huser_add(nck);
71
72 tmp = huser_add_channel(husr, hchan);
73 hchannel_add_user(hchan, husr);
74
75 if (hchan->real_channel->users->content[i] & CUMODE_OP)
76 tmp->flags |= HCUMODE_OP;
77 if (hchan->real_channel->users->content[i] & CUMODE_VOICE)
78 tmp->flags |= HCUMODE_VOICE;
79 }
80 }
81 return hchan;
82 }
83
84 int hchannel_del(hchannel *hchan)
85 {
86 hchannel *tmp, **ptr = &hchannels;
87
88 for (;*ptr;ptr = &(*ptr)->next)
89 if (*ptr == hchan)
90 break;
91
92 assert(*ptr != NULL);
93
94 tmp = hchan->next;
95
96 hcensor_del_all(&(hchan->censor));
97 hterm_del_all(&hchan->channel_hterms);
98 htopic_del_all(&hchan->topic);
99 hstat_del_channel(hchan);
100 free(hchan->stats);
101
102 while (hchan->htickets)
103 hticket_del(hchan->htickets, hchan);
104
105 localpartchannel(helpmodnick, hchan->real_channel, "Channel Removed");
106
107 free(hchan);
108
109 *ptr = tmp;
110
111 return 0;
112 }
113
114 int hchannel_authority(hchannel *hchan, struct huser_struct *husr)
115 {
116 if ((hchan->flags & H_OPER_ONLY) && (huser_get_level(husr) < H_OPER))
117 return 0;
118 return 1;
119 }
120
121 hchannel *hchannel_get_by_name(const char *cname)
122 {
123 hchannel *tmp = hchannels;
124 for (;tmp;tmp=tmp->next)
125 if (!ircd_strcmp(cname, tmp->real_channel->index->name->content))
126 return tmp;
127 return NULL;
128 }
129
130 hchannel *hchannel_get_by_channel(channel *chan)
131 {
132 hchannel *tmp;
133
134 if (chan == NULL)
135 return NULL;
136
137 tmp = hchannels;
138 for (;tmp;tmp=tmp->next)
139 if (tmp->real_channel == chan)
140 return tmp;
141 return NULL;
142 }
143
144 const char *hchannel_get_name(hchannel *hchan)
145 {
146 return hchan->real_channel->index->name->content;
147 }
148
149 void hchannel_del_all(void)
150 {
151 while (hchannels)
152 hchannel_del(hchannels);
153 }
154
155 hchannel_user *hchannel_on_channel(hchannel *hchan, struct huser_struct *husr)
156 {
157 hchannel_user *ptr = hchan->channel_users;
158 for (;ptr;ptr = ptr->next)
159 if (ptr->husr == husr)
160 return ptr;
161 return NULL;
162 }
163
164 hchannel_user *hchannel_add_user(hchannel *hchan, struct huser_struct *husr)
165 {
166 hchannel_user **tmp = &(hchan->channel_users);
167 assert(hchannel_on_channel(hchan, husr) == NULL);
168
169 for (;*tmp;tmp = &(*tmp)->next);
170
171 *tmp = (hchannel_user*)malloc(sizeof(hchannel_user));
172 (*tmp)->husr = husr;
173 (*tmp)->time_joined = time(NULL);
174 (*tmp)->next = NULL;
175
176 assert(hchannel_on_channel(hchan, husr) != NULL);
177
178 return *tmp;
179 }
180
181 hchannel_user *hchannel_del_user(hchannel *hchan, struct huser_struct *husr)
182 {
183 hchannel_user **tmp = &(hchan->channel_users);
184 assert(hchannel_on_channel(hchan, husr) != NULL);
185
186 for (;*tmp;tmp = &(*tmp)->next)
187 if ((*tmp)->husr == husr)
188 {
189 hchannel_user *ptr = (*tmp)->next;
190 free(*tmp);
191 *tmp = ptr;
192
193 assert(hchannel_on_channel(hchan, husr) == NULL);
194 return NULL;
195 }
196 return NULL;
197 }
198
199 void hchannel_remove_inactive_users(void)
200 {
201 hchannel *hchan = hchannels;
202
203 for (;hchan;hchan = hchan->next)
204 {
205 if (hchan->flags & H_ANTI_IDLE && !(hchan->flags & H_PASSIVE))
206 {
207 hchannel_user **hchanuser = &hchan->channel_users;
208 while (*hchanuser)
209 {
210 if (
211 (huser_get_level((*hchanuser)->husr) == H_PEON) &&
212 (time(NULL) - huser_on_channel((*hchanuser)->husr,hchan)->last_activity >= hchan->max_idle) &&
213 !(on_queue((*hchanuser)->husr, huser_on_channel((*hchanuser)->husr, hchan))) &&
214 !IsSetHost((*hchanuser)->husr->real_user)
215 )
216 {
217 if (huser_on_channel((*hchanuser)->husr, hchan)->flags & H_IDLE_WARNING)
218 {
219 const char *banmask = hban_ban_string((*hchanuser)->husr->real_user, HBAN_HOST);
220 int bantime = 10;
221 helpmod_setban(hchan, banmask, time(NULL) + bantime * HDEF_m, MCB_ADD, HLAZY);
222
223 helpmod_kick(hchan, (*hchanuser)->husr, "Please do not idle in %s (%dmin anti-idle tempban). If you still require assistance, please try again later.", hchannel_get_name(hchan), bantime);
224 continue;
225 }
226 else
227 {
228 helpmod_reply((*hchanuser)->husr, NULL, "You are currently idle in %s. Please part the channel if you have nothing to do there", hchannel_get_name(hchan));
229 huser_on_channel((*hchanuser)->husr, hchan)->flags |= H_IDLE_WARNING;
230 }
231 }
232 /*hcommit_modes();*/
233 hchanuser = &(*hchanuser)->next;
234 }
235 hcommit_modes();
236 }
237 /* Additionally, test if the channel has queue but no idle opers / staff */
238 if (hchan->flags & H_QUEUE && hchan->flags & H_QUEUE_TIMEOUT)
239 {
240 hchannel_user *tmp;
241 for (tmp = hchan->channel_users;tmp;tmp = tmp->next)
242 if (huser_get_level(tmp->husr) >= H_TRIAL)
243 {
244 huser_channel *huserchan = huser_on_channel(tmp->husr, hchan);
245 if ((time(NULL) - huserchan->last_activity < HELPMOD_QUEUE_TIMEOUT) && (huserchan->last_activity != tmp->time_joined))
246 break;
247 }
248 if (!tmp)
249 {
250 hchan->flags &= ~H_QUEUE;
251 if (hchan->flags & H_REPORT && hchannel_is_valid(hchan->report_to))
252 helpmod_message_channel(hchan->report_to, "%s: Channel queue deactivated because of inactivity", hchannel_get_name(hchan));
253 hchannel_conf_change(hchan, hchan->flags | H_QUEUE);
254 }
255 }
256 }
257 }
258
259 void hchannel_report(void)
260 {
261 hchannel *hchan = hchannels;
262 for (;hchan;hchan = hchan->next)
263 if (hchan->flags & H_REPORT && !(hchan->flags & H_PASSIVE) && hchannel_is_valid(hchan->report_to))
264 {
265 int total = hchannel_count_users(hchan, H_ANY);
266 int peons = hchannel_count_users(hchan, H_PEON);
267 int services = hchannel_count_users(hchan, H_SERVICE);
268
269 if (peons == 0)
270 return;
271
272 if (hchan->flags & H_QUEUE)
273 {
274 int peons_queue = hchannel_count_queue(hchan);
275 helpmod_message_channel(hchan->report_to, "%s: %d user%s in queue and %d user%s currently receiving support. %d Non-user%s. Average queue time %s", hchannel_get_name(hchan), peons_queue, (peons_queue==1)?"":"s", peons - peons_queue, (peons - peons_queue == 1)?"":"s", total-peons-services, (total-peons-services == 1)?"":"s", helpmod_strtime(hqueue_average_time(hchan)));
276 }
277 else
278 helpmod_message_channel(hchan->report_to, "%s: %d user%s and %d non-user%s", hchannel_get_name(hchan), peons, (peons == 1)?"":"s", total-peons-services, (total-peons-services == 1)?"":"s");
279 }
280 }
281
282 void hchannel_set_topic(hchannel *hchan)
283 {
284 if (hchan->flags & H_HANDLE_TOPIC)
285 helpmod_set_topic(hchan, htopic_construct(hchan->topic));
286 }
287
288 void hchannels_match_accounts(void)
289 {
290 hchannel *hchan = hchannels;
291 hchannel_user *hchanuser;
292 for (;hchan;hchan = hchan->next)
293 for (hchanuser = hchan->channel_users;hchanuser;hchanuser = hchanuser->next)
294 if (hchanuser->husr->account == NULL && IsAccount(hchanuser->husr->real_user))
295 hchanuser->husr->account = haccount_get_by_name(huser_get_auth(hchanuser->husr));
296 }
297
298 int hchannels_on_queue(huser *husr)
299 {
300 huser_channel *huserchan = husr->hchannels;
301 for (;huserchan;huserchan = huserchan->next)
302 if (on_queue(husr, huserchan))
303 return 1;
304 return 0;
305 }
306
307 int hchannels_on_desk(struct huser_struct* husr)
308 {
309 huser_channel *huserchan = husr->hchannels;
310 for (;huserchan;huserchan = huserchan->next)
311 if (on_desk(husr, huserchan))
312 return 1;
313 return 0;
314 }
315
316 void hchannels_dnmo(struct huser_struct *husr)
317 {
318 hchannel *hchan = hchannels;
319 for (;hchan;hchan = hchan->next)
320 {
321 huser_channel *huserchan = huser_on_channel(husr, hchan);
322 /*if (on_queue(husr, huserchan) || on_desk(husr, huserchan))*/
323 if (huserchan != NULL)
324 {
325 hchannel_user *tmp = NULL, **hchanuser = &hchan->channel_users;
326 for (;*hchanuser;hchanuser = &(*hchanuser)->next)
327 if ((*hchanuser)->husr == husr)
328 {
329 tmp = *hchanuser;
330 *hchanuser = (*hchanuser)->next;
331 if (!*hchanuser)
332 break;
333 }
334 *hchanuser = tmp;
335 assert(*hchanuser != NULL);
336 (*hchanuser)->next = NULL;
337 if (on_desk(husr, huserchan))
338 {
339 helpmod_channick_modes(husr, hchan, MC_DEVOICE, HLAZY);
340 huserchan->flags &= ~HQUEUE_DONE;
341 }
342 }
343 }
344 }
345
346 int hchannel_count_users(hchannel *hchan, hlevel lvl)
347 {
348 int count = 0;
349 hchannel_user *hchanuser = hchan->channel_users;
350 for (;hchanuser;hchanuser = hchanuser->next)
351 if (lvl == H_ANY)
352 count++;
353 else if (huser_get_level(hchanuser->husr) == lvl)
354 count++;
355 return count;
356 }
357
358 int hchannel_count_queue(hchannel *hchan)
359 {
360 int count = 0;
361 hchannel_user *hchanuser = hchan->channel_users;
362 for (;hchanuser;hchanuser = hchanuser->next)
363 {
364 if (on_queue(hchanuser->husr, huser_on_channel(hchanuser->husr, hchan)))
365 count++;
366 }
367 return count;
368 }
369
370 int hchannel_is_valid(hchannel *hchan)
371 {
372 hchannel *ptr = hchannels;
373 for (;ptr;ptr = ptr->next)
374 if (hchan == ptr)
375 return 1;
376 return 0;
377 }
378
379 void hchannel_mode_check(hchannel *hchan)
380 {
381 if (((hchan->flags & H_MAINTAIN_M) || (hchan->flags & H_QUEUE)) && !IsModerated(hchan->real_channel))
382 helpmod_simple_modes(hchan, CHANMODE_MODERATE, 0,0);
383 else if (!((hchan->flags & H_MAINTAIN_M) || (hchan->flags & H_QUEUE)) && IsModerated(hchan->real_channel))
384 helpmod_simple_modes(hchan, 0, CHANMODE_MODERATE ,0);
385 if (hchan->flags & H_MAINTAIN_I && !IsInviteOnly(hchan->real_channel))
386 helpmod_simple_modes(hchan, CHANMODE_INVITEONLY, 0,0);
387 else if (!(hchan->flags & H_MAINTAIN_I) && IsInviteOnly(hchan->real_channel))
388 helpmod_simple_modes(hchan, 0, CHANMODE_INVITEONLY, 0);
389 }
390
391 void hchannel_conf_change(hchannel *hchan, int old_flags)
392 {
393 int i;
394 hflagchange change;
395
396 for (i=0;i<HCHANNEL_CONF_COUNT;i++)
397 {
398 if ((hchan->flags ^ old_flags) & (1 << i))
399 {
400 change = (hchan->flags & (1 << i))?H_ON:H_OFF;
401 switch (1 << i)
402 {
403 case H_QUEUE:
404 hchannel_mode_check(hchan);
405 if (change == H_ON)
406 helpmod_message_channel(hchan, "Channel queue has been activated, all users enqueued");
407 else
408 helpmod_message_channel(hchan, "Channel queue has been deactivated");
409 break;
410 case H_MAINTAIN_I:
411 case H_MAINTAIN_M:
412 hchannel_mode_check(hchan);
413 break;
414 }
415 }
416 }
417 }
418
419 int hchannel_count(void)
420 {
421 hchannel *hchan = hchannels;
422 int count = 0;
423 for (;hchan;hchan = hchan->next)
424 count++;
425 return count;
426 }
427
428 void hchannel_activate_join_flood(hchannel *hchan)
429 {
430 hchannel_user **hchanuser = &hchan->channel_users;
431 helpmod_simple_modes(hchan, CHANMODE_REGONLY, 0, 1);
432
433 /* clean the channel of the already joined clients */
434 while (*hchanuser)
435 if (((*hchanuser)->time_joined > (time(NULL) - 5)) && huser_get_level((*hchanuser)->husr) < H_STAFF)
436 helpmod_kick(hchan, (*hchanuser)->husr, "Join flood");
437 else
438 hchanuser = &(*hchanuser)->next;
439
440 hchan->flags |= H_JOIN_FLOOD;
441
442 scheduleoneshot(time(NULL) + 60, &hchannel_deactivate_join_flood, NULL);
443 }
444
445 /* goes to schedule */
446 void hchannel_deactivate_join_flood()
447 {
448 hchannel *hchan = hchannels;
449 for (;hchan;hchan = hchan->next)
450 if (hchan->flags & H_JOIN_FLOOD)
451 {
452 helpmod_simple_modes(hchan, 0, CHANMODE_REGONLY, 1);
453 hchan->flags &= ~H_JOIN_FLOOD;
454 }
455 }
456
457 const char *hchannel_get_state(hchannel* hchan, int mask)
458 {
459 if (hchan->flags & mask)
460 return "Yes";
461 else
462 return "No";
463 }
464
465 int hchannel_highlight_detection(hchannel *hchan, const char *message)
466 {
467 char buffer[512], *buffer_ptr = buffer, *ptr = buffer;
468 int i, matches = 0;
469
470 strcpy(buffer, message);
471
472 /* remove commas */
473 for (i=0;i<512 && buffer[i] != '\0';i++)
474 if (buffer[i] == ',')
475 buffer[i] = ' ';
476
477 /* reset i for loop */
478 i = 0;
479 do
480 {
481 nick *tmp;
482 huser *tmp_huser;
483 huser_channel *tmp_huserchan;
484
485 if (i++ > 6)
486 break;
487
488 while (*buffer_ptr && isspace(*buffer_ptr))
489 buffer_ptr++;
490
491 if (*buffer_ptr == '@')
492 buffer_ptr++;
493
494 if (*buffer_ptr)
495 {
496 ptr = strchr(buffer_ptr, ' ');
497 if (ptr)
498 {
499 *ptr = '\0';
500 ptr++;
501 }
502 if ((tmp = getnickbynick(buffer_ptr)))
503 if ((tmp_huser = huser_get(tmp)))
504 if ((tmp_huserchan = huser_on_channel(tmp_huser, hchan)))
505 if ((tmp_huserchan->flags & HCUMODE_OP) && strlen(huser_get_nick(tmp_huser)) > 1)
506 matches++;
507 }
508 if (ptr == NULL)
509 break;
510 else
511 buffer_ptr = ptr;
512 } while (*ptr);
513
514 if (matches > 2)
515 return 1;
516 else
517 return 0;
518 }
519
520 const char *hchannel_get_sname(int flag)
521 {
522 if (flag < 0 || flag > HCHANNEL_CONF_COUNT)
523 return NULL;
524
525 switch (flag)
526 {
527 case 0:
528 return "Passive state";
529 case 1:
530 return "Welcome message";
531 case 2:
532 return "JoinFlood protection";
533 case 3:
534 return "Queue";
535 case 4:
536 return "Verbose queue (requires queue)";
537 case 5:
538 return "Auto queue (requires queue)";
539 case 6:
540 return "Channel status reporting";
541 case 7:
542 return "Pattern censor";
543 case 8:
544 return "Lamer control";
545 case 9:
546 return "Idle user removal";
547 case 10:
548 return "Keep channel moderated";
549 case 11:
550 return "Keep channel invite only";
551 case 12:
552 return "Handle channel topic";
553 case 13:
554 return "Calculate statistic";
555 case 14:
556 return "Remove joining trojans";
557 case 15:
558 return "Channel commands";
559 case 16:
560 return "Oper only channel";
561 case 17:
562 return "Disallow bold, underline, etc.";
563 case 18:
564 return "Queue inactivity deactivation";
565 case 19:
566 return "Require a ticket to join";
567 case 20:
568 return "Send a message on ticket issue";
569 case 21:
570 return "Excessive highlight prevention";
571 default:
572 return "Error, please contact strutsi";
573 }
574 }