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