Skip to content

Commit 7936f6a

Browse files
committed
feat: custom command aliases
1 parent 3e18e6c commit 7936f6a

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

backend/src/applyCommandAliases.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { PluginMessageCommandManager } from "knub";
2+
3+
type RawAliasValue = string | string[];
4+
type GuildAliasConfig = Record<string, Record<string, RawAliasValue>>;
5+
6+
type PluginDataWithAliases = {
7+
context?: string;
8+
pluginName?: string;
9+
fullConfig?: {
10+
aliases?: GuildAliasConfig;
11+
};
12+
};
13+
14+
const originalAdd = PluginMessageCommandManager.prototype.add;
15+
16+
function normalizeAliasValue(value: RawAliasValue): string[] {
17+
const values = Array.isArray(value) ? value : [value];
18+
return values
19+
.map((alias) => alias.trim())
20+
.filter((alias) => alias.length > 0);
21+
}
22+
23+
PluginMessageCommandManager.prototype.add = function addWithCommandAliases(
24+
this: PluginMessageCommandManager<any>,
25+
blueprint: any,
26+
) {
27+
const pluginData = (this as unknown as { pluginData?: PluginDataWithAliases }).pluginData;
28+
if (pluginData?.context === "guild") {
29+
const aliasesByPlugin = pluginData.fullConfig?.aliases;
30+
if (aliasesByPlugin) {
31+
const pluginName = pluginData.pluginName ?? "";
32+
const pluginAliases =
33+
aliasesByPlugin[pluginName] ?? aliasesByPlugin[pluginName.toLowerCase()];
34+
35+
if (pluginAliases) {
36+
const normalizedAliasMap = new Map<string, string[]>();
37+
for (const [rawKey, rawValue] of Object.entries(pluginAliases)) {
38+
const normalizedKey = rawKey.trim().toLowerCase();
39+
if (!normalizedKey) {
40+
continue;
41+
}
42+
43+
const normalizedValues = normalizeAliasValue(rawValue);
44+
if (normalizedValues.length === 0) {
45+
continue;
46+
}
47+
48+
normalizedAliasMap.set(normalizedKey, normalizedValues);
49+
}
50+
51+
if (normalizedAliasMap.size > 0 && blueprint?.trigger) {
52+
const baseTriggers = Array.isArray(blueprint.trigger)
53+
? [...blueprint.trigger]
54+
: [blueprint.trigger];
55+
const updatedTriggers = [...baseTriggers];
56+
57+
const existingStringTriggers = new Set(
58+
baseTriggers
59+
.filter((trigger): trigger is string => typeof trigger === "string")
60+
.map((trigger) => trigger.trim().toLowerCase()),
61+
);
62+
63+
let changed = false;
64+
for (const trigger of baseTriggers) {
65+
if (typeof trigger !== "string") {
66+
continue;
67+
}
68+
69+
const triggerKey = trigger.trim().toLowerCase();
70+
const aliasList = normalizedAliasMap.get(triggerKey);
71+
if (!aliasList) {
72+
continue;
73+
}
74+
75+
for (const alias of aliasList) {
76+
const aliasKey = alias.toLowerCase();
77+
if (existingStringTriggers.has(aliasKey)) {
78+
continue;
79+
}
80+
81+
existingStringTriggers.add(aliasKey);
82+
updatedTriggers.push(alias);
83+
changed = true;
84+
}
85+
}
86+
87+
if (changed) {
88+
blueprint = {
89+
...blueprint,
90+
trigger: updatedTriggers,
91+
};
92+
}
93+
}
94+
}
95+
}
96+
}
97+
98+
return originalAdd.call(this, blueprint);
99+
};

backend/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// KEEP THIS AS FIRST IMPORT
22
// See comment in module for details
33
import "./threadsSignalFix.js";
4+
import "./applyCommandAliases.js";
45

56
import {
67
Client,

backend/src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ export const zZeppelinGuildConfig = z.strictObject({
66
// From BaseConfig
77
prefix: z.string().optional(),
88
levels: z.record(zSnowflake, z.number()).optional(),
9+
aliases: z
10+
.record(
11+
z.string(),
12+
z.record(z.string(), z.union([z.string().min(1), z.array(z.string().min(1))])),
13+
)
14+
.optional(),
915
plugins: z.record(z.string(), z.unknown()).optional(),
1016
});
1117

0 commit comments

Comments
 (0)