From b9554f8539103a43c26f2c4def911d2251798538 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Sat, 18 Oct 2025 00:38:25 +0100 Subject: [PATCH] Add an IRCv3 time tag to entry messages. --- data/chanserv.example.conf | 14 +++++++++++++- include/protocol.h | 4 ++-- modules/chanserv/cs_entrymsg.cpp | 13 +++++++++++-- modules/protocol/inspircd.cpp | 16 ++++++++-------- src/protocol.cpp | 16 ++++++++-------- 5 files changed, 42 insertions(+), 21 deletions(-) diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index 930815281..d6c32a975 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -990,8 +990,20 @@ module { name = "cs_entrymsg" - /* The maximum number of entrymsgs allowed per channel. If not set, defaults to 5. */ + /* + * The maximum number of entry messages allowed per channel. + * + * Defaults to 5 + */ maxentries = 5 + + /* + * Whether to include an IRCv3 time tag for the original add time on entry + * messages. + * + * Defaults to yes. + */ + #timestamp = no } command { service = "ChanServ"; name = "ENTRYMSG"; command = "chanserv/entrymsg"; group = "chanserv/management"; } diff --git a/include/protocol.h b/include/protocol.h index 4dc9b7525..11e37d953 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -215,8 +215,8 @@ public: virtual void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) = 0; virtual void SendGlobalPrivmsg(BotInfo *bi, const Server *desc, const Anope::string &msg) = 0; - virtual void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg); - virtual void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg); + virtual void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map &tags = {}); + virtual void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map &tags = {}); virtual void SendQuit(User *u, const Anope::string &msg = "", const Anope::string &opermsg = ""); virtual void SendPing(const Anope::string &servname, const Anope::string &who); diff --git a/modules/chanserv/cs_entrymsg.cpp b/modules/chanserv/cs_entrymsg.cpp index a560a1564..0463fe1fa 100644 --- a/modules/chanserv/cs_entrymsg.cpp +++ b/modules/chanserv/cs_entrymsg.cpp @@ -296,12 +296,21 @@ public: if (!messages) return; + const auto timestamp = Config->GetModule(this).Get("timestamp", "yes"); for (const auto &message : *(*messages)) { + Anope::map tags; + if (timestamp) + { + char timebuf[32]; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S.000Z", gmtime(&message->when)); + tags["time"] = timebuf; + } + if (u->ShouldPrivmsg()) - IRCD->SendContextPrivmsg(c->ci->WhoSends(), u, c, message->message); + IRCD->SendContextPrivmsg(c->ci->WhoSends(), u, c, message->message, tags); else - IRCD->SendContextNotice(c->ci->WhoSends(), u, c, message->message); + IRCD->SendContextNotice(c->ci->WhoSends(), u, c, message->message, tags); } } } diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp index 11f186501..633d82a8b 100644 --- a/modules/protocol/inspircd.cpp +++ b/modules/protocol/inspircd.cpp @@ -249,25 +249,25 @@ public: Uplink::Send(bi, "PRIVMSG", "$" + dest->GetName(), msg); } - void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) override + void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map &tags) override { if (spanningtree_proto_ver >= 1206) { - IRCD->SendNotice(bi, target->GetUID(), msg, { - { "~context", context->name }, - }); + auto newtags = tags; + newtags["~context"] = context->name; + IRCD->SendNotice(bi, target->GetUID(), msg, newtags); return; } IRCDProto::SendContextNotice(bi, target, context, msg); } - void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) override + void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map &tags) override { if (spanningtree_proto_ver >= 1206) { - IRCD->SendPrivmsg(bi, target->GetUID(), msg, { - { "~context", context->name }, - }); + auto newtags = tags; + newtags["~context"] = context->name; + IRCD->SendPrivmsg(bi, target->GetUID(), msg, newtags); return; } IRCDProto::SendContextPrivmsg(bi, target, context, msg); diff --git a/src/protocol.cpp b/src/protocol.cpp index 65b99b470..5150b5572 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -388,18 +388,18 @@ Anope::string IRCDProto::NormalizeMask(const Anope::string &mask) return Entry("", mask).GetNUHMask(); } -void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) +void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map &tags) { - IRCD->SendNotice(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), { - { "+draft/channel-context", context->name }, - }); + auto newtags = tags; + newtags["+draft/channel-context"] = context->name; + IRCD->SendNotice(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), newtags); } -void IRCDProto::SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) +void IRCDProto::SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map &tags) { - IRCD->SendPrivmsg(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), { - { "+draft/channel-context", context->name }, - }); + auto newtags = tags; + newtags["+draft/channel-context"] = context->name; + IRCD->SendPrivmsg(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), newtags); } MessageSource::MessageSource(const Anope::string &src) : source(src)