| |
1 /** |
| |
2 * @file cmds.c |
| |
3 * |
| |
4 * gaim |
| |
5 * |
| |
6 * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu> |
| |
7 * |
| |
8 * This program is free software; you can redistribute it and/or modify |
| |
9 * it under the terms of the GNU General Public License as published by |
| |
10 * the Free Software Foundation; either version 2 of the License, or |
| |
11 * (at your option) any later version. |
| |
12 * |
| |
13 * This program is distributed in the hope that it will be useful, |
| |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| |
16 * GNU General Public License for more details. |
| |
17 * |
| |
18 * You should have received a copy of the GNU General Public License |
| |
19 * along with this program; if not, write to the Free Software |
| |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
21 */ |
| |
22 |
| |
23 #include "internal.h" |
| |
24 |
| |
25 #include "conversation.h" |
| |
26 #include "debug.h" |
| |
27 #include "notify.h" |
| |
28 #include "util.h" |
| |
29 |
| |
30 #include "irc.h" |
| |
31 |
| |
32 |
| |
33 static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops); |
| |
34 |
| |
35 int irc_cmd_default(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
36 { |
| |
37 GaimConversation *convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, target, irc->account); |
| |
38 char *buf; |
| |
39 |
| |
40 if (!convo) |
| |
41 return 1; |
| |
42 |
| |
43 buf = g_strdup_printf(_("Unknown command: %s"), cmd); |
| |
44 if (gaim_conversation_get_type(convo) == GAIM_CONV_TYPE_IM) |
| |
45 gaim_conv_im_write(GAIM_CONV_IM(convo), "", buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); |
| |
46 else |
| |
47 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), "", buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); |
| |
48 g_free(buf); |
| |
49 |
| |
50 return 1; |
| |
51 } |
| |
52 |
| |
53 int irc_cmd_away(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
54 { |
| |
55 char *buf, *message; |
| |
56 |
| |
57 if (args[0] && strcmp(cmd, "back")) { |
| |
58 message = gaim_markup_strip_html(args[0]); |
| |
59 gaim_util_chrreplace(message, '\n', ' '); |
| |
60 buf = irc_format(irc, "v:", "AWAY", message); |
| |
61 g_free(message); |
| |
62 } else { |
| |
63 buf = irc_format(irc, "v", "AWAY"); |
| |
64 } |
| |
65 irc_send(irc, buf); |
| |
66 g_free(buf); |
| |
67 |
| |
68 return 0; |
| |
69 } |
| |
70 |
| |
71 int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
72 { |
| |
73 GaimConnection *gc = gaim_account_get_connection(irc->account); |
| |
74 char *action, *escaped, *dst, **newargs; |
| |
75 const char *src; |
| |
76 GaimConversation *convo; |
| |
77 |
| |
78 if (!args || !args[0] || !gc) |
| |
79 return 0; |
| |
80 |
| |
81 action = g_malloc(strlen(args[0]) + 10); |
| |
82 |
| |
83 sprintf(action, "\001ACTION "); |
| |
84 |
| |
85 src = args[0]; |
| |
86 dst = action + 8; |
| |
87 while (*src) { |
| |
88 if (*src == '\n') { |
| |
89 if (*(src + 1) == '\0') { |
| |
90 break; |
| |
91 } else { |
| |
92 *dst++ = ' '; |
| |
93 src++; |
| |
94 continue; |
| |
95 } |
| |
96 } |
| |
97 *dst++ = *src++; |
| |
98 } |
| |
99 *dst++ = '\001'; |
| |
100 *dst = '\0'; |
| |
101 |
| |
102 newargs = g_new0(char *, 2); |
| |
103 newargs[0] = g_strdup(target); |
| |
104 newargs[1] = action; |
| |
105 irc_cmd_privmsg(irc, cmd, target, (const char **)newargs); |
| |
106 g_free(newargs[0]); |
| |
107 g_free(newargs[1]); |
| |
108 g_free(newargs); |
| |
109 |
| |
110 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, target, irc->account); |
| |
111 if (convo) { |
| |
112 escaped = g_markup_escape_text(args[0], -1); |
| |
113 action = g_strdup_printf("/me %s", escaped); |
| |
114 g_free(escaped); |
| |
115 if (action[strlen(action) - 1] == '\n') |
| |
116 action[strlen(action) - 1] = '\0'; |
| |
117 if (gaim_conversation_get_type(convo) == GAIM_CONV_TYPE_CHAT) |
| |
118 serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(convo)), |
| |
119 gaim_connection_get_display_name(gc), |
| |
120 0, action, time(NULL)); |
| |
121 else |
| |
122 gaim_conv_im_write(GAIM_CONV_IM(convo), gaim_connection_get_display_name(gc), |
| |
123 action, 0, time(NULL)); |
| |
124 g_free(action); |
| |
125 } |
| |
126 |
| |
127 return 1; |
| |
128 } |
| |
129 |
| |
130 int irc_cmd_ctcp_version(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
131 { |
| |
132 char *buf; |
| |
133 |
| |
134 |
| |
135 if (!args || !args[0]) |
| |
136 return 0; |
| |
137 |
| |
138 buf = irc_format(irc, "vn:", "PRIVMSG", args[0], "\001VERSION\001"); |
| |
139 irc_send(irc, buf); |
| |
140 g_free(buf); |
| |
141 |
| |
142 return 0; |
| |
143 } |
| |
144 |
| |
145 int irc_cmd_invite(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
146 { |
| |
147 char *buf; |
| |
148 |
| |
149 if (!args || !args[0] || !(args[1] || target)) |
| |
150 return 0; |
| |
151 |
| |
152 buf = irc_format(irc, "vnc", "INVITE", args[0], args[1] ? args[1] : target); |
| |
153 irc_send(irc, buf); |
| |
154 g_free(buf); |
| |
155 |
| |
156 return 0; |
| |
157 } |
| |
158 |
| |
159 int irc_cmd_join(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
160 { |
| |
161 char *buf; |
| |
162 |
| |
163 if (!args || !args[0]) |
| |
164 return 0; |
| |
165 |
| |
166 if (args[1]) |
| |
167 buf = irc_format(irc, "vcv", "JOIN", args[0], args[1]); |
| |
168 else |
| |
169 buf = irc_format(irc, "vc", "JOIN", args[0]); |
| |
170 irc_send(irc, buf); |
| |
171 g_free(buf); |
| |
172 |
| |
173 return 0; |
| |
174 } |
| |
175 |
| |
176 int irc_cmd_kick(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
177 { |
| |
178 char *buf; |
| |
179 GaimConversation *convo; |
| |
180 |
| |
181 if (!args || !args[0]) |
| |
182 return 0; |
| |
183 |
| |
184 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, target, irc->account); |
| |
185 if (!convo) |
| |
186 return 0; |
| |
187 |
| |
188 if (args[1]) |
| |
189 buf = irc_format(irc, "vcn:", "KICK", target, args[0], args[1]); |
| |
190 else |
| |
191 buf = irc_format(irc, "vcn", "KICK", target, args[0]); |
| |
192 irc_send(irc, buf); |
| |
193 g_free(buf); |
| |
194 |
| |
195 return 0; |
| |
196 } |
| |
197 |
| |
198 int irc_cmd_list(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
199 { |
| |
200 gaim_roomlist_show_with_account(irc->account); |
| |
201 |
| |
202 return 0; |
| |
203 } |
| |
204 |
| |
205 int irc_cmd_mode(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
206 { |
| |
207 GaimConnection *gc; |
| |
208 char *buf; |
| |
209 |
| |
210 if (!args) |
| |
211 return 0; |
| |
212 |
| |
213 if (!strcmp(cmd, "mode")) { |
| |
214 if (!args[0] && irc_ischannel(target)) |
| |
215 buf = irc_format(irc, "vc", "MODE", target); |
| |
216 else if (args[0] && (*args[0] == '+' || *args[0] == '-')) |
| |
217 buf = irc_format(irc, "vcv", "MODE", target, args[0]); |
| |
218 else if (args[0]) |
| |
219 buf = irc_format(irc, "vv", "MODE", args[0]); |
| |
220 else |
| |
221 return 0; |
| |
222 } else if (!strcmp(cmd, "umode")) { |
| |
223 if (!args[0]) |
| |
224 return 0; |
| |
225 gc = gaim_account_get_connection(irc->account); |
| |
226 buf = irc_format(irc, "vnv", "MODE", gaim_connection_get_display_name(gc), args[0]); |
| |
227 } else { |
| |
228 return 0; |
| |
229 } |
| |
230 |
| |
231 irc_send(irc, buf); |
| |
232 g_free(buf); |
| |
233 |
| |
234 return 0; |
| |
235 } |
| |
236 |
| |
237 int irc_cmd_names(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
238 { |
| |
239 char *buf; |
| |
240 |
| |
241 if (!args || (!args[0] && !irc_ischannel(target))) |
| |
242 return 0; |
| |
243 |
| |
244 buf = irc_format(irc, "vc", "NAMES", args[0] ? args[0] : target); |
| |
245 irc_send(irc, buf); |
| |
246 g_free(buf); |
| |
247 |
| |
248 irc->nameconv = g_strdup(target); |
| |
249 |
| |
250 return 0; |
| |
251 } |
| |
252 |
| |
253 int irc_cmd_nick(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
254 { |
| |
255 char *buf; |
| |
256 |
| |
257 if (!args || !args[0]) |
| |
258 return 0; |
| |
259 |
| |
260 buf = irc_format(irc, "v:", "NICK", args[0]); |
| |
261 irc_send(irc, buf); |
| |
262 g_free(buf); |
| |
263 |
| |
264 return 0; |
| |
265 } |
| |
266 |
| |
267 int irc_cmd_op(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
268 { |
| |
269 char **nicks, **ops, *sign, *mode; |
| |
270 int i = 0, used = 0; |
| |
271 |
| |
272 if (!args || !args[0] || !*args[0]) |
| |
273 return 0; |
| |
274 |
| |
275 if (!strcmp(cmd, "op")) { |
| |
276 sign = "+"; |
| |
277 mode = "o"; |
| |
278 } else if (!strcmp(cmd, "deop")) { |
| |
279 sign = "-"; |
| |
280 mode = "o"; |
| |
281 } else if (!strcmp(cmd, "voice")) { |
| |
282 sign = "+"; |
| |
283 mode = "v"; |
| |
284 } else if (!strcmp(cmd, "devoice")) { |
| |
285 sign = "-"; |
| |
286 mode = "v"; |
| |
287 } else { |
| |
288 gaim_debug(GAIM_DEBUG_ERROR, "irc", "invalid 'op' command '%s'\n", cmd); |
| |
289 return 0; |
| |
290 } |
| |
291 |
| |
292 nicks = g_strsplit(args[0], " ", -1); |
| |
293 |
| |
294 for (i = 0; nicks[i]; i++) |
| |
295 /* nothing */; |
| |
296 ops = g_new0(char *, i * 2 + 1); |
| |
297 |
| |
298 for (i = 0; nicks[i]; i++) { |
| |
299 if (!*nicks[i]) |
| |
300 continue; |
| |
301 ops[used++] = mode; |
| |
302 ops[used++] = nicks[i]; |
| |
303 } |
| |
304 |
| |
305 irc_do_mode(irc, target, sign, ops); |
| |
306 g_free(ops); |
| |
307 |
| |
308 return 0; |
| |
309 } |
| |
310 |
| |
311 int irc_cmd_part(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
312 { |
| |
313 char *buf; |
| |
314 |
| |
315 if (!args) |
| |
316 return 0; |
| |
317 |
| |
318 if (args[1]) |
| |
319 buf = irc_format(irc, "vc:", "PART", args[0] ? args[0] : target, args[1]); |
| |
320 else |
| |
321 buf = irc_format(irc, "vc", "PART", args[0] ? args[0] : target); |
| |
322 irc_send(irc, buf); |
| |
323 g_free(buf); |
| |
324 |
| |
325 return 0; |
| |
326 } |
| |
327 |
| |
328 int irc_cmd_ping(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
329 { |
| |
330 char *stamp; |
| |
331 char *buf; |
| |
332 |
| |
333 if (args && args[0]) { |
| |
334 if (irc_ischannel(args[0])) |
| |
335 return 0; |
| |
336 stamp = g_strdup_printf("\001PING %lu\001", time(NULL)); |
| |
337 buf = irc_format(irc, "vn:", "PRIVMSG", args[0], stamp); |
| |
338 g_free(stamp); |
| |
339 } else if (target) { |
| |
340 stamp = g_strdup_printf("%s %lu", target, time(NULL)); |
| |
341 buf = irc_format(irc, "v:", "PING", stamp); |
| |
342 g_free(stamp); |
| |
343 } else { |
| |
344 stamp = g_strdup_printf("%lu", time(NULL)); |
| |
345 buf = irc_format(irc, "vv", "PING", stamp); |
| |
346 g_free(stamp); |
| |
347 } |
| |
348 irc_send(irc, buf); |
| |
349 g_free(buf); |
| |
350 |
| |
351 return 0; |
| |
352 } |
| |
353 |
| |
354 int irc_cmd_privmsg(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
355 { |
| |
356 const char *cur, *end; |
| |
357 char *msg, *buf; |
| |
358 |
| |
359 if (!args || !args[0] || !args[1]) |
| |
360 return 0; |
| |
361 |
| |
362 cur = args[1]; |
| |
363 end = args[1]; |
| |
364 while (*end && *cur) { |
| |
365 end = strchr(cur, '\n'); |
| |
366 if (!end) |
| |
367 end = cur + strlen(cur); |
| |
368 msg = g_strndup(cur, end - cur); |
| |
369 buf = irc_format(irc, "vt:", "PRIVMSG", args[0], msg); |
| |
370 irc_send(irc, buf); |
| |
371 g_free(msg); |
| |
372 g_free(buf); |
| |
373 cur = end + 1; |
| |
374 } |
| |
375 |
| |
376 return 0; |
| |
377 } |
| |
378 |
| |
379 int irc_cmd_quit(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
380 { |
| |
381 char *buf; |
| |
382 |
| |
383 if (!irc->quitting) { |
| |
384 /* |
| |
385 * Use gaim_account_get_string(irc->account, "quitmsg", IRC_DEFAULT_QUIT) |
| |
386 * and uncomment the appropriate account preference in irc.c if we |
| |
387 * decide we want custom quit messages. |
| |
388 */ |
| |
389 buf = irc_format(irc, "v:", "QUIT", (args && args[0]) ? args[0] : IRC_DEFAULT_QUIT); |
| |
390 irc_send(irc, buf); |
| |
391 g_free(buf); |
| |
392 |
| |
393 irc->quitting = TRUE; |
| |
394 |
| |
395 if (!irc->account->disconnecting) |
| |
396 gaim_account_set_status(irc->account, "offline", TRUE, NULL); |
| |
397 } |
| |
398 |
| |
399 return 0; |
| |
400 } |
| |
401 |
| |
402 int irc_cmd_quote(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
403 { |
| |
404 char *buf; |
| |
405 |
| |
406 if (!args || !args[0]) |
| |
407 return 0; |
| |
408 |
| |
409 buf = irc_format(irc, "v", args[0]); |
| |
410 irc_send(irc, buf); |
| |
411 g_free(buf); |
| |
412 |
| |
413 return 0; |
| |
414 } |
| |
415 |
| |
416 int irc_cmd_query(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
417 { |
| |
418 GaimConversation *convo; |
| |
419 GaimConnection *gc; |
| |
420 |
| |
421 if (!args || !args[0]) |
| |
422 return 0; |
| |
423 |
| |
424 convo = gaim_conversation_new(GAIM_CONV_TYPE_IM, irc->account, args[0]); |
| |
425 gaim_conversation_present(convo); |
| |
426 |
| |
427 if (args[1]) { |
| |
428 gc = gaim_account_get_connection(irc->account); |
| |
429 irc_cmd_privmsg(irc, cmd, target, args); |
| |
430 gaim_conv_im_write(GAIM_CONV_IM(convo), gaim_connection_get_display_name(gc), |
| |
431 args[1], GAIM_MESSAGE_SEND, time(NULL)); |
| |
432 } |
| |
433 |
| |
434 return 0; |
| |
435 } |
| |
436 |
| |
437 int irc_cmd_remove(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
438 { |
| |
439 char *buf; |
| |
440 |
| |
441 if (!args || !args[0]) |
| |
442 return 0; |
| |
443 |
| |
444 if (!irc_ischannel(target)) /* not a channel, punt */ |
| |
445 return 0; |
| |
446 |
| |
447 if (args[1]) |
| |
448 buf = irc_format(irc, "vcn:", "REMOVE", target, args[0], args[1]); |
| |
449 else |
| |
450 buf = irc_format(irc, "vcn", "REMOVE", target, args[0]); |
| |
451 irc_send(irc, buf); |
| |
452 g_free(buf); |
| |
453 |
| |
454 return 0; |
| |
455 } |
| |
456 |
| |
457 int irc_cmd_service(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
458 { |
| |
459 char *capital_cmd, *buf; |
| |
460 |
| |
461 if (!args || !args[0]) |
| |
462 return 0; |
| |
463 |
| |
464 /* cmd will be one of nickserv, chanserv, memoserv or operserv */ |
| |
465 capital_cmd = g_ascii_strup(cmd, -1); |
| |
466 buf = irc_format(irc, "v:", capital_cmd, args[0]); |
| |
467 irc_send(irc, buf); |
| |
468 g_free(capital_cmd); |
| |
469 g_free(buf); |
| |
470 |
| |
471 return 0; |
| |
472 } |
| |
473 |
| |
474 int irc_cmd_time(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
475 { |
| |
476 char *buf; |
| |
477 |
| |
478 buf = irc_format(irc, "v", "TIME"); |
| |
479 irc_send(irc, buf); |
| |
480 g_free(buf); |
| |
481 |
| |
482 return 0; |
| |
483 } |
| |
484 |
| |
485 int irc_cmd_topic(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
486 { |
| |
487 char *buf; |
| |
488 const char *topic; |
| |
489 GaimConversation *convo; |
| |
490 |
| |
491 if (!args) |
| |
492 return 0; |
| |
493 |
| |
494 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, target, irc->account); |
| |
495 if (!convo) |
| |
496 return 0; |
| |
497 |
| |
498 if (!args[0]) { |
| |
499 topic = gaim_conv_chat_get_topic (GAIM_CONV_CHAT(convo)); |
| |
500 |
| |
501 if (topic) { |
| |
502 char *tmp, *tmp2; |
| |
503 tmp = g_markup_escape_text(topic, -1); |
| |
504 tmp2 = gaim_markup_linkify(tmp); |
| |
505 buf = g_strdup_printf(_("current topic is: %s"), tmp2); |
| |
506 g_free(tmp); |
| |
507 g_free(tmp2); |
| |
508 } else |
| |
509 buf = g_strdup(_("No topic is set")); |
| |
510 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), target, buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); |
| |
511 g_free(buf); |
| |
512 |
| |
513 return 0; |
| |
514 } |
| |
515 |
| |
516 buf = irc_format(irc, "vt:", "TOPIC", target, args[0]); |
| |
517 irc_send(irc, buf); |
| |
518 g_free(buf); |
| |
519 |
| |
520 return 0; |
| |
521 } |
| |
522 |
| |
523 int irc_cmd_wallops(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
524 { |
| |
525 char *buf; |
| |
526 |
| |
527 if (!args || !args[0]) |
| |
528 return 0; |
| |
529 |
| |
530 if (!strcmp(cmd, "wallops")) |
| |
531 buf = irc_format(irc, "v:", "WALLOPS", args[0]); |
| |
532 else if (!strcmp(cmd, "operwall")) |
| |
533 buf = irc_format(irc, "v:", "OPERWALL", args[0]); |
| |
534 else |
| |
535 return 0; |
| |
536 |
| |
537 irc_send(irc, buf); |
| |
538 g_free(buf); |
| |
539 |
| |
540 return 0; |
| |
541 } |
| |
542 |
| |
543 int irc_cmd_whois(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
544 { |
| |
545 char *buf; |
| |
546 |
| |
547 if (!args || !args[0]) |
| |
548 return 0; |
| |
549 |
| |
550 if (args[1]) { |
| |
551 buf = irc_format(irc, "vvn", "WHOIS", args[0], args[1]); |
| |
552 irc->whois.nick = g_strdup(args[1]); |
| |
553 } else { |
| |
554 buf = irc_format(irc, "vn", "WHOIS", args[0]); |
| |
555 irc->whois.nick = g_strdup(args[0]); |
| |
556 } |
| |
557 |
| |
558 irc_send(irc, buf); |
| |
559 g_free(buf); |
| |
560 |
| |
561 return 0; |
| |
562 } |
| |
563 |
| |
564 static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops) |
| |
565 { |
| |
566 char *buf, mode[5]; |
| |
567 int i = 0; |
| |
568 |
| |
569 if (!sign) |
| |
570 return; |
| |
571 |
| |
572 while (ops[i]) { |
| |
573 if (ops[i + 2] && ops[i + 4]) { |
| |
574 g_snprintf(mode, sizeof(mode), "%s%s%s%s", sign, |
| |
575 ops[i], ops[i + 2], ops[i + 4]); |
| |
576 buf = irc_format(irc, "vcvnnn", "MODE", target, mode, |
| |
577 ops[i + 1], ops[i + 3], ops[i + 5]); |
| |
578 i += 6; |
| |
579 } else if (ops[i + 2]) { |
| |
580 g_snprintf(mode, sizeof(mode), "%s%s%s", |
| |
581 sign, ops[i], ops[i + 2]); |
| |
582 buf = irc_format(irc, "vcvnn", "MODE", target, mode, |
| |
583 ops[i + 1], ops[i + 3]); |
| |
584 i += 4; |
| |
585 } else { |
| |
586 g_snprintf(mode, sizeof(mode), "%s%s", sign, ops[i]); |
| |
587 buf = irc_format(irc, "vcvn", "MODE", target, mode, ops[i + 1]); |
| |
588 i += 2; |
| |
589 } |
| |
590 irc_send(irc, buf); |
| |
591 g_free(buf); |
| |
592 } |
| |
593 |
| |
594 return; |
| |
595 } |