]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Add support for the IRCv3 message id specification.
authorPeter Powell <petpow@saberuk.com>
Wed, 15 May 2019 09:33:42 +0000 (10:33 +0100)
committerPeter Powell <petpow@saberuk.com>
Wed, 15 May 2019 09:34:01 +0000 (10:34 +0100)
docs/conf/modules.conf.example
src/modules/m_ircv3_msgid.cpp [new file with mode: 0644]

index 8dcdd7d3db0e52a896de0eac566117f8cdca95e8..bb8a74dbc9a1ecf65a3a2863ce36a44ea3e830de 100644 (file)
 # another user into a channel. This respects <options:announceinvites>.
 #<module name="ircv3_invitenotify">
 
+#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
+# IRCv3 message id module: Provides the msgid IRCv3 extension which
+# adds a unique identifier to each message when the message-tags cap
+# has been requested. This enables support for modern features such as
+# reactions and replies.
+#<module name="ircv3_msgid">
+
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 # IRCv3 server-time module. Adds the 'time' tag which adds a timestamp
 # to all messages received from the server.
diff --git a/src/modules/m_ircv3_msgid.cpp b/src/modules/m_ircv3_msgid.cpp
new file mode 100644 (file)
index 0000000..4d34455
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2019 Peter Powell <petpow@saberuk.com>
+ *   Copyright (C) 2016 Attila Molnar <attilamolnar@hush.com>
+ *
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "inspircd.h"
+#include "modules/cap.h"
+#include "modules/ctctags.h"
+
+class MsgIdTag : public ClientProtocol::MessageTagProvider
+{
+ private:
+       Cap::Reference ctctagcap;
+
+ public:
+       MsgIdTag(Module* mod)
+               : ClientProtocol::MessageTagProvider(mod)
+               , ctctagcap(mod, "message-tags")
+       {
+       }
+
+       ModResult OnProcessTag(User* user, const std::string& tagname, std::string& tagvalue) CXX11_OVERRIDE
+       {
+               if (!irc::equals(tagname, "msgid"))
+                       return MOD_RES_PASSTHRU;
+
+               // We should only allow this tag if it is added by a remote server.
+               return IS_LOCAL(user) ? MOD_RES_DENY : MOD_RES_ALLOW;
+       }
+
+       bool ShouldSendTag(LocalUser* user, const ClientProtocol::MessageTagData& tagdata) CXX11_OVERRIDE
+       {
+               return ctctagcap.get(user);
+       }
+};
+
+class MsgIdGenerator
+{
+       uint64_t counter;
+       std::string strid;
+       const std::string::size_type baselen;
+
+ public:
+       MsgIdGenerator()
+               : counter(0)
+               , strid(InspIRCd::Format("%s~%lu~", ServerInstance->Config->GetSID().c_str(), ServerInstance->startup_time))
+               , baselen(strid.length())
+       {
+       }
+
+       const std::string& GetNext()
+       {
+               strid.erase(baselen);
+               strid.append(ConvToStr(counter++));
+               return strid;
+       }
+};
+
+class ModuleMsgId
+       : public Module
+       , public CTCTags::EventListener
+{
+ private:
+       MsgIdTag tag;
+       MsgIdGenerator generator;
+
+       ModResult CopyMessageId(const ClientProtocol::TagMap& tags_in, ClientProtocol::TagMap& tags_out)
+       {
+               ClientProtocol::TagMap::const_iterator iter = tags_in.find("msgid");
+               if (iter != tags_in.end())
+               {
+                       // If the remote server has sent a message identifier we should use that as
+                       // identifiers need to be the same on all sides of the network.
+                       tags_out.insert(*iter);
+                       return MOD_RES_PASSTHRU;
+               }
+
+               // Otherwise, we can just create a new message identifier.
+               tags_out.insert(std::make_pair("msgid", ClientProtocol::MessageTagData(&tag, generator.GetNext())));
+               return MOD_RES_PASSTHRU;
+       }
+
+ public:
+       ModuleMsgId()
+               : CTCTags::EventListener(this)
+               , tag(this)
+       {
+       }
+
+       ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE
+       {
+               return CopyMessageId(details.tags_in, details.tags_out);
+       }
+
+       ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) CXX11_OVERRIDE
+       {
+               return CopyMessageId(details.tags_in, details.tags_out);
+       }
+
+       Version GetVersion() CXX11_OVERRIDE
+       {
+               return Version("Provides the msgid IRCv3 tag", VF_VENDOR);
+       }
+};
+
+MODULE_INIT(ModuleMsgId)