diff --git a/include/access.h b/include/access.h index fd35cf0b2..154837b55 100644 --- a/include/access.h +++ b/include/access.h @@ -67,6 +67,9 @@ public: */ virtual ChanAccess *Create() = 0; + virtual void GetAccess(CommandSource& source, const Privilege *p, Anope::map &access) = 0; + static void SendAccess(CommandSource &source, const Anope::string &pname); + private: static std::list Providers; public: diff --git a/language/anope.en_US.po b/language/anope.en_US.po index b143284a6..02f0142c8 100644 --- a/language/anope.en_US.po +++ b/language/anope.en_US.po @@ -16,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: Anope\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 17:40+0100\n" -"PO-Revision-Date: 2026-05-20 17:41+0100\n" +"POT-Creation-Date: 2026-05-21 11:52+0100\n" +"PO-Revision-Date: 2026-05-21 11:52+0100\n" "Last-Translator: Sadie Powell \n" "Language-Team: English\n" "Language: en_US\n" @@ -25,7 +25,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.9\n" +"X-Generator: Poedit 3.4.2\n" #: ../modules/operserv/os_forbid.cpp #, c-format @@ -2487,10 +2487,7 @@ msgid "Bans a given nick or mask on a channel" msgstr "" #: ../modules/chanserv/cs_ban.cpp -msgid "" -"Bans a given nick or mask on a channel. An optional expiry may be given to cause services to remove the ban after a set amount of time.\n" -"\n" -"By default, limited to AOPs or those with level 5 access and above on the channel. Channel founders may ban masks." +msgid "Bans a given nick or mask on a channel. An optional expiry may be given to cause services to remove the ban after a set amount of time. Channel founders may ban masks." msgstr "" #: ../modules/chanserv/cs_enforce.cpp @@ -2683,6 +2680,11 @@ msgstr "" msgid "Bot won't kick for repeats anymore." msgstr "" +#: ../src/access.cpp +#, c-format +msgid "By default, the %s command is limited to:" +msgstr "" + #: ../modules/operserv/os_info.cpp msgid "CLEAR target" msgstr "" @@ -4012,6 +4014,10 @@ msgstr "" msgid "Fixed layout" msgstr "" +#: ../modules/chanserv/cs_flags.cpp +msgid "Flag" +msgstr "" + #: ../modules/chanserv/cs_flags.cpp msgid "Flags" msgstr "" @@ -4319,10 +4325,7 @@ msgid "Kicks a specified nick from a channel" msgstr "" #: ../modules/chanserv/cs_kick.cpp -msgid "" -"Kicks a specified nick from a channel.\n" -"\n" -"By default, limited to AOPs or those with level 5 access and above on the channel. Channel founders can also specify masks." +msgid "Kicks a specified nick from a channel. Channel founders can also specify masks." msgstr "" #: ../modules/operserv/os_kill.cpp @@ -6908,18 +6911,12 @@ msgstr "" #: ../modules/chanserv/cs_invite.cpp #, c-format -msgid "" -"Tells %s to invite you or an optionally specified nick into the given channel.\n" -"\n" -"By default, limited to AOPs or those with level 5 access and above on the channel." +msgid "Tells %s to invite you or an optionally specified nick into the given channel." msgstr "" #: ../modules/chanserv/cs_unban.cpp #, c-format -msgid "" -"Tells %s to remove all bans preventing you or the given user from entering the given channel. If no channel is given, all bans affecting you in channels you have access in are removed.\n" -"\n" -"By default, limited to AOPs or those with level 5 access and above on the channel." +msgid "Tells %s to remove all bans preventing you or the given user from entering the given channel. If no channel is given, all bans affecting you in channels you have access in are removed." msgstr "" #: ../modules/operserv/os_jupe.cpp @@ -8007,6 +8004,10 @@ msgstr "" msgid "Word" msgstr "" +#: ../modules/chanserv/cs_xop.cpp +msgid "XOP" +msgstr "" + #: ../modules/nickserv/ns_group.cpp #, c-format msgid "You are already a member of the account of %s." diff --git a/modules/chanserv/cs_access.cpp b/modules/chanserv/cs_access.cpp index fa5de6072..72c5ff3d0 100644 --- a/modules/chanserv/cs_access.cpp +++ b/modules/chanserv/cs_access.cpp @@ -92,6 +92,13 @@ public: { return new AccessChanAccess(this); } + + void GetAccess(CommandSource& source, const Privilege *p, Anope::map &access) override + { + auto it = defaultLevels.find(p->name); + if (it != defaultLevels.end()) + access[_("Level")] = LevelToString(source, it->second); + } }; AccessAccessProvider *AccessAccessProvider::me; diff --git a/modules/chanserv/cs_ban.cpp b/modules/chanserv/cs_ban.cpp index 7c138a87e..e26e05f2a 100644 --- a/modules/chanserv/cs_ban.cpp +++ b/modules/chanserv/cs_ban.cpp @@ -272,11 +272,12 @@ public: source.Reply(_( "Bans a given nick or mask on a channel. An optional expiry may " "be given to cause services to remove the ban after a set amount " - "of time." - "\n\n" - "By default, limited to AOPs or those with level 5 access " - "and above on the channel. Channel founders may ban masks." + "of time. Channel founders may ban masks." )); + + source.Reply(" "); + AccessProvider::SendAccess(source, "BAN"); + return true; } }; diff --git a/modules/chanserv/cs_flags.cpp b/modules/chanserv/cs_flags.cpp index c3e44a8ad..3d0067f1d 100644 --- a/modules/chanserv/cs_flags.cpp +++ b/modules/chanserv/cs_flags.cpp @@ -84,6 +84,13 @@ public: { return new FlagsChanAccess(this); } + + void GetAccess(CommandSource& source, const Privilege *p, Anope::map &access) override + { + auto it = defaultFlags.find(p->name); + if (it != defaultFlags.end()) + access[_("Flag")] = Anope::ToString(it->second); + } }; FlagsAccessProvider *FlagsAccessProvider::ap; diff --git a/modules/chanserv/cs_invite.cpp b/modules/chanserv/cs_invite.cpp index eb7b7f31d..f813cc082 100644 --- a/modules/chanserv/cs_invite.cpp +++ b/modules/chanserv/cs_invite.cpp @@ -95,11 +95,12 @@ public: source.Reply(_( "Tells %s to invite you or an optionally specified " "nick into the given channel." - "\n\n" - "By default, limited to AOPs or those with level 5 access and above " - "on the channel." ), source.service->nick.c_str()); + + source.Reply(" "); + AccessProvider::SendAccess(source, "INVITE"); + return true; } }; diff --git a/modules/chanserv/cs_kick.cpp b/modules/chanserv/cs_kick.cpp index 316080712..5296564cd 100644 --- a/modules/chanserv/cs_kick.cpp +++ b/modules/chanserv/cs_kick.cpp @@ -134,12 +134,11 @@ public: { this->SendSyntax(source); source.Reply(" "); - source.Reply(_( - "Kicks a specified nick from a channel." - "\n\n" - "By default, limited to AOPs or those with level 5 access " - "and above on the channel. Channel founders can also specify masks." - )); + source.Reply(_("Kicks a specified nick from a channel. Channel founders can also specify masks.")); + + source.Reply(" "); + AccessProvider::SendAccess(source, "KICK"); + return true; } }; diff --git a/modules/chanserv/cs_unban.cpp b/modules/chanserv/cs_unban.cpp index 0bc57340a..f78011c98 100644 --- a/modules/chanserv/cs_unban.cpp +++ b/modules/chanserv/cs_unban.cpp @@ -128,11 +128,12 @@ public: "user from entering the given channel. If no channel is " "given, all bans affecting you in channels you have access " "in are removed." - "\n\n" - "By default, limited to AOPs or those with level 5 access and above " - "on the channel." ), source.service->nick.c_str()); + + source.Reply(" "); + AccessProvider::SendAccess(source, "UNBAN"); + return true; } }; diff --git a/modules/chanserv/cs_xop.cpp b/modules/chanserv/cs_xop.cpp index ced25485f..297a8baf3 100644 --- a/modules/chanserv/cs_xop.cpp +++ b/modules/chanserv/cs_xop.cpp @@ -100,6 +100,19 @@ public: { return new XOPChanAccess(this); } + + void GetAccess(CommandSource& source, const Privilege *p, Anope::map &access) override + { + for (const auto& xop : order) + { + const auto &privs = permissions[xop]; + if (std::find(privs.begin(), privs.end(), p->name) != privs.end()) + { + access[_("XOP")] = xop; + return; + } + } + } }; class CommandCSXOP final diff --git a/src/access.cpp b/src/access.cpp index 92844d761..3f9c8031a 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -94,6 +94,27 @@ const std::list& AccessProvider::GetProviders() return Providers; } +void AccessProvider::SendAccess(CommandSource &source, const Anope::string& pname) +{ + auto *p = PrivilegeManager::FindPrivilege(pname); + if (!p) + return; // Privilege missing. + + Anope::map access; + for (auto *service : Service::GetServices("AccessProvider")) + { + auto *accessprovider = static_cast(service); + accessprovider->GetAccess(source, p, access); + } + + if (access.empty()) + return; // No access systems??? + + source.Reply(_("By default, the \002%s\002 command is limited to:"), source.command.c_str()); + for (const auto& [system, privilege] : access) + source.Reply(" \002%s\002: %s", source.Translate(system), privilege.c_str()); +} + ChanAccess::ChanAccess(AccessProvider *p) : Serializable(CHANACCESS_TYPE) , provider(p)