]> jfr.im git - irc/quakenet/newserv.git/blame - helpmod2/hchannel.c
Fix AC message.
[irc/quakenet/newserv.git] / helpmod2 / hchannel.c
CommitLineData
c86edd1d
Q
1
2#include <stdlib.h>
3#include <assert.h>
135d6084 4#include <string.h>
5#include <ctype.h>
c86edd1d 6
c86edd1d
Q
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
15hchannel *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;
9af95c3d 49 hchan->ticket_message = NULL;
c86edd1d 50
3a839281 51 hchan->last_activity = time(NULL);
52 hchan->last_staff_activity = time(NULL);
c86edd1d
Q
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);
3a839281 71
72 tmp = huser_add_channel(husr, hchan);
c86edd1d
Q
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
84int 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
334b567e 105 localpartchannel(helpmodnick, hchan->real_channel, "Channel Removed");
c86edd1d
Q
106
107 free(hchan);
108
109 *ptr = tmp;
110
111 return 0;
112}
113
114int 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
121hchannel *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
130hchannel *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
c86edd1d
Q
144const char *hchannel_get_name(hchannel *hchan)
145{
146 return hchan->real_channel->index->name->content;
147}
148
149void hchannel_del_all(void)
150{
151 while (hchannels)
152 hchannel_del(hchannels);
153}
154
155hchannel_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
164hchannel_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
181hchannel_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
199void 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 {
ce659137 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)
c86edd1d 218 {
b808acb7 219 const char *banmask = hban_ban_string((*hchanuser)->husr->real_user, HBAN_HOST);
9af95c3d 220 helpmod_setban(hchan, banmask, time(NULL) + 10 * HDEF_m, MCB_ADD, HLAZY);
c86edd1d
Q
221
222 helpmod_kick(hchan, (*hchanuser)->husr, "Please do not idle in %s", hchannel_get_name(hchan));
223 continue;
224 }
225 else
226 {
227 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));
228 huser_on_channel((*hchanuser)->husr, hchan)->flags |= H_IDLE_WARNING;
9af95c3d 229 }
230 }
9f824c95 231 /*hcommit_modes();*/
c86edd1d 232 hchanuser = &(*hchanuser)->next;
9f824c95 233 }
234 hcommit_modes();
c86edd1d
Q
235 }
236 /* Additionally, test if the channel has queue but no idle opers / staff */
237 if (hchan->flags & H_QUEUE && hchan->flags & H_QUEUE_TIMEOUT)
238 {
239 hchannel_user *tmp;
240 for (tmp = hchan->channel_users;tmp;tmp = tmp->next)
052247fa 241 if (huser_get_level(tmp->husr) >= H_TRIAL)
c86edd1d
Q
242 {
243 huser_channel *huserchan = huser_on_channel(tmp->husr, hchan);
244 if ((time(NULL) - huserchan->last_activity < HELPMOD_QUEUE_TIMEOUT) && (huserchan->last_activity != tmp->time_joined))
245 break;
246 }
247 if (!tmp)
248 {
249 hchan->flags &= ~H_QUEUE;
250 if (hchan->flags & H_REPORT && hchannel_is_valid(hchan->report_to))
251 helpmod_message_channel(hchan->report_to, "%s: Channel queue deactivated because of inactivity", hchannel_get_name(hchan));
252 hchannel_conf_change(hchan, hchan->flags | H_QUEUE);
253 }
254 }
255 }
256}
257
258void hchannel_report(void)
259{
260 hchannel *hchan = hchannels;
261 for (;hchan;hchan = hchan->next)
262 if (hchan->flags & H_REPORT && !(hchan->flags & H_PASSIVE) && hchannel_is_valid(hchan->report_to))
263 {
264 int total = hchannel_count_users(hchan, H_ANY);
265 int peons = hchannel_count_users(hchan, H_PEON);
266 int services = hchannel_count_users(hchan, H_SERVICE);
267
268 if (peons == 0)
269 return;
270
271 if (hchan->flags & H_QUEUE)
272 {
273 int peons_queue = hchannel_count_queue(hchan);
274 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)));
275 }
276 else
277 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");
278 }
279}
280
281void hchannel_set_topic(hchannel *hchan)
282{
283 if (hchan->flags & H_HANDLE_TOPIC)
284 helpmod_set_topic(hchan, htopic_construct(hchan->topic));
285}
286
287void hchannels_match_accounts(void)
288{
289 hchannel *hchan = hchannels;
290 hchannel_user *hchanuser;
291 for (;hchan;hchan = hchan->next)
292 for (hchanuser = hchan->channel_users;hchanuser;hchanuser = hchanuser->next)
293 if (hchanuser->husr->account == NULL && IsAccount(hchanuser->husr->real_user))
3a839281 294 hchanuser->husr->account = haccount_get_by_name(huser_get_auth(hchanuser->husr));
c86edd1d
Q
295}
296
297int hchannels_on_queue(huser *husr)
298{
299 huser_channel *huserchan = husr->hchannels;
300 for (;huserchan;huserchan = huserchan->next)
301 if (on_queue(husr, huserchan))
302 return 1;
303 return 0;
304}
305
306int hchannels_on_desk(struct huser_struct* husr)
307{
308 huser_channel *huserchan = husr->hchannels;
309 for (;huserchan;huserchan = huserchan->next)
310 if (on_desk(husr, huserchan))
311 return 1;
312 return 0;
313}
314
315void hchannels_dnmo(struct huser_struct *husr)
316{
317 hchannel *hchan = hchannels;
318 for (;hchan;hchan = hchan->next)
319 {
320 huser_channel *huserchan = huser_on_channel(husr, hchan);
321 /*if (on_queue(husr, huserchan) || on_desk(husr, huserchan))*/
322 if (huserchan != NULL)
323 {
f011b15a 324 hchannel_user *tmp = NULL, **hchanuser = &hchan->channel_users;
c86edd1d
Q
325 for (;*hchanuser;hchanuser = &(*hchanuser)->next)
326 if ((*hchanuser)->husr == husr)
327 {
328 tmp = *hchanuser;
329 *hchanuser = (*hchanuser)->next;
330 if (!*hchanuser)
331 break;
332 }
333 *hchanuser = tmp;
334 (*hchanuser)->next = NULL;
335 if (on_desk(husr, huserchan))
336 {
337 helpmod_channick_modes(husr, hchan, MC_DEVOICE, HLAZY);
338 huserchan->flags &= ~HQUEUE_DONE;
339 }
340 }
341 }
342}
343
344int hchannel_count_users(hchannel *hchan, hlevel lvl)
345{
346 int count = 0;
347 hchannel_user *hchanuser = hchan->channel_users;
348 for (;hchanuser;hchanuser = hchanuser->next)
349 if (lvl == H_ANY)
350 count++;
351 else if (huser_get_level(hchanuser->husr) == lvl)
352 count++;
353 return count;
354}
355
356int hchannel_count_queue(hchannel *hchan)
357{
358 int count = 0;
359 hchannel_user *hchanuser = hchan->channel_users;
360 for (;hchanuser;hchanuser = hchanuser->next)
361 {
362 if (on_queue(hchanuser->husr, huser_on_channel(hchanuser->husr, hchan)))
363 count++;
364 }
365 return count;
366}
367
368int hchannel_is_valid(hchannel *hchan)
369{
370 hchannel *ptr = hchannels;
371 for (;ptr;ptr = ptr->next)
372 if (hchan == ptr)
373 return 1;
374 return 0;
375}
376
377void hchannel_mode_check(hchannel *hchan)
378{
379 if (((hchan->flags & H_MAINTAIN_M) || (hchan->flags & H_QUEUE)) && !IsModerated(hchan->real_channel))
380 helpmod_simple_modes(hchan, CHANMODE_MODERATE, 0,0);
381 else if (!((hchan->flags & H_MAINTAIN_M) || (hchan->flags & H_QUEUE)) && IsModerated(hchan->real_channel))
382 helpmod_simple_modes(hchan, 0, CHANMODE_MODERATE ,0);
383 if (hchan->flags & H_MAINTAIN_I && !IsInviteOnly(hchan->real_channel))
384 helpmod_simple_modes(hchan, CHANMODE_INVITEONLY, 0,0);
385 else if (!(hchan->flags & H_MAINTAIN_I) && IsInviteOnly(hchan->real_channel))
386 helpmod_simple_modes(hchan, 0, CHANMODE_INVITEONLY, 0);
387}
388
389void hchannel_conf_change(hchannel *hchan, int old_flags)
390{
391 int i;
392 hflagchange change;
393
394 for (i=0;i<HCHANNEL_CONF_COUNT;i++)
395 {
396 if ((hchan->flags ^ old_flags) & (1 << i))
397 {
398 change = (hchan->flags & (1 << i))?H_ON:H_OFF;
399 switch (1 << i)
400 {
401 case H_QUEUE:
402 hchannel_mode_check(hchan);
403 if (change == H_ON)
404 helpmod_message_channel(hchan, "Channel queue has been activated, all users enqueued");
405 else
406 helpmod_message_channel(hchan, "Channel queue has been deactivated");
407 break;
408 case H_MAINTAIN_I:
409 case H_MAINTAIN_M:
410 hchannel_mode_check(hchan);
411 break;
412 }
413 }
414 }
415}
416
417int hchannel_count(void)
418{
419 hchannel *hchan = hchannels;
420 int count = 0;
421 for (;hchan;hchan = hchan->next)
422 count++;
423 return count;
424}
425
426void hchannel_activate_join_flood(hchannel *hchan)
427{
428 hchannel_user **hchanuser = &hchan->channel_users;
429 helpmod_simple_modes(hchan, CHANMODE_REGONLY, 0, 1);
430
431 /* clean the channel of the already joined clients */
432 while (*hchanuser)
433 if (((*hchanuser)->time_joined > (time(NULL) - 5)) && huser_get_level((*hchanuser)->husr) < H_STAFF)
434 helpmod_kick(hchan, (*hchanuser)->husr, "Join flood");
435 else
436 hchanuser = &(*hchanuser)->next;
437
438 hchan->flags |= H_JOIN_FLOOD;
439
440 scheduleoneshot(time(NULL) + 60, &hchannel_deactivate_join_flood, NULL);
441}
e908ecfa 442
c86edd1d
Q
443/* goes to schedule */
444void hchannel_deactivate_join_flood()
445{
446 hchannel *hchan = hchannels;
447 for (;hchan;hchan = hchan->next)
448 if (hchan->flags & H_JOIN_FLOOD)
449 {
450 helpmod_simple_modes(hchan, 0, CHANMODE_REGONLY, 1);
451 hchan->flags &= ~H_JOIN_FLOOD;
452 }
c86edd1d
Q
453}
454
3a839281 455const char *hchannel_get_state(hchannel* hchan, int mask)
456{
457 if (hchan->flags & mask)
458 return "Yes";
459 else
460 return "No";
461}
462
135d6084 463int hchannel_highlight_detection(hchannel *hchan, const char *message)
464{
465 char buffer[512], *buffer_ptr = buffer, *ptr = buffer;
052247fa 466 int i, matches = 0;
135d6084 467
468 strcpy(buffer, message);
469
052247fa
CP
470 /* remove commas */
471 for (i=0;i<512 && buffer[i] != '\0';i++)
472 if (buffer[i] == ',')
473 buffer[i] = ' ';
474
475 /* reset i for loop */
476 i = 0;
135d6084 477 do
478 {
479 nick *tmp;
480 huser *tmp_huser;
481 huser_channel *tmp_huserchan;
482
483 if (i++ > 6)
484 break;
485
9f824c95 486 while (*buffer_ptr && isspace(*buffer_ptr))
135d6084 487 buffer_ptr++;
488
9f824c95 489 if (*buffer_ptr == '@')
490 buffer_ptr++;
491
135d6084 492 if (*buffer_ptr)
493 {
494 ptr = strchr(buffer_ptr, ' ');
495 if (ptr)
496 {
497 *ptr = '\0';
498 ptr++;
499 }
500 if ((tmp = getnickbynick(buffer_ptr)))
501 if ((tmp_huser = huser_get(tmp)))
502 if ((tmp_huserchan = huser_on_channel(tmp_huser, hchan)))
503 if ((tmp_huserchan->flags & HCUMODE_OP) && strlen(huser_get_nick(tmp_huser)) > 1)
504 matches++;
505 }
506 if (ptr == NULL)
507 break;
508 else
509 buffer_ptr = ptr;
510 } while (*ptr);
511
512 if (matches > 2)
513 return 1;
514 else
515 return 0;
516}
3a839281 517
c86edd1d
Q
518const char *hchannel_get_sname(int flag)
519{
520 if (flag < 0 || flag > HCHANNEL_CONF_COUNT)
521 return NULL;
522
523 switch (flag)
524 {
525 case 0:
526 return "Passive state";
527 case 1:
528 return "Welcome message";
529 case 2:
530 return "JoinFlood protection";
531 case 3:
532 return "Queue";
533 case 4:
534 return "Verbose queue (requires queue)";
535 case 5:
536 return "Auto queue (requires queue)";
537 case 6:
538 return "Channel status reporting";
539 case 7:
540 return "Pattern censor";
541 case 8:
542 return "Lamer control";
543 case 9:
544 return "Idle user removal";
545 case 10:
546 return "Keep channel moderated";
547 case 11:
548 return "Keep channel invite only";
549 case 12:
550 return "Handle channel topic";
551 case 13:
552 return "Calculate statistic";
553 case 14:
554 return "Remove joining trojans";
555 case 15:
556 return "Channel commands";
557 case 16:
558 return "Oper only channel";
559 case 17:
560 return "Disallow bold, underline, etc.";
561 case 18:
562 return "Queue inactivity deactivation";
563 case 19:
9af95c3d 564 return "Require a ticket to join";
565 case 20:
135d6084 566 return "Send a message on ticket issue";
567 case 21:
568 return "Excessive highlight prevention";
c86edd1d 569 default:
e908ecfa 570 return "Error, please contact strutsi";
c86edd1d
Q
571 }
572}