X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fircparser.cpp;h=d5f5295431a509763ed8650a2548b0592afb8d23;hp=f5b37840f54ee62aa9f60fb03aaee3e8d6f98d56;hb=e38846f054ad1766f2e91992a57bbaffd33c7c06;hpb=53e50ab66a5b3fa00282545ebc22ce3433ecf42b diff --git a/src/core/ircparser.cpp b/src/core/ircparser.cpp index f5b37840..d5f52954 100644 --- a/src/core/ircparser.cpp +++ b/src/core/ircparser.cpp @@ -26,6 +26,7 @@ #include "eventmanager.h" #include "ircdecoder.h" #include "ircevent.h" +#include "irctags.h" #include "messageevent.h" #include "networkevent.h" @@ -41,6 +42,9 @@ IrcParser::IrcParser(CoreSession* session) // Check if raw IRC logging is enabled _debugLogRawIrc = (Quassel::isOptionSet("debug-irc") || Quassel::isOptionSet("debug-irc-id")); _debugLogRawNetId = Quassel::optionValue("debug-irc-id").toInt(); + // Check if parsed IRC logging is enabled + _debugLogParsedIrc = (Quassel::isOptionSet("debug-irc-parsed") || Quassel::isOptionSet("debug-irc-parsed-id")); + _debugLogParsedNetId = Quassel::optionValue("debug-irc-parsed-id").toInt(); connect(this, &IrcParser::newEvent, coreSession()->eventManager(), &EventManager::postEvent); } @@ -109,6 +113,23 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e) return net->serverDecode(data); }, rawMsg, tags, prefix, cmd, params); + // Log the message if enabled and network ID matches or allows all + if (_debugLogParsedIrc && (_debugLogParsedNetId == -1 || net->networkId().toInt() == _debugLogParsedNetId)) { + // Include network ID + qDebug() << "IRC net" << net->networkId() << "<<" << tags << prefix << cmd << params; + } + + IrcTagKey serverTimeTag{"", "time", false}; + if (tags.contains(serverTimeTag)) { + QDateTime serverTime = QDateTime::fromString(tags[serverTimeTag], "yyyy-MM-ddThh:mm:ss.zzzZ"); + serverTime.setTimeSpec(Qt::UTC); + if (serverTime.isValid()) { + e->setTimestamp(serverTime); + } else { + qDebug() << "Invalid timestamp from server-time tag:" << tags[serverTimeTag]; + } + } + QList events; EventManager::EventType type = EventManager::Invalid; @@ -169,6 +190,7 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e) IrcEventRawMessage* rawMessage = new IrcEventRawMessage(EventManager::IrcEventRawPrivmsg, net, + tags, msg, prefix, target, @@ -236,16 +258,17 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e) // Don't allow key exchange in channels, and don't allow it for self-messages. bool keyExchangeAllowed = (!net->isChannelName(target) && !isSelfMessage); if (params[1].startsWith("DH1080_INIT") && keyExchangeAllowed) { - events << new KeyEvent(EventManager::KeyEvent, net, prefix, target, KeyEvent::Init, params[1].mid(12)); + events << new KeyEvent(EventManager::KeyEvent, net, tags, prefix, target, KeyEvent::Init, params[1].mid(12)); } else if (params[1].startsWith("DH1080_FINISH") && keyExchangeAllowed) { - events << new KeyEvent(EventManager::KeyEvent, net, prefix, target, KeyEvent::Finish, params[1].mid(14)); + events << new KeyEvent(EventManager::KeyEvent, net, tags, prefix, target, KeyEvent::Finish, params[1].mid(14)); } else #endif { IrcEventRawMessage* rawMessage = new IrcEventRawMessage(EventManager::IrcEventRawNotice, net, + tags, params[1], prefix, target, @@ -260,7 +283,7 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e) } break; - // the following events need only special casing for param decoding + // the following events need only special casing for param decoding case EventManager::IrcEventKick: if (params.count() >= 3) { // we have a reason decParams << net->serverDecode(params.at(0)) << net->serverDecode(params.at(1)); @@ -284,6 +307,34 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e) } break; + case EventManager::IrcEventTagmsg: + defaultHandling = false; // this might create a list of events + + if (checkParamCount(cmd, params, 1)) { + QString senderNick = nickFromMask(prefix); + net->updateNickFromMask(prefix); + // Check if the sender is our own nick. If so, treat message as if sent by ourself. + // See http://ircv3.net/specs/extensions/echo-message-3.2.html + // Cache the result to avoid multiple redundant comparisons + bool isSelfMessage = net->isMyNick(senderNick); + + QStringList targets = net->serverDecode(params.at(0)).split(',', QString::SkipEmptyParts); + QStringList::const_iterator targetIter; + for (targetIter = targets.constBegin(); targetIter != targets.constEnd(); ++targetIter) { + // For self-messages, keep the target, don't set it to the senderNick + QString target = net->isChannelName(*targetIter) || net->isStatusMsg(*targetIter) || isSelfMessage ? *targetIter : senderNick; + + IrcEvent* tagMsg = new IrcEvent(EventManager::IrcEventTagmsg, net, tags, prefix, {target}); + if (isSelfMessage) { + // Self-messages need processed differently, tag as such via flag. + tagMsg->setFlag(EventManager::Self); + } + tagMsg->setTimestamp(e->timestamp()); + events << tagMsg; + } + } + break; + case EventManager::IrcEventTopic: if (params.count() >= 1) { QString channel = net->serverDecode(params.at(0)); @@ -292,15 +343,17 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e) } break; - case EventManager::IrcEventAway: { - // Update hostmask info first. This will create the nick if it doesn't exist, e.g. - // away-notify data being sent before JOIN messages. - net->updateNickFromMask(prefix); - // Separate nick in order to separate server and user decoding - QString nick = nickFromMask(prefix); - decParams << nick; - decParams << (params.count() >= 1 ? net->userDecode(nick, params.at(0)) : QString()); - } break; + case EventManager::IrcEventAway: + { + // Update hostmask info first. This will create the nick if it doesn't exist, e.g. + // away-notify data being sent before JOIN messages. + net->updateNickFromMask(prefix); + // Separate nick in order to separate server and user decoding + QString nick = nickFromMask(prefix); + decParams << nick; + decParams << (params.count() >= 1 ? net->userDecode(nick, params.at(0)) : QString()); + } + break; case EventManager::IrcEventNumeric: switch (num) { @@ -359,15 +412,15 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e) IrcEvent* event; if (type == EventManager::IrcEventNumeric) - event = new IrcEventNumeric(num, net, prefix, messageTarget); + event = new IrcEventNumeric(num, net, tags, prefix, messageTarget); else - event = new IrcEvent(type, net, prefix); + event = new IrcEvent(type, net, tags, prefix); event->setParams(decParams); event->setTimestamp(e->timestamp()); events << event; } - foreach (Event* event, events) { + for (Event* event : events) { emit newEvent(event); } }