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"
23 hchannel
*hchannel_add(const char *cname
)
28 cp
= findchannel((char*)cname
);
31 localcreatechannel(helpmodnick
, (char*)cname
);
32 cp
= findchannel((char*)cname
);
36 localjoinchannel(helpmodnick
, cp
);
37 localgetops(helpmodnick
, cp
);
40 hchan
= (hchannel
*)malloc(sizeof(hchannel
));
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
;
49 hchan
->report_to
= NULL
;
52 hchan
->jf_control
= time(NULL
);
53 hchan
->lc_profile
= NULL
;
56 hchan
->htickets
= NULL
;
57 hchan
->ticket_message
= NULL
;
59 hchan
->last_activity
= time(NULL
);
60 hchan
->last_staff_activity
= time(NULL
);
61 hchan
->stats
= get_hstat_channel();
63 hchan
->next
= hchannels
;
71 for (i
=0;i
< hchan
->real_channel
->users
->hashsize
;i
++)
73 nck
= getnickbynumeric(hchan
->real_channel
->users
->content
[i
]);
74 if (!nck
) /* it's a hash, not an array */
77 if ((husr
= huser_get(nck
)) == NULL
)
78 husr
= huser_add(nck
);
80 tmp
= huser_add_channel(husr
, hchan
);
81 hchannel_add_user(hchan
, husr
);
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
;
92 int hchannel_del(hchannel
*hchan
)
94 hchannel
*tmp
, **ptr
= &hchannels
;
96 for (;*ptr
;ptr
= &(*ptr
)->next
)
100 assert(*ptr
!= NULL
);
104 hcensor_del_all(&(hchan
->censor
));
105 hterm_del_all(&hchan
->channel_hterms
);
106 htopic_del_all(&hchan
->topic
);
107 hstat_del_channel(hchan
);
110 while (hchan
->htickets
)
111 hticket_del(hchan
->htickets
, hchan
);
113 localpartchannel(helpmodnick
, hchan
->real_channel
);
122 int hchannel_authority(hchannel
*hchan
, struct huser_struct
*husr
)
124 if ((hchan
->flags
& H_OPER_ONLY
) && (huser_get_level(husr
) < H_OPER
))
129 hchannel
*hchannel_get_by_name(const char *cname
)
131 hchannel
*tmp
= hchannels
;
132 for (;tmp
;tmp
=tmp
->next
)
133 if (!ircd_strcmp(cname
, tmp
->real_channel
->index
->name
->content
))
138 hchannel
*hchannel_get_by_channel(channel
*chan
)
146 for (;tmp
;tmp
=tmp
->next
)
147 if (tmp
->real_channel
== chan
)
152 const char *hchannel_get_name(hchannel
*hchan
)
154 return hchan
->real_channel
->index
->name
->content
;
157 void hchannel_del_all(void)
160 hchannel_del(hchannels
);
163 hchannel_user
*hchannel_on_channel(hchannel
*hchan
, struct huser_struct
*husr
)
165 hchannel_user
*ptr
= hchan
->channel_users
;
166 for (;ptr
;ptr
= ptr
->next
)
167 if (ptr
->husr
== husr
)
172 hchannel_user
*hchannel_add_user(hchannel
*hchan
, struct huser_struct
*husr
)
174 hchannel_user
**tmp
= &(hchan
->channel_users
);
175 assert(hchannel_on_channel(hchan
, husr
) == NULL
);
177 for (;*tmp
;tmp
= &(*tmp
)->next
);
179 *tmp
= (hchannel_user
*)malloc(sizeof(hchannel_user
));
181 (*tmp
)->time_joined
= time(NULL
);
184 assert(hchannel_on_channel(hchan
, husr
) != NULL
);
189 hchannel_user
*hchannel_del_user(hchannel
*hchan
, struct huser_struct
*husr
)
191 hchannel_user
**tmp
= &(hchan
->channel_users
);
192 assert(hchannel_on_channel(hchan
, husr
) != NULL
);
194 for (;*tmp
;tmp
= &(*tmp
)->next
)
195 if ((*tmp
)->husr
== husr
)
197 hchannel_user
*ptr
= (*tmp
)->next
;
201 assert(hchannel_on_channel(hchan
, husr
) == NULL
);
207 void hchannel_remove_inactive_users(void)
209 hchannel
*hchan
= hchannels
;
211 for (;hchan
;hchan
= hchan
->next
)
213 if (hchan
->flags
& H_ANTI_IDLE
&& !(hchan
->flags
& H_PASSIVE
))
215 hchannel_user
**hchanuser
= &hchan
->channel_users
;
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
)
225 if (huser_on_channel((*hchanuser
)->husr
, hchan
)->flags
& H_IDLE_WARNING
)
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
);
230 helpmod_kick(hchan
, (*hchanuser
)->husr
, "Please do not idle in %s", hchannel_get_name(hchan
));
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
;
240 hchanuser
= &(*hchanuser
)->next
;
244 /* Additionally, test if the channel has queue but no idle opers / staff */
245 if (hchan
->flags
& H_QUEUE
&& hchan
->flags
& H_QUEUE_TIMEOUT
)
248 for (tmp
= hchan
->channel_users
;tmp
;tmp
= tmp
->next
)
249 if (huser_get_level(tmp
->husr
) >= H_TRIAL
)
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
))
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
);
266 void hchannel_report(void)
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
))
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
);
279 if (hchan
->flags
& H_QUEUE
)
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
)));
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");
289 void hchannel_set_topic(hchannel
*hchan
)
291 if (hchan
->flags
& H_HANDLE_TOPIC
)
292 helpmod_set_topic(hchan
, htopic_construct(hchan
->topic
));
295 void hchannels_match_accounts(void)
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
));
305 int hchannels_on_queue(huser
*husr
)
307 huser_channel
*huserchan
= husr
->hchannels
;
308 for (;huserchan
;huserchan
= huserchan
->next
)
309 if (on_queue(husr
, huserchan
))
314 int hchannels_on_desk(struct huser_struct
* husr
)
316 huser_channel
*huserchan
= husr
->hchannels
;
317 for (;huserchan
;huserchan
= huserchan
->next
)
318 if (on_desk(husr
, huserchan
))
323 void hchannels_dnmo(struct huser_struct
*husr
)
325 hchannel
*hchan
= hchannels
;
326 for (;hchan
;hchan
= hchan
->next
)
328 huser_channel
*huserchan
= huser_on_channel(husr
, hchan
);
329 /*if (on_queue(husr, huserchan) || on_desk(husr, huserchan))*/
330 if (huserchan
!= NULL
)
332 hchannel_user
*tmp
= NULL
, **hchanuser
= &hchan
->channel_users
;
333 for (;*hchanuser
;hchanuser
= &(*hchanuser
)->next
)
334 if ((*hchanuser
)->husr
== husr
)
337 *hchanuser
= (*hchanuser
)->next
;
342 (*hchanuser
)->next
= NULL
;
343 if (on_desk(husr
, huserchan
))
345 helpmod_channick_modes(husr
, hchan
, MC_DEVOICE
, HLAZY
);
346 huserchan
->flags
&= ~HQUEUE_DONE
;
352 int hchannel_count_users(hchannel
*hchan
, hlevel lvl
)
355 hchannel_user
*hchanuser
= hchan
->channel_users
;
356 for (;hchanuser
;hchanuser
= hchanuser
->next
)
359 else if (huser_get_level(hchanuser
->husr
) == lvl
)
364 int hchannel_count_queue(hchannel
*hchan
)
367 hchannel_user
*hchanuser
= hchan
->channel_users
;
368 for (;hchanuser
;hchanuser
= hchanuser
->next
)
370 if (on_queue(hchanuser
->husr
, huser_on_channel(hchanuser
->husr
, hchan
)))
376 int hchannel_is_valid(hchannel
*hchan
)
378 hchannel
*ptr
= hchannels
;
379 for (;ptr
;ptr
= ptr
->next
)
385 void hchannel_mode_check(hchannel
*hchan
)
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);
397 void hchannel_conf_change(hchannel
*hchan
, int old_flags
)
402 for (i
=0;i
<HCHANNEL_CONF_COUNT
;i
++)
404 if ((hchan
->flags
^ old_flags
) & (1 << i
))
406 change
= (hchan
->flags
& (1 << i
))?H_ON
:H_OFF
;
410 hchannel_mode_check(hchan
);
412 helpmod_message_channel(hchan
, "Channel queue has been activated, all users enqueued");
414 helpmod_message_channel(hchan
, "Channel queue has been deactivated");
418 hchannel_mode_check(hchan
);
425 int hchannel_count(void)
427 hchannel
*hchan
= hchannels
;
429 for (;hchan
;hchan
= hchan
->next
)
434 void hchannel_activate_join_flood(hchannel
*hchan
)
436 hchannel_user
**hchanuser
= &hchan
->channel_users
;
437 helpmod_simple_modes(hchan
, CHANMODE_REGONLY
, 0, 1);
439 /* clean the channel of the already joined clients */
441 if (((*hchanuser
)->time_joined
> (time(NULL
) - 5)) && huser_get_level((*hchanuser
)->husr
) < H_STAFF
)
442 helpmod_kick(hchan
, (*hchanuser
)->husr
, "Join flood");
444 hchanuser
= &(*hchanuser
)->next
;
446 hchan
->flags
|= H_JOIN_FLOOD
;
448 scheduleoneshot(time(NULL
) + 60, &hchannel_deactivate_join_flood
, NULL
);
451 /* goes to schedule */
452 void hchannel_deactivate_join_flood()
454 hchannel
*hchan
= hchannels
;
455 for (;hchan
;hchan
= hchan
->next
)
456 if (hchan
->flags
& H_JOIN_FLOOD
)
458 helpmod_simple_modes(hchan
, 0, CHANMODE_REGONLY
, 1);
459 hchan
->flags
&= ~H_JOIN_FLOOD
;
463 const char *hchannel_get_state(hchannel
* hchan
, int mask
)
465 if (hchan
->flags
& mask
)
471 int hchannel_highlight_detection(hchannel
*hchan
, const char *message
)
473 char buffer
[512], *buffer_ptr
= buffer
, *ptr
= buffer
;
476 strcpy(buffer
, message
);
479 for (i
=0;i
<512 && buffer
[i
] != '\0';i
++)
480 if (buffer
[i
] == ',')
483 /* reset i for loop */
489 huser_channel
*tmp_huserchan
;
494 while (*buffer_ptr
&& isspace(*buffer_ptr
))
497 if (*buffer_ptr
== '@')
502 ptr
= strchr(buffer_ptr
, ' ');
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)
526 const char *hchannel_get_sname(int flag
)
528 if (flag
< 0 || flag
> HCHANNEL_CONF_COUNT
)
534 return "Passive state";
536 return "Welcome message";
538 return "JoinFlood protection";
542 return "Verbose queue (requires queue)";
544 return "Auto queue (requires queue)";
546 return "Channel status reporting";
548 return "Pattern censor";
550 return "Lamer control";
552 return "Idle user removal";
554 return "Keep channel moderated";
556 return "Keep channel invite only";
558 return "Handle channel topic";
560 return "Calculate statistic";
562 return "Remove joining trojans";
564 return "Channel commands";
566 return "Oper only channel";
568 return "Disallow bold, underline, etc.";
570 return "Queue inactivity deactivation";
572 return "Require a ticket to join";
574 return "Send a message on ticket issue";
576 return "Excessive highlight prevention";
578 return "Error, please contact strutsi";