Cleanup allowing for tags to be available at later points, adds TAGMSG
authorJanne Koschinski <janne@kuschku.de>
Fri, 15 Feb 2019 13:32:31 +0000 (14:32 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Thu, 30 May 2019 20:59:25 +0000 (22:59 +0200)
17 files changed:
src/common/CMakeLists.txt
src/common/ctcpevent.h
src/common/eventmanager.h
src/common/ircevent.h
src/common/irctags.h [moved from src/core/irctags.h with 100% similarity]
src/common/message.cpp
src/common/messageevent.cpp
src/common/messageevent.h
src/core/CMakeLists.txt
src/core/coresession.h
src/core/coresessioneventprocessor.cpp
src/core/ctcpparser.cpp
src/core/ctcpparser.h
src/core/eventstringifier.cpp
src/core/eventstringifier.h
src/core/ircparser.cpp
src/core/keyevent.h

index 417e5ff..000b772 100644 (file)
@@ -28,6 +28,7 @@ target_sources(${TARGET} PRIVATE
     ircdecoder.cpp
     ircencoder.cpp
     irctag.cpp
+    irctags.h
     ircuser.cpp
     logger.cpp
     message.cpp
index a6c5462..dec8ba3 100644 (file)
@@ -39,14 +39,15 @@ public:
 
     explicit CtcpEvent(EventManager::EventType type,
                        Network* network,
-                       const QString& prefix,
+                       QHash<IrcTagKey, QString> tags,
+                       QString prefix,
                        QString target,
                        CtcpType ctcpType,
                        QString ctcpCmd,
                        QString param,
                        const QDateTime& timestamp = QDateTime(),
                        const QUuid& uuid = QUuid())
-        : IrcEvent(type, network, prefix)
+        : IrcEvent(type, network, std::move(tags), std::move(prefix))
         , _ctcpType(ctcpType)
         , _ctcpCmd(std::move(ctcpCmd))
         , _target(std::move(target))
@@ -84,9 +85,12 @@ protected:
     inline void debugInfo(QDebug& dbg) const override
     {
         NetworkEvent::debugInfo(dbg);
-        dbg << ", prefix = " << qPrintable(prefix()) << ", target = " << qPrintable(target())
-            << ", ctcptype = " << (ctcpType() == Query ? "query" : "reply") << ", cmd = " << qPrintable(ctcpCmd())
-            << ", param = " << qPrintable(param()) << ", reply = " << qPrintable(reply());
+        dbg << ", prefix = " << qPrintable(prefix())
+            << ", target = " << qPrintable(target())
+            << ", ctcptype = " << (ctcpType() == Query ? "query" : "reply")
+            << ", cmd = " << qPrintable(ctcpCmd())
+            << ", param = " << qPrintable(param())
+            << ", reply = " << qPrintable(reply());
     }
 
 private:
index d1059cf..e4ddb3b 100644 (file)
@@ -107,6 +107,7 @@ public:
         IrcEventPong,
         IrcEventPrivmsg,
         IrcEventQuit,
+        IrcEventTagmsg,
         IrcEventTopic,
         IrcEventError,  /// ERROR message from server
         IrcEventWallops,
index 7988437..90dc384 100644 (file)
 
 #include <utility>
 
+#include "irctag.h"
 #include "networkevent.h"
 #include "util.h"
 
 class COMMON_EXPORT IrcEvent : public NetworkEvent
 {
 public:
-    explicit IrcEvent(EventManager::EventType type, Network* network, QString prefix, QStringList params = QStringList())
+    explicit IrcEvent(
+        EventManager::EventType type, Network* network, QHash<IrcTagKey, QString> tags, QString prefix, QStringList params = {})
         : NetworkEvent(type, network)
+        , _tags(std::move(tags))
         , _prefix(std::move(prefix))
         , _params(std::move(params))
     {}
@@ -39,6 +42,9 @@ public:
     inline QString prefix() const { return _prefix; }
     inline void setPrefix(const QString& prefix) { _prefix = prefix; }
 
+    inline QHash<IrcTagKey, QString> tags() const { return _tags; }
+    inline void setTags(const QHash<IrcTagKey, QString>& tags) { _tags = tags; }
+
     inline QString nick() const { return nickFromMask(prefix()); }
 
     inline QStringList params() const { return _params; }
@@ -58,6 +64,7 @@ protected:
     }
 
 private:
+    QHash<IrcTagKey, QString> _tags;
     QString _prefix;
     QStringList _params;
 };
@@ -65,8 +72,13 @@ private:
 class COMMON_EXPORT IrcEventNumeric : public IrcEvent
 {
 public:
-    explicit IrcEventNumeric(uint number, Network* network, const QString& prefix, QString target, const QStringList& params = QStringList())
-        : IrcEvent(EventManager::IrcEventNumeric, network, prefix, params)
+    explicit IrcEventNumeric(uint number,
+                             Network* network,
+                             QHash<IrcTagKey, QString> tags,
+                             QString prefix,
+                             QString target,
+                             QStringList params = {})
+        : IrcEvent(EventManager::IrcEventNumeric, network, std::move(tags), std::move(prefix), std::move(params))
         , _number(number)
         , _target(std::move(target))
     {}
@@ -85,7 +97,9 @@ protected:
     {
         dbg << ", num = " << number();
         NetworkEvent::debugInfo(dbg);
-        dbg << ", target = " << qPrintable(target()) << ", prefix = " << qPrintable(prefix()) << ", params = " << params();
+        dbg << ", target = " << qPrintable(target())
+            << ", prefix = " << qPrintable(prefix())
+            << ", params = " << params();
     }
 
 private:
@@ -98,13 +112,14 @@ private:
 class COMMON_EXPORT IrcEventRawMessage : public IrcEvent
 {
 public:
-    explicit inline IrcEventRawMessage(EventManager::EventType type,
-                                       Network* network,
-                                       QByteArray rawMessage,
-                                       const QString& prefix,
-                                       const QString& target,
-                                       const QDateTime& timestamp = QDateTime())
-        : IrcEvent(type, network, prefix, QStringList() << target)
+    explicit IrcEventRawMessage(EventManager::EventType type,
+                                Network* network,
+                                QHash<IrcTagKey, QString> tags,
+                                QByteArray rawMessage,
+                                QString prefix,
+                                QString target,
+                                const QDateTime& timestamp = QDateTime())
+        : IrcEvent(type, network, std::move(tags), std::move(prefix), QStringList() << target)
         , _rawMessage(std::move(rawMessage))
     {
         setTimestamp(timestamp);
@@ -124,7 +139,9 @@ protected:
     inline void debugInfo(QDebug& dbg) const override
     {
         NetworkEvent::debugInfo(dbg);
-        dbg << ", target = " << qPrintable(target()) << ", prefix = " << qPrintable(prefix()) << ", msg = " << rawMessage();
+        dbg << ", target = " << qPrintable(target())
+            << ", prefix = " << qPrintable(prefix())
+            << ", msg = " << rawMessage();
     }
 
 private:
similarity index 100%
rename from src/core/irctags.h
rename to src/common/irctags.h
index 2aa3e30..1367b40 100644 (file)
  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
  ***************************************************************************/
 
-#include "message.h"
-
 #include <utility>
 
 #include <QDataStream>
 
+#include "message.h"
 #include "peer.h"
 #include "signalproxy.h"
 #include "util.h"
 
-Message::Message(
-    BufferInfo bufferInfo, Type type, QString contents, QString sender, QString senderPrefixes, QString realName, QString avatarUrl, Flags flags)
+Message::Message(BufferInfo bufferInfo,
+                 Type type,
+                 QString contents,
+                 QString sender,
+                 QString senderPrefixes,
+                 QString realName,
+                 QString avatarUrl,
+                 Flags flags)
     : _timestamp(QDateTime::currentDateTime().toUTC())
     , _bufferInfo(std::move(bufferInfo))
     , _contents(std::move(contents))
@@ -71,13 +76,16 @@ QDataStream& operator<<(QDataStream& out, const Message& msg)
 
     if (SignalProxy::current()->targetPeer()->hasFeature(Quassel::Feature::LongTime)) {
         // toMSecs returns a qint64, signed rather than unsigned
-        out << (qint64)msg.timestamp().toMSecsSinceEpoch();
+        out << (qint64) msg.timestamp().toMSecsSinceEpoch();
     }
     else {
-        out << (quint32)msg.timestamp().toTime_t();
+        out << (quint32) msg.timestamp().toTime_t();
     }
 
-    out << (quint32)msg.type() << (quint8)msg.flags() << msg.bufferInfo() << msg.sender().toUtf8();
+    out << (quint32) msg.type()
+        << (quint8) msg.flags()
+        << msg.bufferInfo()
+        << msg.sender().toUtf8();
 
     if (SignalProxy::current()->targetPeer()->hasFeature(Quassel::Feature::SenderPrefixes))
         out << msg.senderPrefixes().toUtf8();
@@ -147,9 +155,14 @@ QDataStream& operator>>(QDataStream& in, Message& msg)
 
 QDebug operator<<(QDebug dbg, const Message& msg)
 {
-    dbg.nospace() << qPrintable(QString("Message(MsgId:")) << msg.msgId() << qPrintable(QString(",")) << msg.timestamp()
-                  << qPrintable(QString(", Type:")) << msg.type() << qPrintable(QString(", RealName:")) << msg.realName()
-                  << qPrintable(QString(", AvatarURL:")) << msg.avatarUrl() << qPrintable(QString(", Flags:")) << msg.flags()
-                  << qPrintable(QString(")")) << msg.senderPrefixes() << msg.sender() << ":" << msg.contents();
+    dbg.nospace() << qPrintable(QString("Message(MsgId:")) << msg.msgId()
+                  << qPrintable(QString(",")) << msg.timestamp()
+                  << qPrintable(QString(", Type:")) << msg.type()
+                  << qPrintable(QString(", RealName:")) << msg.realName()
+                  << qPrintable(QString(", AvatarURL:")) << msg.avatarUrl()
+                  << qPrintable(QString(", Flags:")) << msg.flags()
+                  << qPrintable(QString(")"))
+                  << msg.senderPrefixes() << msg.sender() << ":"
+                  << msg.contents();
     return dbg;
 }
index 193e489..1b86070 100644 (file)
@@ -30,12 +30,17 @@ Event* MessageEvent::create(EventManager::EventType type, QVariantMap& map, Netw
     return nullptr;
 }
 
-MessageEvent::MessageEvent(
-    Message::Type msgType, Network* net, QString msg, const QString& sender, QString target, Message::Flags flags, const QDateTime& timestamp)
+MessageEvent::MessageEvent(Message::Type msgType,
+                           Network* net,
+                           QString msg,
+                           QString sender,
+                           QString target,
+                           Message::Flags flags,
+                           const QDateTime& timestamp)
     : NetworkEvent(EventManager::MessageEvent, net)
     , _msgType(msgType)
     , _text(std::move(msg))
-    , _sender(sender)
+    , _sender(std::move(sender))
     , _target(std::move(target))
     , _msgFlags(flags)
 {
@@ -45,7 +50,7 @@ MessageEvent::MessageEvent(
             _target = _target.mid(1);
 
         if (_target.startsWith('$') || _target.startsWith('#'))
-            _target = nickFromMask(sender);
+            _target = nickFromMask(_sender);
     }
 
     _bufferType = bufferTypeByTarget(_target);
@@ -71,7 +76,7 @@ void MessageEvent::toVariantMap(QVariantMap& map) const
 {
     NetworkEvent::toVariantMap(map);
     map["messageType"] = msgType();
-    map["messageFlags"] = (int)msgFlags();
+    map["messageFlags"] = (int) msgFlags();
     map["bufferType"] = bufferType();
     map["text"] = text();
     map["sender"] = sender();
index 8ac668d..f8d636f 100644 (file)
@@ -34,10 +34,10 @@ public:
     explicit MessageEvent(Message::Type msgType,
                           Network* network,
                           QString msg,
-                          const QString& sender = QString(),
-                          QString target = QString(),
+                          QString sender = {},
+                          QString target = {},
                           Message::Flags msgFlags = Message::None,
-                          const QDateTime& timestamp = QDateTime());
+                          const QDateTime& timestamp = {});
 
     inline Message::Type msgType() const { return _msgType; }
     inline void setMsgType(Message::Type type) { _msgType = type; }
index 2e9199a..a4cc809 100644 (file)
@@ -32,7 +32,6 @@ target_sources(${TARGET} PRIVATE
     eventstringifier.cpp
     identserver.cpp
     ircparser.cpp
-    irctags.h
     netsplit.cpp
     oidentdconfiggenerator.cpp
     postgresqlstorage.cpp
index 5a05f02..d44a9c4 100644 (file)
@@ -289,7 +289,12 @@ struct NetworkInternalMessage
     QString text;
     QString sender;
     Message::Flags flags;
-    NetworkInternalMessage(Message::Type type, BufferInfo::Type bufferType, QString target, QString text, QString sender = "", Message::Flags flags = Message::None)
+    NetworkInternalMessage(Message::Type type,
+                           BufferInfo::Type bufferType,
+                           QString target,
+                           QString text,
+                           QString sender = "",
+                           Message::Flags flags = Message::None)
         : type(type)
         , bufferType(bufferType)
         , target(std::move(target))
@@ -308,8 +313,14 @@ struct RawMessage
     QString text;
     QString sender;
     Message::Flags flags;
-    RawMessage(
-        NetworkId networkId, Message::Type type, BufferInfo::Type bufferType, QString target, QString text, QString sender, Message::Flags flags)
+
+    RawMessage(NetworkId networkId,
+               Message::Type type,
+               BufferInfo::Type bufferType,
+               QString target,
+               QString text,
+               QString sender,
+               Message::Flags flags)
         : networkId(networkId)
         , type(type)
         , bufferType(bufferType)
@@ -319,7 +330,8 @@ struct RawMessage
         , flags(flags)
     {}
 
-    RawMessage(NetworkId networkId, const NetworkInternalMessage& msg)
+    RawMessage(NetworkId networkId,
+               const NetworkInternalMessage& msg)
         : networkId(networkId)
         , type(msg.type)
         , bufferType(msg.bufferType)
index c1807ab..af30bfb 100644 (file)
@@ -1469,7 +1469,7 @@ void CoreSessionEventProcessor::handleEarlyNetsplitJoin(Network* net, const QStr
         if (ircUser) {
             ircUsers.append(ircUser);
             // fake event for scripts that consume join events
-            events << new IrcEvent(EventManager::IrcEventJoin, net, ircUser->hostmask(), QStringList() << channel);
+            events << new IrcEvent(EventManager::IrcEventJoin, net, {}, ircUser->hostmask(), QStringList() << channel);
         }
         else {
             newModes.removeAt(users.indexOf(user));
index 8f2384d..dc8ceff 100644 (file)
@@ -24,6 +24,7 @@
 #include "coresession.h"
 #include "coreuserinputhandler.h"
 #include "ctcpevent.h"
+#include "irctags.h"
 #include "messageevent.h"
 
 const QByteArray XDELIM = "\001";
@@ -54,15 +55,17 @@ void CtcpParser::setStandardCtcp(bool enabled)
     _ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
 }
 
-void CtcpParser::displayMsg(
-    NetworkEvent* event, Message::Type msgType, const QString& msg, const QString& sender, const QString& target, Message::Flags msgFlags)
+void CtcpParser::displayMsg(NetworkEvent* event,
+                            Message::Type msgType,
+                            QString msg,
+                            QString sender,
+                            QString target,
+                            Message::Flags msgFlags)
 {
     if (event->testFlag(EventManager::Silent))
         return;
 
-    MessageEvent* msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags);
-    msgEvent->setTimestamp(event->timestamp());
-
+    MessageEvent* msgEvent = new MessageEvent(msgType, event->network(), std::move(msg), std::move(sender), std::move(target), msgFlags, event->timestamp());
     emit newEvent(msgEvent);
 }
 
@@ -192,8 +195,11 @@ void CtcpParser::parse(IrcEventRawMessage* e, Message::Type messagetype)
 
 // only accept CTCPs in their simplest form, i.e. one ctcp, from start to
 // end, no text around it; not as per the 'specs', but makes people happier
-void CtcpParser::parseSimple(
-    IrcEventRawMessage* e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags)
+void CtcpParser::parseSimple(IrcEventRawMessage* e,
+                             Message::Type messagetype,
+                             const QByteArray& dequotedMessage,
+                             CtcpEvent::CtcpType ctcptype,
+                             Message::Flags flags)
 {
     if (dequotedMessage.count(XDELIM) != 2 || dequotedMessage[0] != '\001' || dequotedMessage[dequotedMessage.count() - 1] != '\001') {
         displayMsg(e, messagetype, targetDecode(e, dequotedMessage), e->prefix(), e->target(), flags);
@@ -214,13 +220,15 @@ void CtcpParser::parseSimple(
         }
         ctcpcmd = ctcpcmd.toUpper();
 
+        bool isAction = ctcpcmd == QLatin1String("ACTION");
         // we don't want to block /me messages by the CTCP ignore list
-        if (ctcpcmd == QLatin1String("ACTION")
+        if (isAction
             || !coreSession()->ignoreListManager()->ctcpMatch(e->prefix(), e->network()->networkName(), ctcpcmd)) {
             QUuid uuid = QUuid::createUuid();
             _replies.insert(uuid, CtcpReply(coreNetwork(e), nickFromMask(e->prefix())));
             CtcpEvent* event = new CtcpEvent(EventManager::CtcpEvent,
                                              e->network(),
+                                             isAction ? QHash<IrcTagKey, QString>() : e->tags(),
                                              e->prefix(),
                                              e->target(),
                                              ctcptype,
@@ -231,6 +239,7 @@ void CtcpParser::parseSimple(
             emit newEvent(event);
             CtcpEvent* flushEvent = new CtcpEvent(EventManager::CtcpEventFlush,
                                                   e->network(),
+                                                  {},
                                                   e->prefix(),
                                                   e->target(),
                                                   ctcptype,
@@ -243,9 +252,13 @@ void CtcpParser::parseSimple(
     }
 }
 
-void CtcpParser::parseStandard(
-    IrcEventRawMessage* e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags)
+void CtcpParser::parseStandard(IrcEventRawMessage* e,
+                               Message::Type messagetype,
+                               const QByteArray& dequotedMessage_,
+                               CtcpEvent::CtcpType ctcptype,
+                               Message::Flags flags)
 {
+    auto dequotedMessage = dequotedMessage_;
     QByteArray ctcp;
 
     QList<CtcpEvent*> ctcpEvents;
@@ -283,14 +296,16 @@ void CtcpParser::parseStandard(
 
         ctcpcmd = ctcpcmd.toUpper();
 
+        bool isAction = ctcpcmd == QLatin1String("ACTION");
         // we don't want to block /me messages by the CTCP ignore list
-        if (ctcpcmd == QLatin1String("ACTION")
+        if (isAction
             || !coreSession()->ignoreListManager()->ctcpMatch(e->prefix(), e->network()->networkName(), ctcpcmd)) {
             if (uuid.isNull())
                 uuid = QUuid::createUuid();
 
             CtcpEvent* event = new CtcpEvent(EventManager::CtcpEvent,
                                              e->network(),
+                                             isAction ? QHash<IrcTagKey, QString>() : e->tags(),
                                              e->prefix(),
                                              e->target(),
                                              ctcptype,
@@ -305,6 +320,7 @@ void CtcpParser::parseStandard(
         _replies.insert(uuid, CtcpReply(coreNetwork(e), nickFromMask(e->prefix())));
         CtcpEvent* flushEvent = new CtcpEvent(EventManager::CtcpEventFlush,
                                               e->network(),
+                                              {},
                                               e->prefix(),
                                               e->target(),
                                               ctcptype,
@@ -313,7 +329,7 @@ void CtcpParser::parseStandard(
                                               e->timestamp(),
                                               uuid);
         ctcpEvents << flushEvent;
-        foreach (CtcpEvent* event, ctcpEvents) {
+        for (CtcpEvent* event : ctcpEvents) {
             emit newEvent(event);
         }
     }
index 81f1886..0eac1b7 100644 (file)
@@ -60,16 +60,22 @@ protected:
     //! Creates and sends a MessageEvent
     void displayMsg(NetworkEvent* event,
                     Message::Type msgType,
-                    const QString& msg,
-                    const QString& sender = QString(),
-                    const QString& target = QString(),
+                    QString msg,
+                    QString sender = {},
+                    QString target = {},
                     Message::Flags msgFlags = Message::None);
 
     void parse(IrcEventRawMessage* event, Message::Type msgType);
-    void parseSimple(
-        IrcEventRawMessage* e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags);
-    void parseStandard(
-        IrcEventRawMessage* e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags);
+    void parseSimple(IrcEventRawMessage* e,
+                     Message::Type messagetype,
+                     const QByteArray& dequotedMessage,
+                     CtcpEvent::CtcpType ctcptype,
+                     Message::Flags flags);
+    void parseStandard(IrcEventRawMessage* e,
+                       Message::Type messagetype,
+                       const QByteArray& dequotedMessage,
+                       CtcpEvent::CtcpType ctcptype,
+                       Message::Flags flags);
 
     QByteArray lowLevelQuote(const QByteArray&);
     QByteArray lowLevelDequote(const QByteArray&);
index b575322..d4c268c 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "coresession.h"
 #include "ctcpevent.h"
+#include "irctags.h"
 #include "messageevent.h"
 
 EventStringifier::EventStringifier(CoreSession* parent)
@@ -32,22 +33,29 @@ EventStringifier::EventStringifier(CoreSession* parent)
     connect(this, &EventStringifier::newMessageEvent, coreSession()->eventManager(), &EventManager::postEvent);
 }
 
-void EventStringifier::displayMsg(
-    NetworkEvent* event, Message::Type msgType, const QString& msg, const QString& sender, const QString& target, Message::Flags msgFlags)
+void EventStringifier::displayMsg(NetworkEvent* event,
+                                  Message::Type msgType,
+                                  QString msg,
+                                  QString sender,
+                                  QString target,
+                                  Message::Flags msgFlags)
 {
     if (event->flags().testFlag(EventManager::Silent))
         return;
 
-    MessageEvent* msgEvent = createMessageEvent(event, msgType, msg, sender, target, msgFlags);
+    MessageEvent* msgEvent = createMessageEvent(event, msgType, std::move(msg), std::move(sender), std::move(target), msgFlags);
     // sendMessageEvent(msgEvent);
     emit newMessageEvent(msgEvent);
 }
 
-MessageEvent* EventStringifier::createMessageEvent(
-    NetworkEvent* event, Message::Type msgType, const QString& msg, const QString& sender, const QString& target, Message::Flags msgFlags)
+MessageEvent* EventStringifier::createMessageEvent(NetworkEvent* event,
+                                                   Message::Type msgType,
+                                                   QString msg,
+                                                   QString sender,
+                                                   QString target,
+                                                   Message::Flags msgFlags)
 {
-    MessageEvent* msgEvent = new MessageEvent(msgType, event->network(), msg, sender, target, msgFlags);
-    msgEvent->setTimestamp(event->timestamp());
+    MessageEvent* msgEvent = new MessageEvent(msgType, event->network(), std::move(msg), std::move(sender), std::move(target), msgFlags, event->timestamp());
     return msgEvent;
 }
 
@@ -59,7 +67,7 @@ bool EventStringifier::checkParamCount(IrcEvent* e, int minParams)
                        << "params, got: " << e->params();
         }
         else {
-            QString name = coreSession()->eventManager()->enumName(e->type());
+            QString name = EventManager::enumName(e->type());
             qWarning() << qPrintable(name) << "requires" << minParams << "params, got:" << e->params();
         }
         e->stop();
@@ -328,7 +336,7 @@ void EventStringifier::processIrcEventNick(IrcEvent* e)
     }
 
     // Announce to all channels the IrcUser is in
-    foreach (const QString& channel, ircuser->channels()) {
+    for (const QString& channel : ircuser->channels()) {
         displayMsg(e, Message::Nick, newnick, sender, channel, msgFlags);
     }
 }
@@ -375,7 +383,7 @@ void EventStringifier::processIrcEventQuit(IrcEvent* e)
     }
 
     // Announce to all channels the IrcUser is in
-    foreach (const QString& channel, ircuser->channels()) {
+    for (const QString& channel : ircuser->channels()) {
         displayMsg(e, Message::Quit, e->params().count() ? e->params().first() : QString(), e->prefix(), channel, msgFlags);
     }
 }
@@ -528,9 +536,10 @@ void EventStringifier::processIrcEvent317(IrcEvent* e)
 {
     int idleSecs = e->params()[1].toInt();
 
-    if (e->params().count() > 3) {  // if we have more then 3 params we have the above mentioned "real life" situation
-                                    // Time in IRC protocol is defined as seconds.  Convert from seconds instead.
-                                    // See https://doc.qt.io/qt-5/qdatetime.html#fromSecsSinceEpoch
+    if (e->params().count() > 3) {
+        // if we have more then 3 params we have the above mentioned "real life" situation
+        // Time in IRC protocol is defined as seconds.  Convert from seconds instead.
+        // See https://doc.qt.io/qt-5/qdatetime.html#fromSecsSinceEpoch
 #if QT_VERSION >= 0x050800
         QDateTime loginTime = QDateTime::fromSecsSinceEpoch(e->params()[2].toLongLong()).toUTC();
 #else
@@ -566,7 +575,7 @@ void EventStringifier::processIrcEvent319(IrcEvent* e)
     QStringList op;
     QStringList voice;
     QStringList user;
-    foreach (QString channel, e->params().last().split(" ")) {
+    for (QString channel : e->params().last().split(" ")) {
         if (channel.startsWith("@"))
             op.append(channel.remove(0, 1));
         else if (channel.startsWith("+"))
index 504ff13..d1274ed 100644 (file)
@@ -43,9 +43,9 @@ public:
 
     MessageEvent* createMessageEvent(NetworkEvent* event,
                                      Message::Type msgType,
-                                     const QString& msg,
-                                     const QString& sender = QString(),
-                                     const QString& target = QString(),
+                                     QString msg,
+                                     QString sender = {},
+                                     QString target = {},
                                      Message::Flags msgFlags = Message::None);
 
     // legacy handlers
@@ -108,9 +108,9 @@ public slots:
     //! Creates and sends a MessageEvent
     void displayMsg(NetworkEvent* event,
                     Message::Type msgType,
-                    const QString& msg,
-                    const QString& sender = QString(),
-                    const QString& target = QString(),
+                    QString msg,
+                    QString sender = {},
+                    QString target = {},
                     Message::Flags msgFlags = Message::None);
 
 signals:
index 8a6a7eb..2add78d 100644 (file)
@@ -179,6 +179,7 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent* e)
 
                 IrcEventRawMessage* rawMessage = new IrcEventRawMessage(EventManager::IrcEventRawPrivmsg,
                                                                         net,
+                                                                        tags,
                                                                         msg,
                                                                         prefix,
                                                                         target,
@@ -246,16 +247,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,
@@ -270,7 +272,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));
@@ -294,6 +296,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));
@@ -302,15 +332,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) {
@@ -369,15 +401,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);
     }
 }
index 393f4d2..c1c6cc2 100644 (file)
@@ -36,12 +36,13 @@ public:
 
     explicit KeyEvent(EventManager::EventType type,
                       Network* network,
-                      const QString& prefix,
+                      QHash<IrcTagKey, QString> tags,
+                      QString prefix,
                       QString target,
                       ExchangeType exchangeType,
                       QByteArray key,
                       const QDateTime& timestamp = QDateTime())
-        : IrcEvent(type, network, prefix)
+        : IrcEvent(type, network, std::move(tags), std::move(prefix))
         , _exchangeType(exchangeType)
         , _target(std::move(target))
         , _key(std::move(key))