Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions backend/src/applyCommandAliases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { PluginMessageCommandManager } from "knub";

type RawAliasValue = string | string[];
type GuildAliasConfig = Record<string, Record<string, RawAliasValue>>;

type PluginDataWithAliases = {
context?: string;
pluginName?: string;
fullConfig?: {
aliases?: GuildAliasConfig;
};
};

const originalAdd = PluginMessageCommandManager.prototype.add;

function normalizeAliasValue(value: RawAliasValue): string[] {
const values = Array.isArray(value) ? value : [value];
return values
.map((alias) => alias.trim())
.filter((alias) => alias.length > 0);
}

PluginMessageCommandManager.prototype.add = function addWithCommandAliases(
this: PluginMessageCommandManager<any>,
blueprint: any,
) {
const pluginData = (this as unknown as { pluginData?: PluginDataWithAliases }).pluginData;
if (pluginData?.context === "guild") {
const aliasesByPlugin = pluginData.fullConfig?.aliases;
if (aliasesByPlugin) {
const pluginName = pluginData.pluginName ?? "";
const pluginAliases =
aliasesByPlugin[pluginName] ?? aliasesByPlugin[pluginName.toLowerCase()];

if (pluginAliases) {
const normalizedAliasMap = new Map<string, string[]>();
for (const [rawKey, rawValue] of Object.entries(pluginAliases)) {
const normalizedKey = rawKey.trim().toLowerCase();
if (!normalizedKey) {
continue;
}

const normalizedValues = normalizeAliasValue(rawValue);
if (normalizedValues.length === 0) {
continue;
}

normalizedAliasMap.set(normalizedKey, normalizedValues);
}

if (normalizedAliasMap.size > 0 && blueprint?.trigger) {
const baseTriggers = Array.isArray(blueprint.trigger)
? [...blueprint.trigger]
: [blueprint.trigger];
const updatedTriggers = [...baseTriggers];

const existingStringTriggers = new Set(
baseTriggers
.filter((trigger): trigger is string => typeof trigger === "string")
.map((trigger) => trigger.trim().toLowerCase()),
);

let changed = false;
for (const trigger of baseTriggers) {
if (typeof trigger !== "string") {
continue;
}

const triggerKey = trigger.trim().toLowerCase();
const aliasList = normalizedAliasMap.get(triggerKey);
if (!aliasList) {
continue;
}

for (const alias of aliasList) {
const aliasKey = alias.toLowerCase();
if (existingStringTriggers.has(aliasKey)) {
continue;
}

existingStringTriggers.add(aliasKey);
updatedTriggers.push(alias);
changed = true;
}
}

if (changed) {
blueprint = {
...blueprint,
trigger: updatedTriggers,
};
}
}
}
}
}

return originalAdd.call(this, blueprint);
};
1 change: 1 addition & 0 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// KEEP THIS AS FIRST IMPORT
// See comment in module for details
import "./threadsSignalFix.js";
import "./applyCommandAliases.js";

import {
Client,
Expand Down
6 changes: 6 additions & 0 deletions backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ export const zZeppelinGuildConfig = z.strictObject({
// From BaseConfig
prefix: z.string().optional(),
levels: z.record(zSnowflake, z.number()).optional(),
aliases: z
.record(
z.string(),
z.record(z.string(), z.union([z.string().min(1), z.array(z.string().min(1))])),
)
.optional(),
plugins: z.record(z.string(), z.unknown()).optional(),
});

Expand Down
Loading