]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/hqueue.c
Large reorganisation of all Makefiles, including new configure script.
[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 hchannel_user *hchanuser = hchan->channel_users;
111
112 buffer[0] = '\0';
113
114 if (counter < 0 || counter > 25)
115 return;
116
117 if (!huser_valid(oper) || !huser_on_channel(oper, hchan) || (time(NULL) - huser_on_channel(oper,hchan)->last_activity > HELPMOD_QUEUE_TIMEOUT))
118 oper = NULL;
119
120 while (counter)
121 {
122 if (hchanuser == NULL) /* out of users */
123 {
124 if (counter == nadv)
125 {
126 helpmod_message_channel(hchan, "There are no users in the queue");
127 return;
128 }
129 else
130 break; /* we got something, print the message on channel */
131 }
132 huserchan = huser_on_channel(hchanuser->husr, hchan);
133
134 assert(huserchan != NULL);
135
136 if (huserchan->flags & HQUEUE_DONE || huser_get_level(hchanuser->husr) > H_PEON)
137 {
138 hchanuser = hchanuser->next; /* user was not in queue, proceed to next one */
139 continue;
140 }
141
142 huserchan->flags |= HQUEUE_DONE;
143
144 counter--;
145
146 strcat(buffer, huser_get_nick(hchanuser->husr));
147 strcat(buffer, " ");
148
149 if (hchan->flags & H_DO_STATS)
150 hstat_add_queue(hchan, 1);
151
152 if ((hchan->flags & H_QUEUE_SPAMMY) && (oper != NULL))
153 {
154 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));
155 if (!(huser_get_account_flags(oper) & H_NOSPAM))
156 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));
157 }
158
159 helpmod_channick_modes(hchanuser->husr, hchan, MC_VOICE, HLAZY);
160 huserchan->responsible_oper = oper;
161
162 hchanuser = hchanuser->next;
163 }
164 if (oper != NULL)
165 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));
166 else
167 helpmod_message_channel(hchan, "user%s %s: Please state your questions on this channel", (nadv - counter == 1)?"":"s", buffer);
168
169 if (hchan->flags & H_QUEUE_SPAMMY)
170 hqueue_report_positions(hchan);
171 }
172
173
174 void helpmod_queue_handler (huser *sender, channel* returntype, hchannel *hchan, int hqueue_action, char* ostr, int argc, char *argv[])
175 {
176 if (hchan == NULL)
177 {
178 helpmod_reply(sender, returntype, "Can not handle queue: Channel not defined or not found");
179 return;
180 }
181 switch (hqueue_action) /* easy ones */
182 {
183 case HQ_ON:
184 if (hchan->flags & H_QUEUE)
185 helpmod_reply(sender, returntype, "Can not activate queue: Queue is already active on channel %s", hchannel_get_name(hchan));
186 else
187 {
188 hchan->flags |= H_QUEUE;
189 helpmod_reply(sender, returntype, "Queue activated for channel %s", hchannel_get_name(hchan));
190 hchannel_conf_change(hchan, hchan->flags & ~(H_QUEUE));
191 hchan->autoqueue = 0;
192 }
193 return;
194 case HQ_OFF:
195 if (!(hchan->flags & H_QUEUE))
196 helpmod_reply(sender, returntype, "Can not deactive queue: Queue is not active on %s", hchannel_get_name(hchan));
197 else
198 {
199 hchan->flags &= ~H_QUEUE;
200 helpmod_reply(sender, returntype, "Queue deactivated for channel %s", hchannel_get_name(hchan));
201 hchannel_conf_change(hchan, hchan->flags | H_QUEUE);
202 hchan->autoqueue = 0;
203
204 { /* devoice all users of level H_PEON */
205 hchannel_user *hchanuser;
206 huser_channel *huserchan;
207 for (hchanuser = hchan->channel_users;hchanuser != NULL;hchanuser = hchanuser->next)
208 {
209 huserchan = huser_on_channel(hchanuser->husr, hchan);
210 if (huser_get_level(hchanuser->husr) == H_PEON && huserchan->flags & HCUMODE_VOICE)
211 helpmod_channick_modes(hchanuser->husr, hchan, MC_DEVOICE, HLAZY);
212 }
213 }
214
215 }
216 return;
217 }
218 if (!(hchan->flags & H_QUEUE))
219 {
220 helpmod_reply(sender, returntype, "Can not handle queue: Queue not active on channel %s", hchannel_get_name(hchan));
221 return;
222 }
223 /* now to the real deal */
224 switch (hqueue_action)
225 {
226 case HQ_DONE:
227 {
228 int i;
229 if (argc == 0)
230 {
231 helpmod_reply(sender, returntype, "Can not advance queue: User not specified", hchannel_get_name(hchan));
232 return;
233 }
234 if (argc > H_CMD_MAX_ARGS)
235 argc = H_CMD_MAX_ARGS;
236
237 for (i=0;i<argc;i++)
238 {
239 huser *husr = huser_get(getnickbynick(argv[i]));
240 if (husr == NULL)
241 {
242 helpmod_reply(sender, returntype, "Can not advance queue: User %s not found", argv[i]);
243 continue;
244 }
245 helpmod_channick_modes(husr, hchan, MC_DEVOICE, HLAZY);
246 }
247
248 hqueue_handle_queue(hchan, sender);
249 }
250 return;
251 case HQ_NEXT:
252 {
253 int nnext = 1;
254 if (argc > 0)
255 {
256 if (!sscanf(argv[0], "%d", &nnext) || nnext <= 0 || nnext > 25 /* magic number */)
257 {
258 helpmod_reply(sender, returntype, "Can not advance queue: Integer [1, 25] expected", hchannel_get_name(hchan));
259 return;
260 }
261 }
262 hqueue_advance(hchan, sender, nnext);
263 }
264 return;
265 case HQ_MAINTAIN:
266 {
267 int tmp;
268 if (argc == 0)
269 {
270 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));
271 return;
272 }
273 if (!sscanf(argv[0], "%d", &tmp) || tmp < 0 || tmp > 25)
274 {
275 helpmod_reply(sender, returntype, "Can not set auto queue: Integer [0, 20] expected", hchannel_get_name(hchan));
276 return;
277 }
278 hchan->autoqueue = tmp;
279 if (tmp == 0)
280 {
281 if (hchan->flags & H_QUEUE_MAINTAIN)
282 {
283 hchan->flags &= ~(H_QUEUE_MAINTAIN);
284 helpmod_reply(sender, returntype, "Autoqueue is now disabled for channel %s", hchannel_get_name(hchan));
285 }
286 else
287 helpmod_reply(sender, returntype, "Autoqueue is not enabled for channel %s", hchannel_get_name(hchan));
288 }
289 else if (!(hchan->flags & H_QUEUE_MAINTAIN))
290 {
291 hchan->flags |= H_QUEUE_MAINTAIN;
292 helpmod_reply(sender, returntype, "Autoqueue for channel %s activated and set to %d succesfully", hchannel_get_name(hchan), hchan->autoqueue);
293 }
294 else
295 helpmod_reply(sender, returntype, "Autoqueue for channel %s set to %d succesfully", hchannel_get_name(hchan), hchan->autoqueue);
296 hqueue_handle_queue(hchan, sender);
297 }
298 return;
299 case HQ_LIST:
300 {
301 int count = hqueue_count_in_queue(hchan);
302 hqueue_entry *hqueue = hqueue_get_next(hchan);
303
304 char buffer[512];
305 buffer[0] = '\0';
306
307 helpmod_reply(sender, returntype, "Channel %s has following users in queue (%d user%s total):", hchannel_get_name(hchan), count, (count==1)?"":"s");
308
309 for (;hqueue;hqueue = hqueue_get_next(NULL))
310 {
311 if (strlen(buffer) >= 250)
312 {
313 helpmod_reply(sender, returntype, "%s", buffer);
314 buffer[0] = '\0';
315 }
316 if (hqueue_on_queue(hqueue))
317 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));
318 }
319 if (buffer[0])
320 helpmod_reply(sender, returntype, "%s", buffer);
321 }
322 return;
323 case HQ_NONE: /* if no parameters are given print the summary */
324 case HQ_SUMMARY:
325 {
326 int count_on = hqueue_count_in_queue(hchan);
327 int count_off = hqueue_count_off_queue(hchan);
328 int average = hqueue_average_time(hchan);
329
330 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));
331 }
332 return;
333 case HQ_RESET:
334 {
335 hchannel_user *hchanuser = hchan->channel_users;
336 for (;hchanuser;hchanuser = hchanuser->next)
337 {
338 if (huser_get_level(hchanuser->husr) == H_PEON)
339 {
340 huser_channel *huserchan = huser_on_channel(hchanuser->husr, hchan);
341 assert (huserchan != NULL);
342 if (huserchan->flags & HCUMODE_VOICE)
343 helpmod_channick_modes(hchanuser->husr, hchan, MC_DEVOICE, HLAZY);
344 huserchan->flags &= ~(HQUEUE_DONE | H_IDLE_WARNING);
345 }
346 }
347 if (!IsModerated(hchan->real_channel))
348 helpmod_simple_modes(hchan, CHANMODE_MODERATE, 0, 0);
349 helpmod_message_channel(hchan, "Channel queue has been reset");
350 helpmod_reply(sender, returntype, "Queue for channel %s has been reset", hchannel_get_name(hchan));
351 }
352 return;
353 }
354 }
355
356 void hqueue_handle_queue(hchannel *hchan, huser *huser)
357 {
358 if ((hchan->flags & (H_QUEUE | H_QUEUE_MAINTAIN)) && hchan->autoqueue && hqueue_count_in_queue(hchan))
359 {
360 int dif = hchan->autoqueue - hqueue_count_off_queue(hchan);
361 if (dif > 0)
362 hqueue_advance(hchan, huser, dif);
363 }
364 hcommit_modes();
365 }
366
367 int hqueue_get_position(hchannel *hchan, huser *target)
368 {
369 int position;
370 hqueue_entry *hqueue = hqueue_get_next(hchan);
371
372 if (hchannel_on_channel(hchan, target) == NULL)
373 return -1;
374
375 if (!(hchan->flags & H_QUEUE))
376 return -1;
377
378 for (position = 0;hqueue;hqueue = hqueue_get_next(NULL))
379 {
380 if (hqueue_on_queue(hqueue))
381 {
382 position++;
383 if (hqueue->hchanuser->husr == target)
384 return position;
385 }
386 }
387 return -1;
388 }