aboutsummaryrefslogtreecommitdiffstats
path: root/modules/abbreviation.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2026-03-05 04:24:54 +0000
committerGravatar Sadie Powell2026-03-05 04:24:54 +0000
commit1aab85588bef2e4e4f76c78736044d7a1eb44ad6 (patch)
treea6f1d56eb0c1e8a699f7036df020d8bc8fb4a4ee /modules/abbreviation.cpp
parentDeduplicate command usability checks into Command::IsUsableBy. (diff)
Clean up the abbreviation module and move to standard replies.
Diffstat (limited to 'modules/abbreviation.cpp')
-rw-r--r--modules/abbreviation.cpp67
1 files changed, 38 insertions, 29 deletions
diff --git a/modules/abbreviation.cpp b/modules/abbreviation.cpp
index 2a6427d7c..48e22463a 100644
--- a/modules/abbreviation.cpp
+++ b/modules/abbreviation.cpp
@@ -22,19 +22,18 @@
#include "inspircd.h"
-
-enum
-{
- // InspIRCd-specific.
- ERR_AMBIGUOUSCOMMAND = 420
-};
+#include "modules/ircv3.h"
class ModuleAbbreviation final
: public Module
{
+private:
+ IRCv3::ReplyCapReference stdrplcap;
+
public:
ModuleAbbreviation()
: Module(VF_VENDOR, "Allows commands to be abbreviated by appending a full stop.")
+ , stdrplcap(this)
{
}
@@ -49,43 +48,53 @@ public:
if (validated || command.empty() || command.back() != '.')
return MOD_RES_PASSTHRU;
- /* Look for any command that starts with the same characters, if it does, replace the command string with it */
- size_t clen = command.length() - 1;
+ // :irc.example.com FAIL * AMBIGUOUS_ABBREVIATION :BLAH
+ // :irc.example.com NOTICE nick :*** BLAH
+ const auto maxlen = ServerInstance->Config->Limits.MaxLine
+ - ServerInstance->Config->GetServerName().size()
+ - std::max<size_t>(user->nick.length() + 4, 22)
+ - 10; // Some extra just in case.
+
+ auto foundmatch = false;
std::string foundcommand;
- std::string matchlist;
- bool foundmatch = false;
- for (const auto& [cmdname, _] : ServerInstance->Parser.GetCommands())
+ std::string extracommands;
+
+ const auto cmdlen = command.length() - 1;
+ for (const auto& [cmdname, cmd] : ServerInstance->Parser.GetCommands())
{
- if (!command.compare(0, clen, cmdname, 0, clen))
+ // Look for any command that starts with the same characters that
+ // is usable by the caller.
+ if (command.compare(0, cmdlen, cmdname, 0, cmdlen) != 0 || !cmd->IsUsableBy(user))
+ continue; // No match.
+
+ if (extracommands.length() > maxlen)
{
- if (matchlist.length() > 450)
- {
- user->WriteNumeric(ERR_AMBIGUOUSCOMMAND, "Ambiguous abbreviation and too many possible matches.");
- return MOD_RES_DENY;
- }
+ IRCv3::WriteReply(Reply::Type::FAIL, user, stdrplcap, nullptr, "AMBIGUOUS_ABBREVIATION",
+ "Ambiguous abbreviation and too many possible matches.");
+ return MOD_RES_DENY;
+ }
- if (!foundmatch)
- {
- /* Found the command */
- foundcommand = cmdname;
- foundmatch = true;
- }
- else
- matchlist.append(" ").append(cmdname);
+ if (!foundmatch)
+ {
+ // Found the command.
+ foundcommand = cmdname;
+ foundmatch = true;
}
+ else
+ extracommands.append(" ").append(cmdname);
}
/* Ambiguous command, list the matches */
- if (!matchlist.empty())
+ if (!extracommands.empty())
{
- user->WriteNumeric(ERR_AMBIGUOUSCOMMAND, FMT::format("Ambiguous abbreviation, possible matches: {}{}", foundcommand, matchlist));
+ IRCv3::WriteReply(Reply::Type::FAIL, user, stdrplcap, nullptr, "AMBIGUOUS_ABBREVIATION",
+ FMT::format("Ambiguous abbreviation, possible matches: {}{}", foundcommand, extracommands));
return MOD_RES_DENY;
}
+ // Replace the command abbreviation with the found command name.
if (!foundcommand.empty())
- {
command = foundcommand;
- }
return MOD_RES_PASSTHRU;
}