]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/hqueue.c
Merge pull request #1 from meeb/meeb
[irc/quakenet/newserv.git] / helpmod2 / hqueue.c
1 #include <assert.h>
2 #include <string.h>
3
4 #include "hqueue.h"
5 #include "hgen.h"
6 #include "hstat.h"
7 #include "huser.h"
8
9 #include "hcommands.h"
10
11 typedef struct hqueue_entry
12 {
13 huser_channel *huserchan;
14 hchannel_user *hchanuser;
15 } hqueue_entry;
16
17 static hqueue_entry *hqueue_get_next(hchannel *hchan)
18 {
19 static struct hqueue_entry qentry;
20 static hchannel *current_hchan = NULL;
21 static hchannel_user *hchanuser = NULL;
22 huser_channel *huserchan;
23
24 if (hchan != NULL)
25 {
26 hchanuser = hchan->channel_users;
27 current_hchan = hchan;
28 }
29
30 if (hchanuser == NULL)
31 return NULL;
32
33 huserchan = huser_on_channel(hchanuser->husr, current_hchan);
34
35 assert(huserchan != NULL);
36
37 qentry.huserchan = huserchan;
38 qentry.hchanuser = hchanuser;
39
40 hchanuser = hchanuser->next;
41
42 return &qentry;
43 }
44
45 static int hqueue_on_queue(hqueue_entry *qentry)
46 {
47 return on_queue(qentry->hchanuser->husr, qentry->huserchan);
48 }
49
50 static int hqueue_count_in_queue(hchannel *hchan)
51 {
52 int count;
53 hqueue_entry *tmp = hqueue_get_next(hchan);
54
55 for (count = 0;tmp;tmp = hqueue_get_next(NULL))
56 if (hqueue_on_queue(tmp))
57 count++;
58
59 return count;
60 }
61
62 static int hqueue_count_off_queue(hchannel *hchan)
63 {
64 int count;
65 hqueue_entry *tmp = hqueue_get_next(hchan);
66
67 for (count = 0;tmp;tmp = hqueue_get_next(NULL))
68 if (on_desk(tmp->hchanuser->husr, tmp->huserchan))
69 count++;
70
71 return count;
72 }
73
74 int hqueue_average_time(hchannel *hchan)
75 {
76 int count, sum = 0;
77 hqueue_entry *tmp = hqueue_get_next(hchan);
78
79 for (count = 0;tmp;tmp = hqueue_get_next(NULL))
80 if (hqueue_on_queue(tmp))
81 {
82 count++;
83 sum+=(time(NULL) - tmp->hchanuser->time_joined);
84 }
85 if (count)
86 return sum / count;
87 else
88 return 0;
89 }
90
91 void hqueue_report_positions(hchannel *hchan)
92 {
93 int count;
94 hqueue_entry *tmp = hqueue_get_next(hchan);
95
96 for (count = 1;tmp;tmp = hqueue_get_next(NULL))
97 {
98 if (hqueue_on_queue(tmp) && ((count <= 5) || !(count % 5)))
99 helpmod_reply(tmp->hchanuser->husr, hchan->real_channel, "You now have queue position #%d for channel %s", count, hchannel_get_name(hchan));
100 if (hqueue_on_queue(tmp))
101 count++;
102 }
103 }
104
105 void hqueue_advance(hchannel *hchan, huser *oper, int nadv)
106 {
107 char buffer[512];
108 int counter = nadv;
109 huser_channel *huserchan;
110
111 if (hchan == NULL) return;
112
113 hchannel_user *hchanuser = hchan->channel_users;
114
115 buffer[0] = '\0';
116
117 if (counter < 0 || counter > 25)
118 return;
119
120 if (!huser_valid(oper) || !huser_on_channel(oper, hchan) || (time(NULL) - huser_on_channel(oper,hchan)->last_activity > HELPMOD_QUEUE_TIMEOUT))
121 oper = NULL;
122
123 while (counter)
124 {
125 if (hchanuser == NULL) /* out of users */
126 {
127 if (counter == nadv)
128 {
129 helpmod_message_channel(hchan, "There are no users in the queue");
130 return;
131 }
132 else
133 break; /* we got something, print the message on channel */
134 }
135 huserchan = huser_on_channel(hchanuser->husr, hchan);
136
137 assert(huserchan != NULL);
138
139 if (huserchan->flags & HQUEUE_DONE || huser_get_level(hchanuser->husr) > H_PEON)
140 {
141 hchanuser = hchanuser->next; /* user was not in queue, proceed to next one */
142 continue;
143 }
144
145 huserchan->flags |= HQUEUE_DONE;
146
147 counter--;
148
149 strcat(buffer, huser_get_nick(hchanuser->husr));
150 strcat(buffer, " ");
151
152 if (hchan->flags & H_DO_STATS)
153 hstat_add_queue(hchan, 1);
154
155 if ((hchan->flags & H_QUEUE_SPAMMY) && (oper != NULL))
156 {
157 helpmod_reply(hchanuser->husr, hchan->real_channel, "It is now your time to state your problem. Please do so on channel %s and direct your questions to %s %s", hchannel_get_name(hchan), hlevel_title(huser_get_level(oper)), huser_get_nick(oper));
158 if (!(huser_get_account_flags(oper) & H_NOSPAM))
159 helpmod_reply(oper, hchan->real_channel, "User %s (%s@%s) is yours, he has been in queue for %s", huser_get_nick(hchanuser->husr), huser_get_ident(hchanuser->husr), huser_get_host(hchanuser->husr), helpmod_strtime(time(NULL) - hchanuser->time_joined));
160 }
161
162 helpmod_channick_modes(hchanuser->husr, hchan, MC_VOICE, HLAZY);
163 huserchan->responsible_oper = oper;
164
165 hchanuser = hchanuser->next;
166 }
167 if (oper != NULL)
168 helpmod_message_channel(hchan, "user%s %s: Please state your questions on this channel and direct them to %s %s", (nadv - counter == 1)?"":"s", buffer, hlevel_title(huser_get_level(oper)), huser_get_nick(oper));
169 else
170 helpmod_message_channel(hchan, "user%s %s: Please state your questions on this channel", (nadv - counter == 1)?"":"s", buffer);
171
172 if (hchan->flags & H_QUEUE_SPAMMY)
173 hqueue_report_positions(hchan);
174 }
175
176
177 void helpmod_queue_handler (huser *sender, channel* returntype, hchannel *hchan, int hqueue_action, char* ostr, int argc, char *argv[])
178 {
179 if (hchan == NULL)
180 {
181 helpmod_reply(sender, returntype, "Can not handle queue: Channel not defined or not found");
182 return;
183 }
184 switch (hqueue_action) /* easy ones */
185 {
186 case HQ_ON:
187 if (hchan->flags & H_QUEUE)
188 helpmod_reply(sender, returntype, "Can not activate queue: Queue is already active on channel %s", hchannel_get_name(hchan));
189 else
190 {
191 hchan->flags |= H_QUEUE;
192 helpmod_reply(sender, returntype, "Queue activated for channel %s", hchannel_get_name(hchan));
193 hchannel_conf_change(hchan, hchan->flags & ~(H_QUEUE));
194 hchan->autoqueue = 0;
195 }
196 return;
197 case HQ_OFF:
198 if (!(hchan->flags & H_QUEUE))
199 helpmod_reply(sender, returntype, "Can not deactive queue: Queue is not active on %s", hchannel_get_name(hchan));
200 else
201 {
202 hchan->flags &= ~H_QUEUE;
203 helpmod_reply(sender, returntype, "Queue deactivated for channel %s", hchannel_get_name(hchan));
204 hchannel_conf_change(hchan, hchan->flags | H_QUEUE);
205 hchan->autoqueue = 0;
206
207 { /* devoice all users of level H_PEON */
208 hchannel_user *hchanuser;
209 huser_channel *huserchan;
210 for (hchanuser = hchan->channel_users;hchanuser != NULL;hchanuser = hchanuser->next)
211 {
212 huserchan = huser_on_channel(hchanuser->husr, hchan);
213 if (huser_get_level(hchanuser->husr) == H_PEON && huserchan->flags & HCUMODE_VOICE)
214 helpmod_channick_modes(hchanuser->husr, hchan, MC_DEVOICE, HLAZY);
215 }
216 }
217
218 }
219 return;
220 }
221 if (!(hchan->flags & H_QUEUE))
222 {
223 helpmod_reply(sender, returntype, "Can not handle queue: Queue not active on channel %s", hchannel_get_name(hchan));
224 return;
225 }
226 /* now to the real deal */
227 switch (hqueue_action)
228 {
229 case HQ_DONE:
230 {
231 int i;
232 if (argc == 0)
233 {
234 helpmod_reply(sender, returntype, "Can not advance queue: User not specified");
235 return;
236 }
237 if (argc > H_CMD_MAX_ARGS)
238 argc = H_CMD_MAX_ARGS;
239
240 for (i=0;i<argc;i++)
241 {
242 huser *husr = huser_get(getnickbynick(argv[i]));
243 if (husr == NULL)
244 {
245 helpmod_reply(sender, returntype, "Can not advance queue: User %s not found", argv[i]);
246 continue;
247 }
248 helpmod_channick_modes(husr, hchan, MC_DEVOICE, HLAZY);
249 }
250
251 hqueue_handle_queue(hchan, sender);
252 }
253 return;
254 case HQ_NEXT:
255 {
256 int nnext = 1;
257 if (argc > 0)
258 {
259 if (!sscanf(argv[0], "%d", &nnext) || nnext <= 0 || nnext > 25 /* magic number */)
260 {
261 helpmod_reply(sender, returntype, "Can not advance queue: Integer [1, 25] expected");
262 return;
263 }
264 }
265 hqueue_advance(hchan, sender, nnext);
266 }
267 return;
268 case HQ_MAINTAIN:
269 {
270 int tmp;
271 if (argc == 0)
272 {
273 helpmod_reply(sender, returntype, "Autoqueue for channel %s is currently %d (%s)", hchannel_get_name(hchan), hchan->autoqueue, hchannel_get_state(hchan, H_QUEUE_MAINTAIN));
274 return;
275 }
276 if (!sscanf(argv[0], "%d", &tmp) || tmp < 0 || tmp > 25)
277 {
278 helpmod_reply(sender, returntype, "Can not set auto queue: Integer [0, 20] expected");
279 return;
280 }
281 hchan->autoqueue = tmp;
282 if (tmp == 0)
283 {
284 if (hchan->flags & H_QUEUE_MAINTAIN)
285 {
286 hchan->flags &= ~(H_QUEUE_MAINTAIN);
287 helpmod_reply(sender, returntype, "Autoqueue is now disabled for channel %s", hchannel_get_name(hchan));
288 }
289 else
290 helpmod_reply(sender, returntype, "Autoqueue is not enabled for channel %s", hchannel_get_name(hchan));
291 }
292 else if (!(hchan->flags & H_QUEUE_MAINTAIN))
293 {
294 hchan->flags |= H_QUEUE_MAINTAIN;
295 helpmod_reply(sender, returntype, "Autoqueue for channel %s activated and set to %d succesfully", hchannel_get_name(hchan), hchan->autoqueue);
296 }
297 else
298 helpmod_reply(sender, returntype, "Autoqueue for channel %s set to %d succesfully", hchannel_get_name(hchan), hchan->autoqueue);
299 hqueue_handle_queue(hchan, sender);
300 }
301 return;
302 case HQ_LIST:
303 {
304 int count = hqueue_count_in_queue(hchan);
305 hqueue_entry *hqueue = hqueue_get_next(hchan);
306
307 char buffer[512];
308 buffer[0] = '\0';
309
310 helpmod_reply(sender, returntype, "Channel %s has following users in queue (%d user%s total):", hchannel_get_name(hchan), count, (count==1)?"":"s");
311
312 for (;hqueue;hqueue = hqueue_get_next(NULL))
313 {
314 if (strlen(buffer) >= 250)
315 {
316 helpmod_reply(sender, returntype, "%s", buffer);
317 buffer[0] = '\0';
318 }
319 if (hqueue_on_queue(hqueue))
320 sprintf(buffer+strlen(buffer) /* :) */, "%s (%s@%s) [%s] ", huser_get_nick(hqueue->hchanuser->husr), huser_get_ident(hqueue->hchanuser->husr), huser_get_host(hqueue->hchanuser->husr), helpmod_strtime(time(NULL) - hqueue->hchanuser->time_joined));
321 }
322 if (buffer[0])
323 helpmod_reply(sender, returntype, "%s", buffer);
324 }
325 return;
326 case HQ_NONE: /* if no parameters are given print the summary */
327 case HQ_SUMMARY:
328 {
329 int count_on = hqueue_count_in_queue(hchan);
330 int count_off = hqueue_count_off_queue(hchan);
331 int average = hqueue_average_time(hchan);
332
333 helpmod_reply(sender, returntype, "Channel %s has %d user%s in queue, %d user%s being helped, average time in queue %s", hchannel_get_name(hchan), count_on, (count_on==1)?"":"s", count_off, (count_off==1)?"":"s", helpmod_strtime(average));
334 }
335 return;
336 case HQ_RESET:
337 {
338 hchannel_user *hchanuser = hchan->channel_users;
339 for (;hchanuser;hchanuser = hchanuser->next)
340 {
341 if (huser_get_level(hchanuser->husr) == H_PEON)
342 {
343 huser_channel *huserchan = huser_on_channel(hchanuser->husr, hchan);
344 assert (huserchan != NULL);
345 if (huserchan->flags & HCUMODE_VOICE)
346 helpmod_channick_modes(hchanuser->husr, hchan, MC_DEVOICE, HLAZY);
347 huserchan->flags &= ~(HQUEUE_DONE | H_IDLE_WARNING);
348 }
349 }
350 if (!IsModerated(hchan->real_channel))
351 helpmod_simple_modes(hchan, CHANMODE_MODERATE, 0, 0);
352 helpmod_message_channel(hchan, "Channel queue has been reset");
353 helpmod_reply(sender, returntype, "Queue for channel %s has been reset", hchannel_get_name(hchan));
354 }
355 return;
356 }
357 }
358
359 void hqueue_handle_queue(hchannel *hchan, huser *huser)
360 {
361 if ((hchan->flags & (H_QUEUE | H_QUEUE_MAINTAIN)) && hchan->autoqueue && hqueue_count_in_queue(hchan))
362 {
363 int dif = hchan->autoqueue - hqueue_count_off_queue(hchan);
364 if (dif > 0)
365 hqueue_advance(hchan, huser, dif);
366 }
367 hcommit_modes();
368 }
369
370 int hqueue_get_position(hchannel *hchan, huser *target)
371 {
372 int position;
373 hqueue_entry *hqueue = hqueue_get_next(hchan);
374
375 if (hchannel_on_channel(hchan, target) == NULL)
376 return -1;
377
378 if (!(hchan->flags & H_QUEUE))
379 return -1;
380
381 for (position = 0;hqueue;hqueue = hqueue_get_next(NULL))
382 {
383 if (hqueue_on_queue(hqueue))
384 {
385 position++;
386 if (hqueue->hchanuser->husr == target)
387 return position;
388 }
389 }
390 return -1;
391 }