1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 by the Quassel Project * |
3 | * devel@quassel-irc.org * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * |
7 | * the Free Software Foundation; either version 2 of the License, or * |
8 | * (at your option) version 3. * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
19 | ***************************************************************************/ |
20 | |
21 | #include "eventstringifier.h" |
22 | |
23 | #include "coresession.h" |
24 | #include "ctcpevent.h" |
25 | #include "messageevent.h" |
26 | |
27 | EventStringifier::EventStringifier(CoreSession *parent) : BasicHandler("handleCtcp" , parent), |
28 | _coreSession(parent), |
29 | _whois(false) |
30 | { |
31 | connect(this, SIGNAL(newMessageEvent(Event *)), coreSession()->eventManager(), SLOT(postEvent(Event *))); |
32 | } |
33 | |
34 | |
35 | void EventStringifier::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender, |
36 | const QString &target, Message::Flags msgFlags) |
37 | { |
38 | if (event->flags().testFlag(EventManager::Silent)) |
39 | return; |
40 | |
41 | MessageEvent *msgEvent = createMessageEvent(event, msgType, msg, sender, target, msgFlags); |
42 | //sendMessageEvent(msgEvent); |
43 | emit newMessageEvent(msgEvent); |
44 | } |
45 | |
46 | |
47 | MessageEvent *EventStringifier::createMessageEvent(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender, |
48 | const QString &target, Message::Flags msgFlags) |
49 | { |
50 | MessageEvent *msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags); |
51 | msgEvent->setTimestamp(event->timestamp()); |
52 | return msgEvent; |
53 | } |
54 | |
55 | |
56 | bool EventStringifier::checkParamCount(IrcEvent *e, int minParams) |
57 | { |
58 | if (e->params().count() < minParams) { |
59 | if (e->type() == EventManager::IrcEventNumeric) { |
60 | qWarning() << "Command " << static_cast<IrcEventNumeric *>(e)->number() << " requires " << minParams << "params, got: " << e->params(); |
61 | } |
62 | else { |
63 | QString name = coreSession()->eventManager()->enumName(e->type()); |
64 | qWarning() << qPrintable(name) << "requires" << minParams << "params, got:" << e->params(); |
65 | } |
66 | e->stop(); |
67 | return false; |
68 | } |
69 | return true; |
70 | } |
71 | |
72 | |
73 | /* These are only for legacy reasons; remove as soon as we handle NetworkSplitEvents properly */ |
74 | void EventStringifier::processNetworkSplitJoin(NetworkSplitEvent *e) |
75 | { |
76 | QString msg = e->users().join("#:#" ) + "#:#" + e->quitMessage(); |
77 | displayMsg(e, Message::NetsplitJoin, msg, QString(), e->channel()); |
78 | } |
79 | |
80 | |
81 | void EventStringifier::processNetworkSplitQuit(NetworkSplitEvent *e) |
82 | { |
83 | QString msg = e->users().join("#:#" ) + "#:#" + e->quitMessage(); |
84 | displayMsg(e, Message::NetsplitQuit, msg, QString(), e->channel()); |
85 | } |
86 | |
87 | |
88 | /* End legacy */ |
89 | |
90 | void EventStringifier::processIrcEventNumeric(IrcEventNumeric *e) |
91 | { |
92 | //qDebug() << e->number(); |
93 | switch (e->number()) { |
94 | // Welcome, status, info messages. Just display these. |
95 | case 1: |
96 | case 2: |
97 | case 3: |
98 | case 4: |
99 | case 5: |
100 | case 221: |
101 | case 250: |
102 | case 251: |
103 | case 252: |
104 | case 253: |
105 | case 254: |
106 | case 255: |
107 | case 256: |
108 | case 257: |
109 | case 258: |
110 | case 259: |
111 | case 265: |
112 | case 266: |
113 | case 372: |
114 | case 375: |
115 | displayMsg(e, Message::Server, e->params().join(" " ), e->prefix()); |
116 | break; |
117 | |
118 | // Server error messages without param, just display them |
119 | case 263: |
120 | case 409: |
121 | case 411: |
122 | case 412: |
123 | case 422: |
124 | case 424: |
125 | case 445: |
126 | case 446: |
127 | case 451: |
128 | case 462: |
129 | case 463: |
130 | case 464: |
131 | case 465: |
132 | case 466: |
133 | case 472: |
134 | case 481: |
135 | case 483: |
136 | case 485: |
137 | case 491: |
138 | case 501: |
139 | case 502: |
140 | case 431: // ERR_NONICKNAMEGIVEN |
141 | displayMsg(e, Message::Error, e->params().join(" " ), e->prefix()); |
142 | break; |
143 | |
144 | // Server error messages, display them in red. Colon between first param and rest. |
145 | case 401: |
146 | { |
147 | if (!checkParamCount(e, 1)) |
148 | return; |
149 | |
150 | QStringList params = e->params(); |
151 | QString target = params.takeFirst(); |
152 | displayMsg(e, Message::Error, target + ": " + params.join(" " ), e->prefix(), target, Message::Redirected); |
153 | break; |
154 | } |
155 | |
156 | case 402: |
157 | case 403: |
158 | case 404: |
159 | case 406: |
160 | case 408: |
161 | case 415: |
162 | case 421: |
163 | case 442: |
164 | { |
165 | if (!checkParamCount(e, 1)) |
166 | return; |
167 | |
168 | QStringList params = e->params(); |
169 | QString channelName = params.takeFirst(); |
170 | displayMsg(e, Message::Error, channelName + ": " + params.join(" " ), e->prefix()); |
171 | break; |
172 | } |
173 | |
174 | // Server error messages which will be displayed with a colon between the first param and the rest |
175 | case 413: |
176 | case 414: |
177 | case 423: |
178 | case 441: |
179 | case 444: |
180 | case 461: // FIXME see below for the 47x codes |
181 | case 467: |
182 | case 471: |
183 | case 473: |
184 | case 474: |
185 | case 475: |
186 | case 476: |
187 | case 477: |
188 | case 478: |
189 | case 482: |
190 | case 436: // ERR_NICKCOLLISION |
191 | { |
192 | if (!checkParamCount(e, 1)) |
193 | return; |
194 | |
195 | QStringList params = e->params(); |
196 | QString p = params.takeFirst(); |
197 | displayMsg(e, Message::Error, p + ": " + params.join(" " )); |
198 | break; |
199 | } |
200 | |
201 | // Ignore these commands. |
202 | case 321: |
203 | case 353: |
204 | case 366: |
205 | case 376: |
206 | break; |
207 | |
208 | // CAP stuff |
209 | case 900: |
210 | case 903: |
211 | case 904: |
212 | case 905: |
213 | case 906: |
214 | case 907: |
215 | { |
216 | displayMsg(e, Message::Info, "CAP: " + e->params().join("" )); |
217 | break; |
218 | } |
219 | |
220 | // Everything else will be marked in red, so we can add them somewhere. |
221 | default: |
222 | if (_whois) { |
223 | // many nets define their own WHOIS fields. we fetch those not in need of special attention here: |
224 | displayMsg(e, Message::Server, tr("[Whois] " ) + e->params().join(" " ), e->prefix()); |
225 | } |
226 | else { |
227 | // FIXME figure out how/where to do this in the future |
228 | //if(coreSession()->ircListHelper()->requestInProgress(network()->networkId())) |
229 | // coreSession()->ircListHelper()->reportError(params.join(" ")); |
230 | //else |
231 | displayMsg(e, Message::Error, QString("%1 %2" ).arg(e->number(), 3, 10, QLatin1Char('0')).arg(e->params().join(" " )), e->prefix()); |
232 | } |
233 | } |
234 | } |
235 | |
236 | |
237 | void EventStringifier::processIrcEventInvite(IrcEvent *e) |
238 | { |
239 | displayMsg(e, Message::Invite, tr("%1 invited you to channel %2" ).arg(e->nick(), e->params().at(1))); |
240 | } |
241 | |
242 | |
243 | void EventStringifier::processIrcEventJoin(IrcEvent *e) |
244 | { |
245 | if (e->testFlag(EventManager::Netsplit)) |
246 | return; |
247 | |
248 | displayMsg(e, Message::Join, e->params()[0], e->prefix(), e->params()[0]); |
249 | } |
250 | |
251 | |
252 | void EventStringifier::processIrcEventKick(IrcEvent *e) |
253 | { |
254 | if (!checkParamCount(e, 2)) |
255 | return; |
256 | |
257 | IrcUser *victim = e->network()->ircUser(e->params().at(1)); |
258 | if (victim) { |
259 | QString channel = e->params().at(0); |
260 | QString msg = victim->nick(); |
261 | if (e->params().count() > 2) |
262 | msg += " " + e->params().at(2); |
263 | |
264 | displayMsg(e, Message::Kick, msg, e->prefix(), channel); |
265 | } |
266 | } |
267 | |
268 | |
269 | void EventStringifier::processIrcEventMode(IrcEvent *e) |
270 | { |
271 | if (e->network()->isChannelName(e->params().first())) { |
272 | // Channel Modes |
273 | displayMsg(e, Message::Mode, e->params().join(" " ), e->prefix(), e->params().first()); |
274 | } |
275 | else { |
276 | // User Modes |
277 | // FIXME: redirect |
278 | displayMsg(e, Message::Mode, e->params().join(" " ), e->prefix()); |
279 | } |
280 | } |
281 | |
282 | |
283 | // this needs to be called before the ircuser is renamed! |
284 | void EventStringifier::processIrcEventNick(IrcEvent *e) |
285 | { |
286 | if (!checkParamCount(e, 1)) |
287 | return; |
288 | |
289 | IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); |
290 | if (!ircuser) { |
291 | qWarning() << Q_FUNC_INFO << "Unknown IrcUser!" ; |
292 | return; |
293 | } |
294 | |
295 | QString newnick = e->params().at(0); |
296 | QString oldnick = ircuser->nick(); |
297 | |
298 | QString sender = e->network()->isMyNick(oldnick) ? newnick : e->prefix(); |
299 | foreach(const QString &channel, ircuser->channels()) |
300 | displayMsg(e, Message::Nick, newnick, sender, channel); |
301 | } |
302 | |
303 | |
304 | void EventStringifier::processIrcEventPart(IrcEvent *e) |
305 | { |
306 | if (!checkParamCount(e, 1)) |
307 | return; |
308 | |
309 | QString channel = e->params().at(0); |
310 | QString msg = e->params().count() > 1 ? e->params().at(1) : QString(); |
311 | |
312 | displayMsg(e, Message::Part, msg, e->prefix(), channel); |
313 | } |
314 | |
315 | |
316 | void EventStringifier::processIrcEventPong(IrcEvent *e) |
317 | { |
318 | QString timestamp = e->params().at(1); |
319 | QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz" ); |
320 | if (!sendTime.isValid()) |
321 | displayMsg(e, Message::Server, "PONG " + e->params().join(" " ), e->prefix()); |
322 | } |
323 | |
324 | |
325 | void EventStringifier::processIrcEventQuit(IrcEvent *e) |
326 | { |
327 | if (e->testFlag(EventManager::Netsplit)) |
328 | return; |
329 | |
330 | IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix()); |
331 | if (!ircuser) |
332 | return; |
333 | |
334 | foreach(const QString &channel, ircuser->channels()) |
335 | displayMsg(e, Message::Quit, e->params().count() ? e->params().first() : QString(), e->prefix(), channel); |
336 | } |
337 | |
338 | |
339 | void EventStringifier::processIrcEventTopic(IrcEvent *e) |
340 | { |
341 | displayMsg(e, Message::Topic, tr("%1 has changed topic for %2 to: \"%3\"" ) |
342 | .arg(e->nick(), e->params().at(0), e->params().at(1)), QString(), e->params().at(0)); |
343 | } |
344 | |
345 | void EventStringifier::processIrcEventWallops(IrcEvent *e) |
346 | { |
347 | displayMsg(e, Message::Server, tr("[Operwall] %1: %2" ).arg(e->nick(), e->params().join(" " ))); |
348 | } |
349 | |
350 | |
351 | /* RPL_ISUPPORT */ |
352 | void EventStringifier::processIrcEvent005(IrcEvent *e) |
353 | { |
354 | if (!e->params().last().contains(QRegExp("are supported (by|on) this server" ))) |
355 | displayMsg(e, Message::Error, tr("Received non-RFC-compliant RPL_ISUPPORT: this can lead to unexpected behavior!" ), e->prefix()); |
356 | displayMsg(e, Message::Server, e->params().join(" " ), e->prefix()); |
357 | } |
358 | |
359 | |
360 | /* RPL_AWAY - "<nick> :<away message>" */ |
361 | void EventStringifier::processIrcEvent301(IrcEvent *e) |
362 | { |
363 | QString nick = e->params().at(0); |
364 | QString awayMsg = e->params().at(1); |
365 | QString msg, target; |
366 | bool send = true; |
367 | |
368 | // FIXME: proper redirection needed |
369 | if (_whois) { |
370 | msg = tr("[Whois] " ); |
371 | } |
372 | else { |
373 | target = nick; |
374 | IrcUser *ircuser = e->network()->ircUser(nick); |
375 | if (ircuser) { |
376 | int now = QDateTime::currentDateTime().toTime_t(); |
377 | const int silenceTime = 60; |
378 | if (ircuser->lastAwayMessage() + silenceTime >= now) |
379 | send = false; |
380 | ircuser->setLastAwayMessage(now); |
381 | } |
382 | } |
383 | if (send) |
384 | displayMsg(e, Message::Server, msg + tr("%1 is away: \"%2\"" ).arg(nick, awayMsg), QString(), target); |
385 | } |
386 | |
387 | |
388 | /* RPL_UNAWAY - ":You are no longer marked as being away" */ |
389 | void EventStringifier::processIrcEvent305(IrcEvent *e) |
390 | { |
391 | displayMsg(e, Message::Server, tr("You are no longer marked as being away" )); |
392 | } |
393 | |
394 | |
395 | /* RPL_NOWAWAY - ":You have been marked as being away" */ |
396 | void EventStringifier::processIrcEvent306(IrcEvent *e) |
397 | { |
398 | if (!e->network()->autoAwayActive()) |
399 | displayMsg(e, Message::Server, tr("You have been marked as being away" )); |
400 | } |
401 | |
402 | |
403 | /* |
404 | WHOIS-Message: |
405 | Replies 311 - 313, 317 - 319 are all replies generated in response to a WHOIS message. |
406 | and 301 (RPL_AWAY) |
407 | "<nick> :<away message>" |
408 | WHO-Message: |
409 | Replies 352 and 315 paired are used to answer a WHO message. |
410 | |
411 | WHOWAS-Message: |
412 | Replies 314 and 369 are responses to a WHOWAS message. |
413 | |
414 | */ |
415 | |
416 | /* RPL_WHOISUSER - "<nick> <user> <host> * :<real name>" */ |
417 | void EventStringifier::processIrcEvent311(IrcEvent *e) |
418 | { |
419 | _whois = true; |
420 | |
421 | const QString whoisUserString = tr("[Whois] %1 is %2 (%3)" ); |
422 | |
423 | IrcUser *ircuser = e->network()->ircUser(e->params().at(0)); |
424 | if (ircuser) |
425 | displayMsg(e, Message::Server, whoisUserString.arg(ircuser->nick(), ircuser->hostmask(), ircuser->realName())); |
426 | else { |
427 | QString host = QString("%1!%2@%3" ).arg(e->params().at(0), e->params().at(1), e->params().at(2)); |
428 | displayMsg(e, Message::Server, whoisUserString.arg(e->params().at(0), host, e->params().last())); |
429 | } |
430 | } |
431 | |
432 | |
433 | /* RPL_WHOISSERVER - "<nick> <server> :<server info>" */ |
434 | void EventStringifier::processIrcEvent312(IrcEvent *e) |
435 | { |
436 | if (_whois) |
437 | displayMsg(e, Message::Server, tr("[Whois] %1 is online via %2 (%3)" ).arg(e->params().at(0), e->params().at(1), e->params().last())); |
438 | else |
439 | displayMsg(e, Message::Server, tr("[Whowas] %1 was online via %2 (%3)" ).arg(e->params().at(0), e->params().at(1), e->params().last())); |
440 | } |
441 | |
442 | |
443 | /* RPL_WHOWASUSER - "<nick> <user> <host> * :<real name>" */ |
444 | void EventStringifier::processIrcEvent314(IrcEvent *e) |
445 | { |
446 | if (!checkParamCount(e, 3)) |
447 | return; |
448 | |
449 | displayMsg(e, Message::Server, tr("[Whowas] %1 was %2@%3 (%4)" ).arg(e->params()[0], e->params()[1], e->params()[2], e->params().last())); |
450 | } |
451 | |
452 | |
453 | /* RPL_ENDOFWHO: "<name> :End of WHO list" */ |
454 | void EventStringifier::processIrcEvent315(IrcEvent *e) |
455 | { |
456 | QStringList p = e->params(); |
457 | p.takeLast(); // should be "End of WHO list" |
458 | displayMsg(e, Message::Server, tr("[Who] End of /WHO list for %1" ).arg(p.join(" " ))); |
459 | } |
460 | |
461 | |
462 | /* RPL_WHOISIDLE - "<nick> <integer> :seconds idle" |
463 | (real life: "<nick> <integer> <integer> :seconds idle, signon time) */ |
464 | void EventStringifier::processIrcEvent317(IrcEvent *e) |
465 | { |
466 | int idleSecs = e->params()[1].toInt(); |
467 | |
468 | if (e->params().count() > 3) { // if we have more then 3 params we have the above mentioned "real life" situation |
469 | QDateTime loginTime = QDateTime::fromTime_t(e->params()[2].toInt()).toUTC(); |
470 | displayMsg(e, Message::Server, tr("[Whois] %1 is logged in since %2" ) |
471 | .arg(e->params()[0], loginTime.toString("yyyy-MM-dd hh:mm:ss UTC" ))); |
472 | } |
473 | QDateTime idlingSince = e->timestamp().toLocalTime().addSecs(-idleSecs).toUTC(); |
474 | displayMsg(e, Message::Server, tr("[Whois] %1 is idling for %2 (since %3)" ) |
475 | .arg(e->params()[0], secondsToString(idleSecs), |
476 | idlingSince.toString("yyyy-MM-dd hh:mm:ss UTC" ))); |
477 | } |
478 | |
479 | |
480 | /* RPL_ENDOFWHOIS - "<nick> :End of WHOIS list" */ |
481 | void EventStringifier::processIrcEvent318(IrcEvent *e) |
482 | { |
483 | _whois = false; |
484 | displayMsg(e, Message::Server, tr("[Whois] End of /WHOIS list" )); |
485 | } |
486 | |
487 | |
488 | /* RPL_WHOISCHANNELS - "<nick> :*( ( "@" / "+" ) <channel> " " )" */ |
489 | void EventStringifier::processIrcEvent319(IrcEvent *e) |
490 | { |
491 | if (!checkParamCount(e, 2)) |
492 | return; |
493 | |
494 | QString nick = e->params().first(); |
495 | QStringList op; |
496 | QStringList voice; |
497 | QStringList user; |
498 | foreach(QString channel, e->params().last().split(" " )) { |
499 | if (channel.startsWith("@" )) |
500 | op.append(channel.remove(0, 1)); |
501 | else if (channel.startsWith("+" )) |
502 | voice.append(channel.remove(0, 1)); |
503 | else |
504 | user.append(channel); |
505 | } |
506 | if (!user.isEmpty()) |
507 | displayMsg(e, Message::Server, tr("[Whois] %1 is a user on channels: %2" ).arg(nick, user.join(" " ))); |
508 | if (!voice.isEmpty()) |
509 | displayMsg(e, Message::Server, tr("[Whois] %1 has voice on channels: %2" ).arg(nick, voice.join(" " ))); |
510 | if (!op.isEmpty()) |
511 | displayMsg(e, Message::Server, tr("[Whois] %1 is an operator on channels: %2" ).arg(nick, op.join(" " ))); |
512 | } |
513 | |
514 | |
515 | /* RPL_LIST - "<channel> <# visible> :<topic>" */ |
516 | void EventStringifier::processIrcEvent322(IrcEvent *e) |
517 | { |
518 | QString channelName; |
519 | quint32 userCount = 0; |
520 | QString topic; |
521 | |
522 | switch (e->params().count()) { |
523 | case 3: |
524 | topic = e->params()[2]; |
525 | case 2: |
526 | userCount = e->params()[1].toUInt(); |
527 | case 1: |
528 | channelName = e->params()[0]; |
529 | default: |
530 | break; |
531 | } |
532 | displayMsg(e, Message::Server, tr("Channel %1 has %2 users. Topic is: \"%3\"" ) |
533 | .arg(channelName).arg(userCount).arg(topic)); |
534 | } |
535 | |
536 | |
537 | /* RPL_LISTEND ":End of LIST" */ |
538 | void EventStringifier::processIrcEvent323(IrcEvent *e) |
539 | { |
540 | displayMsg(e, Message::Server, tr("End of channel list" )); |
541 | } |
542 | |
543 | |
544 | /* RPL_CHANNELMODEIS - "<channel> <mode> <mode params>" */ |
545 | void EventStringifier::processIrcEvent324(IrcEvent *e) |
546 | { |
547 | processIrcEventMode(e); |
548 | } |
549 | |
550 | |
551 | /* RPL_??? - "<channel> <homepage> */ |
552 | void EventStringifier::processIrcEvent328(IrcEvent *e) |
553 | { |
554 | if (!checkParamCount(e, 2)) |
555 | return; |
556 | |
557 | QString channel = e->params()[0]; |
558 | displayMsg(e, Message::Topic, tr("Homepage for %1 is %2" ).arg(channel, e->params()[1]), QString(), channel); |
559 | } |
560 | |
561 | |
562 | /* RPL_??? - "<channel> <creation time (unix)>" */ |
563 | void EventStringifier::processIrcEvent329(IrcEvent *e) |
564 | { |
565 | if (!checkParamCount(e, 2)) |
566 | return; |
567 | |
568 | QString channel = e->params()[0]; |
569 | uint unixtime = e->params()[1].toUInt(); |
570 | if (!unixtime) { |
571 | qWarning() << Q_FUNC_INFO << "received invalid timestamp:" << e->params()[1]; |
572 | return; |
573 | } |
574 | QDateTime time = QDateTime::fromTime_t(unixtime).toUTC(); |
575 | displayMsg(e, Message::Topic, tr("Channel %1 created on %2" ) |
576 | .arg(channel, time.toString("yyyy-MM-dd hh:mm:ss UTC" )), |
577 | QString(), channel); |
578 | } |
579 | |
580 | |
581 | /* RPL_WHOISACCOUNT: "<nick> <account> :is authed as */ |
582 | void EventStringifier::processIrcEvent330(IrcEvent *e) |
583 | { |
584 | if (e->params().count() < 3) |
585 | return; |
586 | |
587 | // check for whois or whowas |
588 | if (_whois) { |
589 | displayMsg(e, Message::Server, tr("[Whois] %1 is authed as %2" ).arg(e->params()[0], e->params()[1])); |
590 | } |
591 | else { |
592 | displayMsg(e, Message::Server, tr("[Whowas] %1 was authed as %2" ).arg(e->params()[0], e->params()[1])); |
593 | } |
594 | } |
595 | |
596 | |
597 | /* RPL_NOTOPIC */ |
598 | void EventStringifier::processIrcEvent331(IrcEvent *e) |
599 | { |
600 | QString channel = e->params().first(); |
601 | displayMsg(e, Message::Topic, tr("No topic is set for %1." ).arg(channel), QString(), channel); |
602 | } |
603 | |
604 | |
605 | /* RPL_TOPIC */ |
606 | void EventStringifier::processIrcEvent332(IrcEvent *e) |
607 | { |
608 | QString channel = e->params().first(); |
609 | displayMsg(e, Message::Topic, tr("Topic for %1 is \"%2\"" ).arg(channel, e->params()[1]), QString(), channel); |
610 | } |
611 | |
612 | |
613 | /* Topic set by... */ |
614 | void EventStringifier::processIrcEvent333(IrcEvent *e) |
615 | { |
616 | if (!checkParamCount(e, 3)) |
617 | return; |
618 | |
619 | QString channel = e->params().first(); |
620 | QDateTime topicSetTime = QDateTime::fromTime_t(e->params()[2].toInt()).toUTC(); |
621 | displayMsg(e, Message::Topic, tr("Topic set by %1 on %2" ) |
622 | .arg(e->params()[1], |
623 | topicSetTime.toString("yyyy-MM-dd hh:mm:ss UTC" )), QString(), channel); |
624 | } |
625 | |
626 | |
627 | /* RPL_INVITING - "<nick> <channel>*/ |
628 | void EventStringifier::processIrcEvent341(IrcEvent *e) |
629 | { |
630 | if (!checkParamCount(e, 2)) |
631 | return; |
632 | |
633 | QString channel = e->params()[1]; |
634 | displayMsg(e, Message::Server, tr("%1 has been invited to %2" ).arg(e->params().first(), channel), QString(), channel); |
635 | } |
636 | |
637 | |
638 | /* RPL_WHOREPLY: "<channel> <user> <host> <server> <nick> |
639 | ( "H" / "G" > ["*"] [ ( "@" / "+" ) ] :<hopcount> <real name>" */ |
640 | void EventStringifier::processIrcEvent352(IrcEvent *e) |
641 | { |
642 | displayMsg(e, Message::Server, tr("[Who] %1" ).arg(e->params().join(" " ))); |
643 | } |
644 | |
645 | |
646 | /* RPL_ENDOFWHOWAS - "<nick> :End of WHOWAS" */ |
647 | void EventStringifier::processIrcEvent369(IrcEvent *e) |
648 | { |
649 | displayMsg(e, Message::Server, tr("End of /WHOWAS" )); |
650 | } |
651 | |
652 | |
653 | /* ERR_ERRONEUSNICKNAME */ |
654 | void EventStringifier::processIrcEvent432(IrcEvent *e) |
655 | { |
656 | if (!checkParamCount(e, 1)) |
657 | return; |
658 | |
659 | displayMsg(e, Message::Error, tr("Nick %1 contains illegal characters" ).arg(e->params()[0])); |
660 | } |
661 | |
662 | |
663 | /* ERR_NICKNAMEINUSE */ |
664 | void EventStringifier::processIrcEvent433(IrcEvent *e) |
665 | { |
666 | if (!checkParamCount(e, 1)) |
667 | return; |
668 | |
669 | displayMsg(e, Message::Error, tr("Nick already in use: %1" ).arg(e->params()[0])); |
670 | } |
671 | |
672 | |
673 | /* ERR_UNAVAILRESOURCE */ |
674 | void EventStringifier::processIrcEvent437(IrcEvent *e) |
675 | { |
676 | if (!checkParamCount(e, 1)) |
677 | return; |
678 | |
679 | displayMsg(e, Message::Error, tr("Nick/channel is temporarily unavailable: %1" ).arg(e->params()[0])); |
680 | } |
681 | |
682 | |
683 | // template |
684 | /* |
685 | |
686 | void EventStringifier::processIrcEvent(IrcEvent *e) { |
687 | |
688 | } |
689 | |
690 | */ |
691 | |
692 | /*******************************/ |
693 | /******** CTCP HANDLING ********/ |
694 | /*******************************/ |
695 | |
696 | void EventStringifier::processCtcpEvent(CtcpEvent *e) |
697 | { |
698 | if (e->type() != EventManager::CtcpEvent) |
699 | return; |
700 | |
701 | if (e->testFlag(EventManager::Self)) { |
702 | displayMsg(e, Message::Action, tr("sending CTCP-%1 request to %2" ).arg(e->ctcpCmd(), e->target()), e->network()->myNick()); |
703 | return; |
704 | } |
705 | |
706 | handle(e->ctcpCmd(), Q_ARG(CtcpEvent *, e)); |
707 | } |
708 | |
709 | |
710 | void EventStringifier::defaultHandler(const QString &ctcpCmd, CtcpEvent *e) |
711 | { |
712 | Q_UNUSED(ctcpCmd); |
713 | if (e->ctcpType() == CtcpEvent::Query) { |
714 | QString unknown; |
715 | if (e->reply().isNull()) // all known core-side handlers (except for ACTION) set a reply! |
716 | //: Optional "unknown" in "Received unknown CTCP-FOO request by bar" |
717 | unknown = tr("unknown" ) + ' '; |
718 | displayMsg(e, Message::Server, tr("Received %1CTCP-%2 request by %3" ).arg(unknown, e->ctcpCmd(), e->prefix())); |
719 | return; |
720 | } |
721 | displayMsg(e, Message::Server, tr("Received CTCP-%1 answer from %2: %3" ).arg(e->ctcpCmd(), nickFromMask(e->prefix()), e->param())); |
722 | } |
723 | |
724 | |
725 | void EventStringifier::handleCtcpAction(CtcpEvent *e) |
726 | { |
727 | displayMsg(e, Message::Action, e->param(), e->prefix(), e->target()); |
728 | } |
729 | |
730 | |
731 | void EventStringifier::handleCtcpPing(CtcpEvent *e) |
732 | { |
733 | if (e->ctcpType() == CtcpEvent::Query) |
734 | defaultHandler(e->ctcpCmd(), e); |
735 | else { |
736 | #if QT_VERSION >= 0x040700 |
737 | displayMsg(e, Message::Server, tr("Received CTCP-PING answer from %1 with %2 milliseconds round trip time" ) |
738 | .arg(nickFromMask(e->prefix())).arg(QDateTime::fromMSecsSinceEpoch(e->param().toULongLong()).msecsTo(e->timestamp()))); |
739 | #else |
740 | displayMsg(e, Message::Server, tr("Received CTCP-PING answer from %1 with %2 seconds round trip time" ) |
741 | .arg(nickFromMask(e->prefix())).arg(QDateTime::fromTime_t(e->param().toInt()).secsTo(e->timestamp()))); |
742 | #endif |
743 | } |
744 | } |
745 | |