diff options
Diffstat (limited to 'src/modules/m_services.cpp')
| -rw-r--r-- | src/modules/m_services.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/modules/m_services.cpp b/src/modules/m_services.cpp index 3a1b27e90..1cb827c7a 100644 --- a/src/modules/m_services.cpp +++ b/src/modules/m_services.cpp @@ -32,6 +32,9 @@ enum // From Charybdis. ERR_MLOCKRESTRICTED = 742, + + // InspIRCd-specific. + ERR_TOPICLOCK = 744, }; class RegisteredChannel final @@ -424,6 +427,55 @@ public: } }; +class CommandSVSTopic final + : public Command +{ +public: + CommandSVSTopic(Module* mod) + : Command(mod, "SVSTOPIC", 1, 4) + { + access_needed = CmdAccess::SERVER; + allow_empty_last_param = true; + } + + CmdResult Handle(User* user, const Params& parameters) override + { + // The command can only be executed by remote services servers. + if (IS_LOCAL(user) || !user->server->IsService()) + return CmdResult::FAILURE; + + auto* chan = ServerInstance->Channels.Find(parameters[0]); + if (!chan) + return CmdResult::FAILURE; + + if (parameters.size() == 4) + { + // 4 parameter version, set all topic data on the channel to the ones given in the parameters. + time_t topicts = ConvToNum<time_t>(parameters[1]); + if (!topicts) + { + ServerInstance->Logs.Debug(MODNAME, "Received SVSTOPIC with a 0 topicts; dropped."); + return CmdResult::INVALID; + } + + chan->SetTopic(user, parameters[3], topicts, ¶meters[2]); + } + else + { + // 1 parameter version, nuke the topic + chan->SetTopic(user, std::string(), 0); + chan->setby.clear(); + } + + return CmdResult::SUCCESS; + } + + RouteDescriptor GetRouting(User* user, const Params& parameters) override + { + return ROUTE_BROADCAST; + } +}; + class ModuleServices final : public Module , public Stats::EventListener @@ -436,11 +488,13 @@ private: ServProtect servprotectmode; SVSHoldFactory svsholdfactory; StringExtItem mlockext; + BoolExtItem topiclockext; CommandSVSCMode svscmodecmd; CommandSVSHold svsholdcmd; CommandSVSJoin svsjoincmd; CommandSVSNick svsnickcmd; CommandSVSPart svspartcmd; + CommandSVSTopic svstopiccmd; bool accountoverrideshold; bool HandleModeLock(User* user, Channel* chan, const Modes::Change& change) @@ -491,11 +545,13 @@ public: , servicetag(this) , servprotectmode(this) , mlockext(this, "mlock", ExtensionType::CHANNEL, true) + , topiclockext(this, "topiclock", ExtensionType::CHANNEL, true) , svscmodecmd(this) , svsholdcmd(this) , svsjoincmd(this) , svsnickcmd(this) , svspartcmd(this) + , svstopiccmd(this) { } @@ -529,6 +585,15 @@ public: return MOD_RES_PASSTHRU; } + ModResult OnPreTopicChange(User* user, Channel* chan, const std::string& topic) override + { + if (!IS_LOCAL(user) || !topiclockext.Get(chan)) + return MOD_RES_PASSTHRU; // Remote user or no topiclock. + + user->WriteNumeric(ERR_TOPICLOCK, chan->name, "Topic cannot be changed as it has been locked by services!"); + return MOD_RES_DENY; + } + ModResult OnRawMode(User* user, Channel* chan, const Modes::Change& change) override { if (!IS_LOCAL(user) || !chan) |
