mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-06-07 16:05:01 +00:00
feat: update to djs 14.19.3, node 22, zod 4
This commit is contained in:
parent
595e1a0556
commit
09eb8e92f2
189 changed files with 1244 additions and 900 deletions
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
||||||
18
|
22
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"migrate-rollback-prod": "npm run migrate-rollback",
|
"migrate-rollback-prod": "npm run migrate-rollback",
|
||||||
"migrate-rollback-dev": "npm run build && npm run migrate-rollback",
|
"migrate-rollback-dev": "npm run build && npm run migrate-rollback",
|
||||||
"validate-active-configs": "node --enable-source-maps dist/validateActiveConfigs.js > ../config-errors.txt",
|
"validate-active-configs": "node --enable-source-maps dist/validateActiveConfigs.js > ../config-errors.txt",
|
||||||
"export-config-json-schema": "node --enable-source-maps dist/exportSchemas.js > ../config-schema.json",
|
"export-config-json-schema": "node --enable-source-maps dist/exportSchemas.js",
|
||||||
"test": "npm run build && npm run run-tests",
|
"test": "npm run build && npm run run-tests",
|
||||||
"run-tests": "ava",
|
"run-tests": "ava",
|
||||||
"test-watch": "tsc-watch --build --onSuccess \"npx ava\""
|
"test-watch": "tsc-watch --build --onSuccess \"npx ava\""
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"deep-diff": "^1.0.2",
|
"deep-diff": "^1.0.2",
|
||||||
"discord.js": "^14.14.1",
|
"discord.js": "^14.19.3",
|
||||||
"dotenv": "^4.0.0",
|
"dotenv": "^4.0.0",
|
||||||
"emoji-regex": "^8.0.0",
|
"emoji-regex": "^8.0.0",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
"fp-ts": "^2.0.1",
|
"fp-ts": "^2.0.1",
|
||||||
"humanize-duration": "^3.15.0",
|
"humanize-duration": "^3.15.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"knub": "^32.0.0-next.21",
|
"knub": "^32.0.0-next.23",
|
||||||
"knub-command-manager": "^9.1.0",
|
"knub-command-manager": "^9.1.0",
|
||||||
"last-commit-log": "^2.1.0",
|
"last-commit-log": "^2.1.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
|
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
|
||||||
"zlib-sync": "^0.1.7",
|
"zlib-sync": "^0.1.7",
|
||||||
"zod": "^3.7.2"
|
"zod": "^3.25.17"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/cors": "^2.8.5",
|
"@types/cors": "^2.8.5",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "node:events";
|
||||||
import { CooldownManager } from "knub";
|
import { CooldownManager } from "knub";
|
||||||
import { RegExpWorker, TimeoutError } from "regexp-worker";
|
import { RegExpWorker, TimeoutError } from "regexp-worker";
|
||||||
import { MINUTES, SECONDS } from "./utils.js";
|
import { MINUTES, SECONDS } from "./utils.js";
|
||||||
|
|
|
@ -46,7 +46,7 @@ export class SimpleCache<T = any> {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.maxItems && this.store.size > this.maxItems) {
|
if (this.maxItems && this.store.size > this.maxItems) {
|
||||||
const keyToDelete = this.store.keys().next().value;
|
const keyToDelete = this.store.keys().next().value!;
|
||||||
this.store.delete(keyToDelete);
|
this.store.delete(keyToDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,97 +1,90 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { availableGuildPlugins } from "../plugins/availablePlugins.js";
|
import { availableGuildPlugins } from "../plugins/availablePlugins.js";
|
||||||
import { ZeppelinGuildPluginInfo } from "../types.js";
|
import { ZeppelinGuildPluginInfo } from "../types.js";
|
||||||
import { indentLines } from "../utils.js";
|
import { indentLines } from "../utils.js";
|
||||||
import { notFound } from "./responses.js";
|
import { notFound } from "./responses.js";
|
||||||
|
|
||||||
function isZodObject(schema: z.ZodTypeAny): schema is z.ZodObject<any> {
|
function isZodObject(schema: z.ZodType): schema is z.ZodObject<any> {
|
||||||
return schema._def.typeName === "ZodObject";
|
return schema.def.type === "object";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodRecord(schema: z.ZodTypeAny): schema is z.ZodRecord<any> {
|
function isZodRecord(schema: z.ZodType): schema is z.ZodRecord<any> {
|
||||||
return schema._def.typeName === "ZodRecord";
|
return schema.def.type === "record";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodEffects(schema: z.ZodTypeAny): schema is z.ZodEffects<any, any> {
|
function isZodOptional(schema: z.ZodType): schema is z.ZodOptional<any> {
|
||||||
return schema._def.typeName === "ZodEffects";
|
return schema.def.type === "optional";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodOptional(schema: z.ZodTypeAny): schema is z.ZodOptional<any> {
|
function isZodArray(schema: z.ZodType): schema is z.ZodArray<any> {
|
||||||
return schema._def.typeName === "ZodOptional";
|
return schema.def.type === "array";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodArray(schema: z.ZodTypeAny): schema is z.ZodArray<any> {
|
function isZodUnion(schema: z.ZodType): schema is z.ZodUnion<any> {
|
||||||
return schema._def.typeName === "ZodArray";
|
return schema.def.type === "union";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodUnion(schema: z.ZodTypeAny): schema is z.ZodUnion<any> {
|
function isZodNullable(schema: z.ZodType): schema is z.ZodNullable<any> {
|
||||||
return schema._def.typeName === "ZodUnion";
|
return schema.def.type === "nullable";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodNullable(schema: z.ZodTypeAny): schema is z.ZodNullable<any> {
|
function isZodDefault(schema: z.ZodType): schema is z.ZodDefault<any> {
|
||||||
return schema._def.typeName === "ZodNullable";
|
return schema.def.type === "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodDefault(schema: z.ZodTypeAny): schema is z.ZodDefault<any> {
|
function isZodLiteral(schema: z.ZodType): schema is z.ZodLiteral<any> {
|
||||||
return schema._def.typeName === "ZodDefault";
|
return schema.def.type === "literal";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodLiteral(schema: z.ZodTypeAny): schema is z.ZodLiteral<any> {
|
function isZodIntersection(schema: z.ZodType): schema is z.ZodIntersection<any, any> {
|
||||||
return schema._def.typeName === "ZodLiteral";
|
return schema.def.type === "intersection";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isZodIntersection(schema: z.ZodTypeAny): schema is z.ZodIntersection<any, any> {
|
function formatZodConfigSchema(schema: z.ZodType) {
|
||||||
return schema._def.typeName === "ZodIntersection";
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatZodConfigSchema(schema: z.ZodTypeAny) {
|
|
||||||
if (isZodObject(schema)) {
|
if (isZodObject(schema)) {
|
||||||
return (
|
return (
|
||||||
`{\n` +
|
`{\n` +
|
||||||
Object.entries(schema._def.shape())
|
Object.entries(schema._def.shape())
|
||||||
.map(([k, value]) => indentLines(`${k}: ${formatZodConfigSchema(value as z.ZodTypeAny)}`, 2))
|
.map(([k, value]) => indentLines(`${k}: ${formatZodConfigSchema(value as z.ZodType)}`, 2))
|
||||||
.join("\n") +
|
.join("\n") +
|
||||||
"\n}"
|
"\n}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (isZodRecord(schema)) {
|
if (isZodRecord(schema)) {
|
||||||
return "{\n" + indentLines(`[string]: ${formatZodConfigSchema(schema._def.valueType)}`, 2) + "\n}";
|
return "{\n" + indentLines(`[string]: ${formatZodConfigSchema(schema.valueType as z.ZodType)}`, 2) + "\n}";
|
||||||
}
|
|
||||||
if (isZodEffects(schema)) {
|
|
||||||
return formatZodConfigSchema(schema._def.schema);
|
|
||||||
}
|
}
|
||||||
if (isZodOptional(schema)) {
|
if (isZodOptional(schema)) {
|
||||||
return `Optional<${formatZodConfigSchema(schema._def.innerType)}>`;
|
return `Optional<${formatZodConfigSchema(schema.def.innerType)}>`;
|
||||||
}
|
}
|
||||||
if (isZodArray(schema)) {
|
if (isZodArray(schema)) {
|
||||||
return `Array<${formatZodConfigSchema(schema._def.type)}>`;
|
return `Array<${formatZodConfigSchema(schema.def.element)}>`;
|
||||||
}
|
}
|
||||||
if (isZodUnion(schema)) {
|
if (isZodUnion(schema)) {
|
||||||
return schema._def.options.map((t) => formatZodConfigSchema(t)).join(" | ");
|
return schema._def.options.map((t) => formatZodConfigSchema(t)).join(" | ");
|
||||||
}
|
}
|
||||||
if (isZodNullable(schema)) {
|
if (isZodNullable(schema)) {
|
||||||
return `Nullable<${formatZodConfigSchema(schema._def.innerType)}>`;
|
return `Nullable<${formatZodConfigSchema(schema.def.innerType)}>`;
|
||||||
}
|
}
|
||||||
if (isZodDefault(schema)) {
|
if (isZodDefault(schema)) {
|
||||||
return formatZodConfigSchema(schema._def.innerType);
|
return formatZodConfigSchema(schema.def.innerType);
|
||||||
}
|
}
|
||||||
if (isZodLiteral(schema)) {
|
if (isZodLiteral(schema)) {
|
||||||
return schema._def.value;
|
return schema.def.values;
|
||||||
}
|
}
|
||||||
if (isZodIntersection(schema)) {
|
if (isZodIntersection(schema)) {
|
||||||
return [formatZodConfigSchema(schema._def.left), formatZodConfigSchema(schema._def.right)].join(" & ");
|
return [formatZodConfigSchema(schema.def.left as z.ZodType), formatZodConfigSchema(schema.def.right as z.ZodType)].join(" & ");
|
||||||
}
|
}
|
||||||
if (schema._def.typeName === "ZodString") {
|
if (schema.def.type === "string") {
|
||||||
return "string";
|
return "string";
|
||||||
}
|
}
|
||||||
if (schema._def.typeName === "ZodNumber") {
|
if (schema.def.type === "number") {
|
||||||
return "number";
|
return "number";
|
||||||
}
|
}
|
||||||
if (schema._def.typeName === "ZodBoolean") {
|
if (schema.def.type === "boolean") {
|
||||||
return "boolean";
|
return "boolean";
|
||||||
}
|
}
|
||||||
if (schema._def.typeName === "ZodNever") {
|
if (schema.def.type === "never") {
|
||||||
return "never";
|
return "never";
|
||||||
}
|
}
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ApiPermissions } from "@zeppelinbot/shared/apiPermissions.js";
|
import { ApiPermissions } from "@zeppelinbot/shared/apiPermissions.js";
|
||||||
import express, { Request, Response } from "express";
|
import express, { Request, Response } from "express";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { GuildCases } from "../../data/GuildCases.js";
|
import { GuildCases } from "../../data/GuildCases.js";
|
||||||
import { Case } from "../../data/entities/Case.js";
|
import { Case } from "../../data/entities/Case.js";
|
||||||
import { MINUTES } from "../../utils.js";
|
import { MINUTES } from "../../utils.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BaseConfig, ConfigValidationError, GuildPluginBlueprint, PluginConfigManager } from "knub";
|
import { BaseConfig, ConfigValidationError, GuildPluginBlueprint, PluginConfigManager } from "knub";
|
||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod/v4";
|
||||||
import { availableGuildPlugins } from "./plugins/availablePlugins.js";
|
import { availableGuildPlugins } from "./plugins/availablePlugins.js";
|
||||||
import { zZeppelinGuildConfig } from "./types.js";
|
import { zZeppelinGuildConfig } from "./types.js";
|
||||||
import { formatZodIssue } from "./utils/formatZodIssue.js";
|
import { formatZodIssue } from "./utils/formatZodIssue.js";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { rootDir } from "./paths.js";
|
import { rootDir } from "./paths.js";
|
||||||
|
|
||||||
const envType = z.object({
|
const envType = z.object({
|
||||||
|
|
|
@ -1,21 +1,89 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
||||||
import { availableGuildPlugins } from "./plugins/availablePlugins.js";
|
import { availableGuildPlugins } from "./plugins/availablePlugins.js";
|
||||||
import { zZeppelinGuildConfig } from "./types.js";
|
import { zZeppelinGuildConfig } from "./types.js";
|
||||||
|
import { deepPartial } from "./utils/zodDeepPartial.js";
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
const basePluginOverrideCriteriaSchema = z.strictObject({
|
||||||
|
channel: z
|
||||||
|
.union([z.string(), z.array(z.string())])
|
||||||
|
.nullable()
|
||||||
|
.optional(),
|
||||||
|
category: z
|
||||||
|
.union([z.string(), z.array(z.string())])
|
||||||
|
.nullable()
|
||||||
|
.optional(),
|
||||||
|
level: z
|
||||||
|
.union([z.string(), z.array(z.string())])
|
||||||
|
.nullable()
|
||||||
|
.optional(),
|
||||||
|
user: z
|
||||||
|
.union([z.string(), z.array(z.string())])
|
||||||
|
.nullable()
|
||||||
|
.optional(),
|
||||||
|
role: z
|
||||||
|
.union([z.string(), z.array(z.string())])
|
||||||
|
.nullable()
|
||||||
|
.optional(),
|
||||||
|
thread: z
|
||||||
|
.union([z.string(), z.array(z.string())])
|
||||||
|
.nullable()
|
||||||
|
.optional(),
|
||||||
|
is_thread: z.boolean().nullable().optional(),
|
||||||
|
thread_type: z.literal(["public", "private"]).nullable().optional(),
|
||||||
|
extra: z.any().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const pluginOverrideCriteriaSchema = basePluginOverrideCriteriaSchema.extend({
|
||||||
|
get zzz_dummy_property_do_not_use() {
|
||||||
|
return pluginOverrideCriteriaSchema.optional();
|
||||||
|
},
|
||||||
|
get all() {
|
||||||
|
return z.array(pluginOverrideCriteriaSchema).optional();
|
||||||
|
},
|
||||||
|
get any() {
|
||||||
|
return z.array(pluginOverrideCriteriaSchema).optional();
|
||||||
|
},
|
||||||
|
get not() {
|
||||||
|
return pluginOverrideCriteriaSchema.optional();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const outputPath = process.argv[2];
|
||||||
|
if (!outputPath) {
|
||||||
|
console.error("Output path required");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const partialConfigs = new Map<any, z.ZodType>();
|
||||||
|
function getPartialConfig(configSchema: z.ZodType) {
|
||||||
|
if (!partialConfigs.has(configSchema)) {
|
||||||
|
partialConfigs.set(configSchema, deepPartial(configSchema));
|
||||||
|
}
|
||||||
|
return partialConfigs.get(configSchema)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
function overrides(configSchema: z.ZodType): z.ZodType {
|
||||||
|
const partialConfig = getPartialConfig(configSchema);
|
||||||
|
return pluginOverrideCriteriaSchema.extend({
|
||||||
|
config: partialConfig,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const pluginSchemaMap = availableGuildPlugins.reduce((map, pluginInfo) => {
|
const pluginSchemaMap = availableGuildPlugins.reduce((map, pluginInfo) => {
|
||||||
map[pluginInfo.plugin.name] = pluginInfo.docs.configSchema;
|
map[pluginInfo.plugin.name] = z.object({
|
||||||
|
config: pluginInfo.docs.configSchema.optional(),
|
||||||
|
overrides: overrides(pluginInfo.docs.configSchema).optional(),
|
||||||
|
});
|
||||||
return map;
|
return map;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const fullSchema = zZeppelinGuildConfig.omit({ plugins: true }).merge(
|
const fullSchema = zZeppelinGuildConfig.omit({ plugins: true }).extend({
|
||||||
z.strictObject({
|
plugins: z.strictObject(pluginSchemaMap).partial().optional(),
|
||||||
plugins: z.strictObject(pluginSchemaMap).partial(),
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const jsonSchema = zodToJsonSchema(fullSchema);
|
const jsonSchema = z.toJSONSchema(fullSchema, { io: "input", cycles: "ref" });
|
||||||
|
|
||||||
console.log(JSON.stringify(jsonSchema, null, 2));
|
fs.writeFileSync(outputPath, JSON.stringify(jsonSchema, null, 2), { encoding: "utf8" });
|
||||||
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
|
|
@ -12,7 +12,6 @@ import {
|
||||||
TextChannel,
|
TextChannel,
|
||||||
ThreadChannel,
|
ThreadChannel,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
import { EventEmitter } from "events";
|
|
||||||
import { Knub, PluginError, PluginLoadError, PluginNotLoadedError } from "knub";
|
import { Knub, PluginError, PluginLoadError, PluginNotLoadedError } from "knub";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { performance } from "perf_hooks";
|
import { performance } from "perf_hooks";
|
||||||
|
@ -252,9 +251,8 @@ connect().then(async () => {
|
||||||
GatewayIntentBits.GuildVoiceStates,
|
GatewayIntentBits.GuildVoiceStates,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// FIXME: TS doesn't see Client as a child of EventEmitter for some reason
|
|
||||||
// If you're here because of an error from TS 5.5.2, see https://github.com/discordjs/discord.js/issues/10358
|
client.setMaxListeners(200);
|
||||||
(client as unknown as EventEmitter).setMaxListeners(200);
|
|
||||||
|
|
||||||
const safe429DecayInterval = 5 * SECONDS;
|
const safe429DecayInterval = 5 * SECONDS;
|
||||||
const safe429MaxCount = 5;
|
const safe429MaxCount = 5;
|
||||||
|
|
|
@ -9,7 +9,7 @@ export class MigrateUsernamesToNewHistoryTable1556909512501 implements Migration
|
||||||
|
|
||||||
const migratedUsernames = new Set();
|
const migratedUsernames = new Set();
|
||||||
|
|
||||||
await new Promise(async (resolve) => {
|
await new Promise<void>(async (resolve) => {
|
||||||
const stream = await queryRunner.stream("SELECT CONCAT(user_id, '-', username) AS `key` FROM username_history");
|
const stream = await queryRunner.stream("SELECT CONCAT(user_id, '-', username) AS `key` FROM username_history");
|
||||||
stream.on("data", (row: any) => {
|
stream.on("data", (row: any) => {
|
||||||
migratedUsernames.add(row.key);
|
migratedUsernames.add(row.key);
|
||||||
|
|
|
@ -3,16 +3,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
BaseChannel,
|
||||||
|
BitField,
|
||||||
|
BitFieldResolvable,
|
||||||
ChatInputCommandInteraction,
|
ChatInputCommandInteraction,
|
||||||
|
CommandInteraction,
|
||||||
GuildMember,
|
GuildMember,
|
||||||
|
InteractionEditReplyOptions,
|
||||||
InteractionReplyOptions,
|
InteractionReplyOptions,
|
||||||
|
InteractionResponse,
|
||||||
Message,
|
Message,
|
||||||
MessageCreateOptions,
|
MessageCreateOptions,
|
||||||
|
MessageEditOptions,
|
||||||
|
MessageFlags,
|
||||||
|
MessageFlagsString,
|
||||||
|
ModalSubmitInteraction,
|
||||||
PermissionsBitField,
|
PermissionsBitField,
|
||||||
|
SendableChannels,
|
||||||
TextBasedChannel,
|
TextBasedChannel,
|
||||||
User,
|
User,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
import { AnyPluginData, BasePluginData, CommandContext, ExtendedMatchParams, GuildPluginData, helpers } from "knub";
|
import { AnyPluginData, BasePluginData, CommandContext, ExtendedMatchParams, GuildPluginData, helpers, PluginConfigManager } from "knub";
|
||||||
import { isStaff } from "./staff.js";
|
import { isStaff } from "./staff.js";
|
||||||
import { TZeppelinKnub } from "./types.js";
|
import { TZeppelinKnub } from "./types.js";
|
||||||
import { Tail } from "./utils/typeUtils.js";
|
import { Tail } from "./utils/typeUtils.js";
|
||||||
|
@ -49,57 +60,124 @@ export async function hasPermission(
|
||||||
return helpers.hasPermission(config, permission);
|
return helpers.hasPermission(config, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type GenericCommandSource = Message | CommandInteraction | ModalSubmitInteraction;
|
||||||
|
|
||||||
export function isContextInteraction(
|
export function isContextInteraction(
|
||||||
context: TextBasedChannel | Message | User | ChatInputCommandInteraction,
|
context: GenericCommandSource,
|
||||||
): context is ChatInputCommandInteraction {
|
): context is CommandInteraction | ModalSubmitInteraction {
|
||||||
return "commandId" in context && !!context.commandId;
|
return (context instanceof CommandInteraction || context instanceof ModalSubmitInteraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isContextMessage(
|
export function isContextMessage(
|
||||||
context: TextBasedChannel | Message | User | ChatInputCommandInteraction,
|
context: GenericCommandSource,
|
||||||
): context is Message {
|
): context is Message {
|
||||||
return "content" in context || "embeds" in context;
|
return (context instanceof Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getContextChannel(
|
export async function getContextChannel(
|
||||||
context: TextBasedChannel | Message | User | ChatInputCommandInteraction,
|
context: GenericCommandSource,
|
||||||
): Promise<TextBasedChannel> {
|
): Promise<TextBasedChannel | null> {
|
||||||
if (isContextInteraction(context)) {
|
if (isContextInteraction(context)) {
|
||||||
// context is ChatInputCommandInteraction
|
|
||||||
return context.channel!;
|
|
||||||
} else if ("username" in context) {
|
|
||||||
// context is User
|
|
||||||
return await (context as User).createDM();
|
|
||||||
} else if ("send" in context) {
|
|
||||||
// context is TextBaseChannel
|
|
||||||
return context as TextBasedChannel;
|
|
||||||
} else {
|
|
||||||
// context is Message
|
|
||||||
return context.channel;
|
return context.channel;
|
||||||
}
|
}
|
||||||
|
if (context instanceof Message) {
|
||||||
|
return context.channel;
|
||||||
|
}
|
||||||
|
throw new Error("Unknown context type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getContextChannelId(
|
||||||
|
context: GenericCommandSource,
|
||||||
|
): string | null {
|
||||||
|
return context.channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchContextChannel(context: GenericCommandSource) {
|
||||||
|
if (!context.guild) {
|
||||||
|
throw new Error("Missing context guild");
|
||||||
|
}
|
||||||
|
const channelId = getContextChannelId(context);
|
||||||
|
if (!channelId) {
|
||||||
|
throw new Error("Missing context channel ID");
|
||||||
|
}
|
||||||
|
return (await context.guild.channels.fetch(channelId))!;
|
||||||
|
}
|
||||||
|
|
||||||
|
function flagsWithEphemeral<
|
||||||
|
TFlags extends string,
|
||||||
|
TType extends number | bigint
|
||||||
|
>(flags: BitFieldResolvable<TFlags, any>, ephemeral: boolean): BitFieldResolvable<
|
||||||
|
TFlags | Extract<MessageFlagsString, "Ephemeral">,
|
||||||
|
TType | MessageFlags.Ephemeral
|
||||||
|
> {
|
||||||
|
if (!ephemeral) {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
return new BitField(flags).add(MessageFlags.Ephemeral) as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ContextResponseOptions = MessageCreateOptions & InteractionReplyOptions & InteractionEditReplyOptions;
|
||||||
|
export type ContextResponse = Message | InteractionResponse;
|
||||||
|
|
||||||
export async function sendContextResponse(
|
export async function sendContextResponse(
|
||||||
context: TextBasedChannel | Message | User | ChatInputCommandInteraction,
|
context: GenericCommandSource,
|
||||||
response: string | Omit<MessageCreateOptions, "flags"> | InteractionReplyOptions,
|
content: string | ContextResponseOptions,
|
||||||
|
ephemeral = false,
|
||||||
): Promise<Message> {
|
): Promise<Message> {
|
||||||
if (isContextInteraction(context)) {
|
if (isContextInteraction(context)) {
|
||||||
const options = { ...(typeof response === "string" ? { content: response } : response), fetchReply: true };
|
const options = { ...(typeof content === "string" ? { content: content } : content), fetchReply: true };
|
||||||
|
|
||||||
return (
|
if (context.replied) {
|
||||||
context.replied
|
return context.followUp({
|
||||||
? context.followUp(options)
|
...options,
|
||||||
: context.deferred
|
flags: flagsWithEphemeral(options.flags, ephemeral),
|
||||||
? context.editReply(options)
|
});
|
||||||
: context.reply(options)
|
}
|
||||||
) as Promise<Message>;
|
if (context.deferred) {
|
||||||
|
return context.editReply(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
const replyResult = await context.reply({
|
||||||
|
...options,
|
||||||
|
flags: flagsWithEphemeral(options.flags, ephemeral),
|
||||||
|
withResponse: true,
|
||||||
|
});
|
||||||
|
return replyResult.resource!.message!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof response !== "string" && "ephemeral" in response) {
|
const contextChannel = await fetchContextChannel(context);
|
||||||
delete response.ephemeral;
|
if (!contextChannel?.isSendable()) {
|
||||||
|
throw new Error("Context channel does not exist or is not sendable");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (await getContextChannel(context)).send(response as string | Omit<MessageCreateOptions, "flags">);
|
return contextChannel.send(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ContextResponseEditOptions = MessageEditOptions & InteractionEditReplyOptions;
|
||||||
|
|
||||||
|
export function editContextResponse(
|
||||||
|
response: ContextResponse,
|
||||||
|
content: string | ContextResponseEditOptions,
|
||||||
|
): Promise<ContextResponse> {
|
||||||
|
return response.edit(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteContextResponse(response: ContextResponse): Promise<void> {
|
||||||
|
await response.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getConfigForContext<TPluginData extends BasePluginData<any>>(config: PluginConfigManager<TPluginData>, context: GenericCommandSource): Promise<TPluginData["_pluginType"]["config"]> {
|
||||||
|
if (context instanceof ChatInputCommandInteraction) {
|
||||||
|
// TODO: Support for modal interactions (here and Knub)
|
||||||
|
return config.getForInteraction(context);
|
||||||
|
}
|
||||||
|
const channel = await getContextChannel(context);
|
||||||
|
const member = isContextMessage(context) && context.inGuild() ? await resolveMessageMember(context) : null;
|
||||||
|
|
||||||
|
return config.getMatchingConfig({
|
||||||
|
channel,
|
||||||
|
member,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBaseUrl(pluginData: AnyPluginData<any>) {
|
export function getBaseUrl(pluginData: AnyPluginData<any>) {
|
||||||
|
@ -147,4 +225,6 @@ export function makePublicFn<TPluginData extends BasePluginData<any>, T extends
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ???
|
export function resolveMessageMember(message: Message<true>) {
|
||||||
|
return Promise.resolve(message.member || message.guild.members.fetch(message.author.id));
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { GuildLogs } from "../../data/GuildLogs.js";
|
import { GuildLogs } from "../../data/GuildLogs.js";
|
||||||
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
|
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
|
||||||
import { SavedMessage } from "../../data/entities/SavedMessage.js";
|
import { SavedMessage } from "../../data/entities/SavedMessage.js";
|
||||||
|
|
|
@ -17,8 +17,8 @@ export async function deleteNextItem(pluginData: GuildPluginData<AutoDeletePlugi
|
||||||
scheduleNextDeletion(pluginData);
|
scheduleNextDeletion(pluginData);
|
||||||
|
|
||||||
const channel = pluginData.guild.channels.cache.get(itemToDelete.message.channel_id as Snowflake);
|
const channel = pluginData.guild.channels.cache.get(itemToDelete.message.channel_id as Snowflake);
|
||||||
if (!channel || channel.type === ChannelType.GuildCategory) {
|
if (!channel || !("messages" in channel)) {
|
||||||
// Channel was deleted, ignore
|
// Channel does not exist or does not support messages, ignore
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand, pluginUtils } from "knub";
|
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand, pluginUtils } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { GuildAutoReactions } from "../../data/GuildAutoReactions.js";
|
import { GuildAutoReactions } from "../../data/GuildAutoReactions.js";
|
||||||
import { GuildLogs } from "../../data/GuildLogs.js";
|
import { GuildLogs } from "../../data/GuildLogs.js";
|
||||||
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
|
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { nonNullish, unique, zSnowflake } from "../../../utils.js";
|
import { nonNullish, unique, zSnowflake } from "../../../utils.js";
|
||||||
import { canAssignRole } from "../../../utils/canAssignRole.js";
|
import { canAssignRole } from "../../../utils/canAssignRole.js";
|
||||||
import { getMissingPermissions } from "../../../utils/getMissingPermissions.js";
|
import { getMissingPermissions } from "../../../utils/getMissingPermissions.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { zBoundedCharacters } from "../../../utils.js";
|
import { zBoundedCharacters } from "../../../utils.js";
|
||||||
import { CountersPlugin } from "../../Counters/CountersPlugin.js";
|
import { CountersPlugin } from "../../Counters/CountersPlugin.js";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Snowflake } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { LogType } from "../../../data/LogType.js";
|
import { LogType } from "../../../data/LogType.js";
|
||||||
import {
|
import {
|
||||||
createTypedTemplateSafeValueContainer,
|
createTypedTemplateSafeValueContainer,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { AnyThreadChannel } from "discord.js";
|
import { AnyThreadChannel } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { noop } from "../../../utils.js";
|
import { noop } from "../../../utils.js";
|
||||||
import { automodAction } from "../helpers.js";
|
import { automodAction } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import {
|
import {
|
||||||
convertDelayStringToMS,
|
convertDelayStringToMS,
|
||||||
nonNullish,
|
nonNullish,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { nonNullish, unique, zBoundedCharacters } from "../../../utils.js";
|
import { nonNullish, unique, zBoundedCharacters } from "../../../utils.js";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
||||||
import { automodAction } from "../helpers.js";
|
import { automodAction } from "../helpers.js";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { PermissionsBitField, PermissionsString } from "discord.js";
|
import { PermissionsBitField, PermissionsString } from "discord.js";
|
||||||
import { U } from "ts-toolbelt";
|
import { U } from "ts-toolbelt";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { TemplateParseError, TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
import { TemplateParseError, TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
||||||
import { isValidSnowflake, keys, noop, zBoundedCharacters } from "../../../utils.js";
|
import { isValidSnowflake, keys, noop, zBoundedCharacters } from "../../../utils.js";
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GuildTextBasedChannel, Snowflake } from "discord.js";
|
import { GuildTextBasedChannel, Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { LogType } from "../../../data/LogType.js";
|
import { LogType } from "../../../data/LogType.js";
|
||||||
import { noop } from "../../../utils.js";
|
import { noop } from "../../../utils.js";
|
||||||
import { automodAction } from "../helpers.js";
|
import { automodAction } from "../helpers.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { zBoundedCharacters } from "../../../utils.js";
|
import { zBoundedCharacters } from "../../../utils.js";
|
||||||
import { automodAction } from "../helpers.js";
|
import { automodAction } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { asyncMap, nonNullish, resolveMember, unique, zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
import { asyncMap, nonNullish, resolveMember, unique, zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
||||||
import { CaseArgs } from "../../Cases/types.js";
|
import { CaseArgs } from "../../Cases/types.js";
|
||||||
import { ModActionsPlugin } from "../../ModActions/ModActionsPlugin.js";
|
import { ModActionsPlugin } from "../../ModActions/ModActionsPlugin.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { isTruthy, unique } from "../../../utils.js";
|
import { isTruthy, unique } from "../../../utils.js";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
||||||
import { automodAction } from "../helpers.js";
|
import { automodAction } from "../helpers.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError.js";
|
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError.js";
|
||||||
import {
|
import {
|
||||||
convertDelayStringToMS,
|
convertDelayStringToMS,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GuildFeature } from "discord.js";
|
import { GuildFeature } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodAction } from "../helpers.js";
|
import { automodAction } from "../helpers.js";
|
||||||
|
|
||||||
export const PauseInvitesAction = automodAction({
|
export const PauseInvitesAction = automodAction({
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { nonNullish, unique, zSnowflake } from "../../../utils.js";
|
import { nonNullish, unique, zSnowflake } from "../../../utils.js";
|
||||||
import { canAssignRole } from "../../../utils/canAssignRole.js";
|
import { canAssignRole } from "../../../utils/canAssignRole.js";
|
||||||
import { getMissingPermissions } from "../../../utils/getMissingPermissions.js";
|
import { getMissingPermissions } from "../../../utils/getMissingPermissions.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GuildTextBasedChannel, MessageCreateOptions, PermissionsBitField, Snowflake, User } from "discord.js";
|
import { GuildTextBasedChannel, MessageCreateOptions, PermissionsBitField, Snowflake, User } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { TemplateParseError, TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
import { TemplateParseError, TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
||||||
import {
|
import {
|
||||||
convertDelayStringToMS,
|
convertDelayStringToMS,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { MAX_COUNTER_VALUE, MIN_COUNTER_VALUE } from "../../../data/GuildCounters.js";
|
import { MAX_COUNTER_VALUE, MIN_COUNTER_VALUE } from "../../../data/GuildCounters.js";
|
||||||
import { zBoundedCharacters } from "../../../utils.js";
|
import { zBoundedCharacters } from "../../../utils.js";
|
||||||
import { CountersPlugin } from "../../Counters/CountersPlugin.js";
|
import { CountersPlugin } from "../../Counters/CountersPlugin.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ChannelType, GuildTextBasedChannel, Snowflake } from "discord.js";
|
import { ChannelType, GuildTextBasedChannel, Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { convertDelayStringToMS, isDiscordAPIError, zDelayString, zSnowflake } from "../../../utils.js";
|
import { convertDelayStringToMS, isDiscordAPIError, zDelayString, zSnowflake } from "../../../utils.js";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
import { LogsPlugin } from "../../Logs/LogsPlugin.js";
|
||||||
import { automodAction } from "../helpers.js";
|
import { automodAction } from "../helpers.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ChannelType, GuildTextThreadCreateOptions, ThreadAutoArchiveDuration, ThreadChannel } from "discord.js";
|
import { ChannelType, GuildTextThreadCreateOptions, ThreadAutoArchiveDuration, ThreadChannel } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { TemplateParseError, TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
import { TemplateParseError, TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
||||||
import { MINUTES, convertDelayStringToMS, noop, zBoundedCharacters, zDelayString } from "../../../utils.js";
|
import { MINUTES, convertDelayStringToMS, noop, zBoundedCharacters, zDelayString } from "../../../utils.js";
|
||||||
import { savedMessageToTemplateSafeSavedMessage, userToTemplateSafeUser } from "../../../utils/templateSafeObjects.js";
|
import { savedMessageToTemplateSafeSavedMessage, userToTemplateSafeUser } from "../../../utils/templateSafeObjects.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { asyncMap, nonNullish, resolveMember, unique, zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
import { asyncMap, nonNullish, resolveMember, unique, zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
||||||
import { CaseArgs } from "../../Cases/types.js";
|
import { CaseArgs } from "../../Cases/types.js";
|
||||||
import { ModActionsPlugin } from "../../ModActions/ModActionsPlugin.js";
|
import { ModActionsPlugin } from "../../ModActions/ModActionsPlugin.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { MINUTES, SECONDS } from "../../utils.js";
|
import { MINUTES, SECONDS } from "../../utils.js";
|
||||||
|
|
||||||
export const RECENT_SPAM_EXPIRY_TIME = 10 * SECONDS;
|
export const RECENT_SPAM_EXPIRY_TIME = 10 * SECONDS;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { SavedMessage } from "../../../data/entities/SavedMessage.js";
|
import { SavedMessage } from "../../../data/entities/SavedMessage.js";
|
||||||
import { humanizeDurationShort } from "../../../humanizeDuration.js";
|
import { humanizeDurationShort } from "../../../humanizeDuration.js";
|
||||||
import { getBaseUrl } from "../../../pluginUtils.js";
|
import { getBaseUrl } from "../../../pluginUtils.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z, { ZodTypeAny } from "zod";
|
import z, { ZodTypeAny } from "zod/v4";
|
||||||
import { Awaitable } from "../../utils/typeUtils.js";
|
import { Awaitable } from "../../utils/typeUtils.js";
|
||||||
import { AutomodContext, AutomodPluginType } from "./types.js";
|
import { AutomodContext, AutomodPluginType } from "./types.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
interface AntiraidLevelTriggerResult {}
|
interface AntiraidLevelTriggerResult {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Snowflake } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { verboseChannelMention } from "../../../utils.js";
|
import { verboseChannelMention } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
interface ExampleMatchResultType {
|
interface ExampleMatchResultType {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { escapeInlineCode, Snowflake } from "discord.js";
|
import { escapeInlineCode, Snowflake } from "discord.js";
|
||||||
import { extname } from "path";
|
import { extname } from "path";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils.js";
|
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { getInviteCodesInString, GuildInvite, isGuildInvite, resolveInvite, zSnowflake } from "../../../utils.js";
|
import { getInviteCodesInString, GuildInvite, isGuildInvite, resolveInvite, zSnowflake } from "../../../utils.js";
|
||||||
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary.js";
|
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary.js";
|
||||||
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage.js";
|
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { escapeInlineCode } from "discord.js";
|
import { escapeInlineCode } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { allowTimeout } from "../../../RegExpRunner.js";
|
import { allowTimeout } from "../../../RegExpRunner.js";
|
||||||
import { phishermanDomainIsSafe } from "../../../data/Phisherman.js";
|
import { phishermanDomainIsSafe } from "../../../data/Phisherman.js";
|
||||||
import { getUrlsInString, zRegex } from "../../../utils.js";
|
import { getUrlsInString, zRegex } from "../../../utils.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { escapeInlineCode } from "discord.js";
|
import { escapeInlineCode } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils.js";
|
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { allowTimeout } from "../../../RegExpRunner.js";
|
import { allowTimeout } from "../../../RegExpRunner.js";
|
||||||
import { zRegex } from "../../../utils.js";
|
import { zRegex } from "../../../utils.js";
|
||||||
import { mergeRegexes } from "../../../utils/mergeRegexes.js";
|
import { mergeRegexes } from "../../../utils/mergeRegexes.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import escapeStringRegexp from "escape-string-regexp";
|
import escapeStringRegexp from "escape-string-regexp";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { normalizeText } from "../../../utils/normalizeText.js";
|
import { normalizeText } from "../../../utils/normalizeText.js";
|
||||||
import { stripMarkdown } from "../../../utils/stripMarkdown.js";
|
import { stripMarkdown } from "../../../utils/stripMarkdown.js";
|
||||||
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary.js";
|
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { convertDelayStringToMS, zDelayString } from "../../../utils.js";
|
import { convertDelayStringToMS, zDelayString } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { convertDelayStringToMS, zDelayString } from "../../../utils.js";
|
import { convertDelayStringToMS, zDelayString } from "../../../utils.js";
|
||||||
import { RecentActionType } from "../constants.js";
|
import { RecentActionType } from "../constants.js";
|
||||||
import { findRecentSpam } from "../functions/findRecentSpam.js";
|
import { findRecentSpam } from "../functions/findRecentSpam.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
const configSchema = z.strictObject({});
|
const configSchema = z.strictObject({});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Snowflake } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { renderUsername, zSnowflake } from "../../../utils.js";
|
import { renderUsername, zSnowflake } from "../../../utils.js";
|
||||||
import { consumeIgnoredRoleChange } from "../functions/ignoredRoleChanges.js";
|
import { consumeIgnoredRoleChange } from "../functions/ignoredRoleChanges.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Snowflake } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { renderUsername, zSnowflake } from "../../../utils.js";
|
import { renderUsername, zSnowflake } from "../../../utils.js";
|
||||||
import { consumeIgnoredRoleChange } from "../functions/ignoredRoleChanges.js";
|
import { consumeIgnoredRoleChange } from "../functions/ignoredRoleChanges.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { User, escapeBold, type Snowflake } from "discord.js";
|
import { User, escapeBold, type Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { renderUsername } from "../../../utils.js";
|
import { renderUsername } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { User, escapeBold, type Snowflake } from "discord.js";
|
import { User, escapeBold, type Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { renderUsername } from "../../../utils.js";
|
import { renderUsername } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { convertDelayStringToMS, zDelayString } from "../../../utils.js";
|
import { convertDelayStringToMS, zDelayString } from "../../../utils.js";
|
||||||
import { RecentActionType } from "../constants.js";
|
import { RecentActionType } from "../constants.js";
|
||||||
import { findRecentSpam } from "../functions/findRecentSpam.js";
|
import { findRecentSpam } from "../functions/findRecentSpam.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { User, escapeBold, type Snowflake } from "discord.js";
|
import { User, escapeBold, type Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { renderUsername } from "../../../utils.js";
|
import { renderUsername } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { User, escapeBold, type Snowflake } from "discord.js";
|
import { User, escapeBold, type Snowflake } from "discord.js";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { renderUsername } from "../../../utils.js";
|
import { renderUsername } from "../../../utils.js";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { automodTrigger } from "../helpers.js";
|
import { automodTrigger } from "../helpers.js";
|
||||||
|
|
||||||
// tslint:disable-next-line:no-empty-interface
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { GuildMember, GuildTextBasedChannel, PartialGuildMember, ThreadChannel, User } from "discord.js";
|
import { GuildMember, GuildTextBasedChannel, PartialGuildMember, ThreadChannel, User } from "discord.js";
|
||||||
import { BasePluginType, CooldownManager, pluginUtils } from "knub";
|
import { BasePluginType, CooldownManager, pluginUtils } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { Queue } from "../../Queue.js";
|
import { Queue } from "../../Queue.js";
|
||||||
import { RegExpRunner } from "../../RegExpRunner.js";
|
import { RegExpRunner } from "../../RegExpRunner.js";
|
||||||
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels.js";
|
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType, globalPluginEventListener, globalPluginMessageCommand } from "knub";
|
import { BasePluginType, globalPluginEventListener, globalPluginMessageCommand } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { AllowedGuilds } from "../../data/AllowedGuilds.js";
|
import { AllowedGuilds } from "../../data/AllowedGuilds.js";
|
||||||
import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments.js";
|
import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments.js";
|
||||||
import { Configs } from "../../data/Configs.js";
|
import { Configs } from "../../data/Configs.js";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { escapeCodeBlock, MessageCreateOptions, MessageEditOptions } from "discord.js";
|
import { escapeCodeBlock, InteractionEditReplyOptions, InteractionReplyOptions, MessageCreateOptions, MessageEditOptions } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { CaseTypes } from "../../../data/CaseTypes.js";
|
import { CaseTypes } from "../../../data/CaseTypes.js";
|
||||||
|
@ -14,7 +14,7 @@ export async function getCaseEmbed(
|
||||||
caseOrCaseId: Case | number,
|
caseOrCaseId: Case | number,
|
||||||
requestMemberId?: string,
|
requestMemberId?: string,
|
||||||
noOriginalCaseLink?: boolean,
|
noOriginalCaseLink?: boolean,
|
||||||
): Promise<MessageCreateOptions & MessageEditOptions> {
|
): Promise<MessageCreateOptions & MessageEditOptions & InteractionReplyOptions & InteractionEditReplyOptions> {
|
||||||
const theCase = await pluginData.state.cases.with("notes").find(resolveCaseId(caseOrCaseId));
|
const theCase = await pluginData.state.cases.with("notes").find(resolveCaseId(caseOrCaseId));
|
||||||
if (!theCase) {
|
if (!theCase) {
|
||||||
throw new Error("Unknown case");
|
throw new Error("Unknown case");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import { U } from "ts-toolbelt";
|
import { U } from "ts-toolbelt";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { CaseNameToType, CaseTypes } from "../../data/CaseTypes.js";
|
import { CaseNameToType, CaseTypes } from "../../data/CaseTypes.js";
|
||||||
import { GuildArchives } from "../../data/GuildArchives.js";
|
import { GuildArchives } from "../../data/GuildArchives.js";
|
||||||
import { GuildCases } from "../../data/GuildCases.js";
|
import { GuildCases } from "../../data/GuildCases.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { RegExpRunner } from "../../RegExpRunner.js";
|
import { RegExpRunner } from "../../RegExpRunner.js";
|
||||||
import { GuildLogs } from "../../data/GuildLogs.js";
|
import { GuildLogs } from "../../data/GuildLogs.js";
|
||||||
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
|
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { guildPlugin } from "knub";
|
import { guildPlugin } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
||||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin.js";
|
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin.js";
|
||||||
import { ArchiveChannelCmd } from "./commands/ArchiveChannelCmd.js";
|
import { ArchiveChannelCmd } from "./commands/ArchiveChannelCmd.js";
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import {
|
import {
|
||||||
Attachment,
|
Attachment,
|
||||||
ChatInputCommandInteraction,
|
ChatInputCommandInteraction,
|
||||||
|
InteractionResponse,
|
||||||
Message,
|
Message,
|
||||||
MessageCreateOptions,
|
MessageCreateOptions,
|
||||||
MessageMentionOptions,
|
MessageMentionOptions,
|
||||||
ModalSubmitInteraction,
|
ModalSubmitInteraction,
|
||||||
|
SendableChannels,
|
||||||
TextBasedChannel,
|
TextBasedChannel,
|
||||||
User,
|
User,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
import { PluginOptions, guildPlugin } from "knub";
|
import { PluginOptions, guildPlugin } from "knub";
|
||||||
import { logger } from "../../logger.js";
|
import { logger } from "../../logger.js";
|
||||||
import { isContextInteraction, sendContextResponse } from "../../pluginUtils.js";
|
import { GenericCommandSource, isContextInteraction, sendContextResponse } from "../../pluginUtils.js";
|
||||||
import { errorMessage, successMessage } from "../../utils.js";
|
import { errorMessage, successMessage } from "../../utils.js";
|
||||||
import { getErrorEmoji, getSuccessEmoji } from "./functions/getEmoji.js";
|
import { getErrorEmoji, getSuccessEmoji } from "./functions/getEmoji.js";
|
||||||
import { CommonPluginType, zCommonConfig } from "./types.js";
|
import { CommonPluginType, zCommonConfig } from "./types.js";
|
||||||
|
@ -34,101 +36,39 @@ export const CommonPlugin = guildPlugin<CommonPluginType>()({
|
||||||
getErrorEmoji,
|
getErrorEmoji,
|
||||||
|
|
||||||
sendSuccessMessage: async (
|
sendSuccessMessage: async (
|
||||||
context: TextBasedChannel | Message | User | ChatInputCommandInteraction,
|
context: GenericCommandSource | SendableChannels,
|
||||||
body: string,
|
body: string,
|
||||||
allowedMentions?: MessageMentionOptions,
|
allowedMentions?: MessageMentionOptions,
|
||||||
responseInteraction?: ModalSubmitInteraction,
|
responseInteraction?: never,
|
||||||
ephemeral = true,
|
ephemeral = true,
|
||||||
): Promise<Message | undefined> => {
|
) => {
|
||||||
const emoji = getSuccessEmoji(pluginData);
|
const emoji = getSuccessEmoji(pluginData);
|
||||||
const formattedBody = successMessage(body, emoji);
|
const formattedBody = successMessage(body, emoji);
|
||||||
const content: MessageCreateOptions = allowedMentions
|
const content = allowedMentions
|
||||||
? { content: formattedBody, allowedMentions }
|
? { content: formattedBody, allowedMentions }
|
||||||
: { content: formattedBody };
|
: { content: formattedBody };
|
||||||
|
if ("isSendable" in context) {
|
||||||
if (responseInteraction) {
|
return context.send(content);
|
||||||
await responseInteraction
|
|
||||||
.editReply({ content: formattedBody, embeds: [], components: [] })
|
|
||||||
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return sendContextResponse(context, content, ephemeral);
|
||||||
if (!isContextInteraction(context)) {
|
|
||||||
// noinspection TypeScriptValidateJSTypes
|
|
||||||
return sendContextResponse(context, { ...content }) // Force line break
|
|
||||||
.catch((err) => {
|
|
||||||
const channelInfo =
|
|
||||||
"guild" in context && context.guild ? `${context.id} (${context.guild.id})` : context.id;
|
|
||||||
|
|
||||||
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const replyMethod = context.replied || context.deferred ? "editReply" : "reply";
|
|
||||||
|
|
||||||
return context[replyMethod]({
|
|
||||||
content: formattedBody,
|
|
||||||
embeds: [],
|
|
||||||
components: [],
|
|
||||||
fetchReply: true,
|
|
||||||
ephemeral,
|
|
||||||
}).catch((err) => {
|
|
||||||
logger.error(`Context reply failed: ${err}`);
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}) as Promise<Message>;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
sendErrorMessage: async (
|
sendErrorMessage: async (
|
||||||
context: TextBasedChannel | Message | User | ChatInputCommandInteraction,
|
context: GenericCommandSource | SendableChannels,
|
||||||
body: string,
|
body: string,
|
||||||
allowedMentions?: MessageMentionOptions,
|
allowedMentions?: MessageMentionOptions,
|
||||||
responseInteraction?: ModalSubmitInteraction,
|
responseInteraction?: never,
|
||||||
ephemeral = true,
|
ephemeral = true,
|
||||||
): Promise<Message | undefined> => {
|
) => {
|
||||||
const emoji = getErrorEmoji(pluginData);
|
const emoji = getErrorEmoji(pluginData);
|
||||||
const formattedBody = errorMessage(body, emoji);
|
const formattedBody = errorMessage(body, emoji);
|
||||||
const content: MessageCreateOptions = allowedMentions
|
const content = allowedMentions
|
||||||
? { content: formattedBody, allowedMentions }
|
? { content: formattedBody, allowedMentions }
|
||||||
: { content: formattedBody };
|
: { content: formattedBody };
|
||||||
|
if ("isSendable" in context) {
|
||||||
if (responseInteraction) {
|
return context.send(content);
|
||||||
await responseInteraction
|
|
||||||
.editReply({ content: formattedBody, embeds: [], components: [] })
|
|
||||||
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return sendContextResponse(context, content, ephemeral);
|
||||||
if (!isContextInteraction(context)) {
|
|
||||||
// noinspection TypeScriptValidateJSTypes
|
|
||||||
return sendContextResponse(context, { ...content }) // Force line break
|
|
||||||
.catch((err) => {
|
|
||||||
const channelInfo =
|
|
||||||
"guild" in context && context.guild ? `${context.id} (${context.guild.id})` : context.id;
|
|
||||||
|
|
||||||
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const replyMethod = context.replied || context.deferred ? "editReply" : "reply";
|
|
||||||
|
|
||||||
return context[replyMethod]({
|
|
||||||
content: formattedBody,
|
|
||||||
embeds: [],
|
|
||||||
components: [],
|
|
||||||
fetchReply: true,
|
|
||||||
ephemeral,
|
|
||||||
}).catch((err) => {
|
|
||||||
logger.error(`Context reply failed: ${err}`);
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}) as Promise<Message>;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
storeAttachmentsAsMessage: async (attachments: Attachment[], backupChannel?: TextBasedChannel | null) => {
|
storeAttachmentsAsMessage: async (attachments: Attachment[], backupChannel?: TextBasedChannel | null) => {
|
||||||
|
@ -142,8 +82,13 @@ export const CommonPlugin = guildPlugin<CommonPluginType>()({
|
||||||
"Cannot store attachments: no attachment storing channel configured, and no backup channel passed",
|
"Cannot store attachments: no attachment storing channel configured, and no backup channel passed",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (!channel.isSendable()) {
|
||||||
|
throw new Error(
|
||||||
|
"Passed attachment storage channel is not sendable",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return channel!.send({
|
return channel.send({
|
||||||
content: `Storing ${attachments.length} attachment${attachments.length === 1 ? "" : "s"}`,
|
content: `Storing ${attachments.length} attachment${attachments.length === 1 ? "" : "s"}`,
|
||||||
files: attachments.map((a) => a.url),
|
files: attachments.map((a) => a.url),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
|
|
||||||
export const zCommonConfig = z.strictObject({
|
export const zCommonConfig = z.strictObject({
|
||||||
success_emoji: z.string(),
|
success_emoji: z.string(),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType, CooldownManager, guildPluginEventListener } from "knub";
|
import { BasePluginType, CooldownManager, guildPluginEventListener } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { GuildLogs } from "../../data/GuildLogs.js";
|
import { GuildLogs } from "../../data/GuildLogs.js";
|
||||||
import { zBoundedCharacters, zSnowflake } from "../../utils.js";
|
import { zBoundedCharacters, zSnowflake } from "../../utils.js";
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ export async function cleanAction(
|
||||||
amount: number,
|
amount: number,
|
||||||
target: string,
|
target: string,
|
||||||
targetMessage: Message,
|
targetMessage: Message,
|
||||||
targetChannel: string,
|
targetChannelId: string,
|
||||||
interaction: ModalSubmitInteraction,
|
interaction: ModalSubmitInteraction,
|
||||||
) {
|
) {
|
||||||
const executingMember = await pluginData.guild.members.fetch(interaction.user.id);
|
const executingMember = await pluginData.guild.members.fetch(interaction.user.id);
|
||||||
|
@ -28,13 +28,21 @@ export async function cleanAction(
|
||||||
});
|
});
|
||||||
const utility = pluginData.getPlugin(UtilityPlugin);
|
const utility = pluginData.getPlugin(UtilityPlugin);
|
||||||
|
|
||||||
if (!userCfg.can_use || !(await utility.hasPermission(executingMember, targetChannel, "can_clean"))) {
|
if (!userCfg.can_use || !(await utility.hasPermission(executingMember, targetChannelId, "can_clean"))) {
|
||||||
await interaction
|
await interaction
|
||||||
.editReply({ content: "Cannot clean: insufficient permissions", embeds: [], components: [] })
|
.editReply({ content: "Cannot clean: insufficient permissions", embeds: [], components: [] })
|
||||||
.catch((err) => logger.error(`Clean interaction reply failed: ${err}`));
|
.catch((err) => logger.error(`Clean interaction reply failed: ${err}`));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const targetChannel = await pluginData.guild.channels.fetch(targetChannelId);
|
||||||
|
if (!targetChannel?.isTextBased()) {
|
||||||
|
await interaction
|
||||||
|
.editReply({ content: "Cannot clean: target channel is not a text channel", embeds: [], components: [] })
|
||||||
|
.catch((err) => logger.error(`Clean interaction reply failed: ${err}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await interaction
|
await interaction
|
||||||
.editReply({
|
.editReply({
|
||||||
content: `Cleaning ${amount} messages from ${target}...`,
|
content: `Cleaning ${amount} messages from ${target}...`,
|
||||||
|
@ -43,7 +51,21 @@ export async function cleanAction(
|
||||||
})
|
})
|
||||||
.catch((err) => logger.error(`Clean interaction reply failed: ${err}`));
|
.catch((err) => logger.error(`Clean interaction reply failed: ${err}`));
|
||||||
|
|
||||||
await utility.clean({ count: amount, channel: targetChannel, "response-interaction": interaction }, targetMessage);
|
const fetchMessagesResult = await utility.fetchChannelMessagesToClean(targetChannel, {
|
||||||
|
count: amount,
|
||||||
|
beforeId: targetMessage.id,
|
||||||
|
});
|
||||||
|
if ("error" in fetchMessagesResult) {
|
||||||
|
interaction.editReply(fetchMessagesResult.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fetchMessagesResult.messages.length > 0) {
|
||||||
|
await utility.cleanMessages(targetChannel, fetchMessagesResult.messages, interaction.user);
|
||||||
|
interaction.editReply(`Cleaned ${fetchMessagesResult.messages.length} ${fetchMessagesResult.messages.length === 1 ? "message" : "messages"}`);
|
||||||
|
} else {
|
||||||
|
interaction.editReply("No messages to clean");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function launchCleanActionModal(
|
export async function launchCleanActionModal(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { APIEmbed, Awaitable } from "discord.js";
|
import { APIEmbed, Awaitable } from "discord.js";
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { GuildCases } from "../../data/GuildCases.js";
|
import { GuildCases } from "../../data/GuildCases.js";
|
||||||
|
|
||||||
export const zContextMenusConfig = z.strictObject({
|
export const zContextMenusConfig = z.strictObject({
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { PluginOptions, guildPlugin } from "knub";
|
import { PluginOptions, guildPlugin } from "knub";
|
||||||
import { GuildCounters } from "../../data/GuildCounters.js";
|
import { GuildCounters } from "../../data/GuildCounters.js";
|
||||||
import { CounterTrigger, parseCounterConditionString } from "../../data/entities/CounterTrigger.js";
|
import { buildCounterConditionString, CounterTrigger, getReverseCounterComparisonOp, parseCounterConditionString } from "../../data/entities/CounterTrigger.js";
|
||||||
import { makePublicFn } from "../../pluginUtils.js";
|
import { makePublicFn } from "../../pluginUtils.js";
|
||||||
import { MINUTES, convertDelayStringToMS } from "../../utils.js";
|
import { MINUTES, convertDelayStringToMS } from "../../utils.js";
|
||||||
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
||||||
|
@ -89,7 +89,7 @@ export const CountersPlugin = guildPlugin<CountersPluginType>()({
|
||||||
const { state, guild } = pluginData;
|
const { state, guild } = pluginData;
|
||||||
|
|
||||||
state.counters = new GuildCounters(guild.id);
|
state.counters = new GuildCounters(guild.id);
|
||||||
state.events = new EventEmitter();
|
state.events = new EventEmitter() as any;
|
||||||
state.counterTriggersByCounterId = new Map();
|
state.counterTriggersByCounterId = new Map();
|
||||||
|
|
||||||
const activeTriggerIds: number[] = [];
|
const activeTriggerIds: number[] = [];
|
||||||
|
@ -107,7 +107,8 @@ export const CountersPlugin = guildPlugin<CountersPluginType>()({
|
||||||
// Initialize triggers
|
// Initialize triggers
|
||||||
for (const [triggerName, trigger] of Object.entries(counter.triggers)) {
|
for (const [triggerName, trigger] of Object.entries(counter.triggers)) {
|
||||||
const parsedCondition = parseCounterConditionString(trigger.condition)!;
|
const parsedCondition = parseCounterConditionString(trigger.condition)!;
|
||||||
const parsedReverseCondition = parseCounterConditionString(trigger.reverse_condition)!;
|
const rawReverseCondition = trigger.reverse_condition || buildCounterConditionString(getReverseCounterComparisonOp(parsedCondition[0]), parsedCondition[1]);
|
||||||
|
const parsedReverseCondition = parseCounterConditionString(rawReverseCondition)!;
|
||||||
const counterTrigger = await state.counters.initCounterTrigger(
|
const counterTrigger = await state.counters.initCounterTrigger(
|
||||||
dbCounter.id,
|
dbCounter.id,
|
||||||
triggerName,
|
triggerName,
|
||||||
|
@ -167,6 +168,6 @@ export const CountersPlugin = guildPlugin<CountersPluginType>()({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.events.removeAllListeners();
|
(state.events as any).removeAllListeners();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,5 +13,5 @@ export function getPrettyNameForCounterTrigger(
|
||||||
}
|
}
|
||||||
|
|
||||||
const trigger = counter.triggers[triggerName];
|
const trigger = counter.triggers[triggerName];
|
||||||
return trigger ? trigger.pretty_name || trigger.name : "Unknown Counter Trigger";
|
return trigger ? trigger.pretty_name || triggerName : "Unknown Counter Trigger";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { BasePluginType, pluginUtils } from "knub";
|
import { BasePluginType, pluginUtils } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { GuildCounters, MAX_COUNTER_VALUE, MIN_COUNTER_VALUE } from "../../data/GuildCounters.js";
|
import { GuildCounters, MAX_COUNTER_VALUE, MIN_COUNTER_VALUE } from "../../data/GuildCounters.js";
|
||||||
import {
|
import {
|
||||||
CounterTrigger,
|
CounterTrigger,
|
||||||
|
@ -18,10 +18,6 @@ const MAX_TRIGGERS_PER_COUNTER = 5;
|
||||||
export const zTrigger = z
|
export const zTrigger = z
|
||||||
.strictObject({
|
.strictObject({
|
||||||
// Dummy type because name gets replaced by the property key in transform()
|
// Dummy type because name gets replaced by the property key in transform()
|
||||||
name: z
|
|
||||||
.never()
|
|
||||||
.optional()
|
|
||||||
.transform(() => ""),
|
|
||||||
pretty_name: zBoundedCharacters(0, 100).nullable().default(null),
|
pretty_name: zBoundedCharacters(0, 100).nullable().default(null),
|
||||||
condition: zBoundedCharacters(1, 64).refine((str) => parseCounterConditionString(str) !== null, {
|
condition: zBoundedCharacters(1, 64).refine((str) => parseCounterConditionString(str) !== null, {
|
||||||
message: "Invalid counter trigger condition",
|
message: "Invalid counter trigger condition",
|
||||||
|
@ -31,28 +27,9 @@ export const zTrigger = z
|
||||||
message: "Invalid counter trigger reverse condition",
|
message: "Invalid counter trigger reverse condition",
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
})
|
|
||||||
.transform((val, ctx) => {
|
|
||||||
const ruleName = String(ctx.path[ctx.path.length - 1]).trim();
|
|
||||||
|
|
||||||
let reverseCondition = val.reverse_condition;
|
|
||||||
if (!reverseCondition) {
|
|
||||||
const parsedCondition = parseCounterConditionString(val.condition)!;
|
|
||||||
reverseCondition = buildCounterConditionString(
|
|
||||||
getReverseCounterComparisonOp(parsedCondition[0]),
|
|
||||||
parsedCondition[1],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...val,
|
|
||||||
name: ruleName,
|
|
||||||
reverse_condition: reverseCondition,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const zTriggerFromString = zBoundedCharacters(0, 100).transform((val, ctx) => {
|
const zTriggerFromString = zBoundedCharacters(0, 100).transform((val, ctx) => {
|
||||||
const ruleName = String(ctx.path[ctx.path.length - 1]).trim();
|
|
||||||
const parsedCondition = parseCounterConditionString(val);
|
const parsedCondition = parseCounterConditionString(val);
|
||||||
if (!parsedCondition) {
|
if (!parsedCondition) {
|
||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
|
@ -62,7 +39,6 @@ const zTriggerFromString = zBoundedCharacters(0, 100).transform((val, ctx) => {
|
||||||
return z.NEVER;
|
return z.NEVER;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name: ruleName,
|
|
||||||
pretty_name: null,
|
pretty_name: null,
|
||||||
condition: buildCounterConditionString(parsedCondition[0], parsedCondition[1]),
|
condition: buildCounterConditionString(parsedCondition[0], parsedCondition[1]),
|
||||||
reverse_condition: buildCounterConditionString(
|
reverse_condition: buildCounterConditionString(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { canActOn } from "../../../pluginUtils.js";
|
import { canActOn } from "../../../pluginUtils.js";
|
||||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
||||||
import { resolveMember, zSnowflake } from "../../../utils.js";
|
import { resolveMember, zSnowflake } from "../../../utils.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { CaseTypes } from "../../../data/CaseTypes.js";
|
import { CaseTypes } from "../../../data/CaseTypes.js";
|
||||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
||||||
import { zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
import { zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Snowflake } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
import { TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
||||||
import { convertDelayStringToMS, noop, zDelayString, zSnowflake } from "../../../utils.js";
|
import { convertDelayStringToMS, noop, zDelayString, zSnowflake } from "../../../utils.js";
|
||||||
import { ActionError } from "../ActionError.js";
|
import { ActionError } from "../ActionError.js";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Snowflake } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
import { TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
||||||
import { zSnowflake } from "../../../utils.js";
|
import { zSnowflake } from "../../../utils.js";
|
||||||
import { ActionError } from "../ActionError.js";
|
import { ActionError } from "../ActionError.js";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Snowflake, TextChannel } from "discord.js";
|
import { Snowflake, TextChannel } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
import { TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
||||||
import { zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
import { zBoundedCharacters, zSnowflake } from "../../../utils.js";
|
||||||
import { ActionError } from "../ActionError.js";
|
import { ActionError } from "../ActionError.js";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Snowflake, VoiceChannel } from "discord.js";
|
import { Snowflake, VoiceChannel } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { canActOn } from "../../../pluginUtils.js";
|
import { canActOn } from "../../../pluginUtils.js";
|
||||||
import { TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
import { TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter.js";
|
||||||
import { resolveMember, zSnowflake } from "../../../utils.js";
|
import { resolveMember, zSnowflake } from "../../../utils.js";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { PermissionsBitField, PermissionsString, Snowflake } from "discord.js";
|
import { PermissionsBitField, PermissionsString, Snowflake } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
import { TemplateSafeValueContainer } from "../../../templateFormatter.js";
|
||||||
import { zSnowflake } from "../../../utils.js";
|
import { zSnowflake } from "../../../utils.js";
|
||||||
import { ActionError } from "../ActionError.js";
|
import { ActionError } from "../ActionError.js";
|
||||||
|
|
|
@ -38,7 +38,7 @@ export async function runEvent(
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ActionError) {
|
if (e instanceof ActionError) {
|
||||||
if (event.trigger.type === "command") {
|
if (event.trigger.type === "command") {
|
||||||
void pluginData.state.common.sendErrorMessage((eventData.msg as Message).channel, e.message);
|
void pluginData.state.common.sendErrorMessage(eventData.msg, e.message);
|
||||||
} else {
|
} else {
|
||||||
// TODO: Where to log action errors from other kinds of triggers?
|
// TODO: Where to log action errors from other kinds of triggers?
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType, pluginUtils } from "knub";
|
import { BasePluginType, pluginUtils } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { zBoundedCharacters, zBoundedRecord } from "../../utils.js";
|
import { zBoundedCharacters, zBoundedRecord } from "../../utils.js";
|
||||||
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
||||||
import { zAddRoleAction } from "./actions/addRoleAction.js";
|
import { zAddRoleAction } from "./actions/addRoleAction.js";
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
export const zGuildAccessMonitorConfig = z.strictObject({});
|
export const zGuildAccessMonitorConfig = z.strictObject({});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { globalPlugin } from "knub";
|
import { globalPlugin } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { Configs } from "../../data/Configs.js";
|
import { Configs } from "../../data/Configs.js";
|
||||||
import { reloadChangedGuilds } from "./functions/reloadChangedGuilds.js";
|
import { reloadChangedGuilds } from "./functions/reloadChangedGuilds.js";
|
||||||
import { GuildConfigReloaderPluginType } from "./types.js";
|
import { GuildConfigReloaderPluginType } from "./types.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { Configs } from "../../data/Configs.js";
|
import { Configs } from "../../data/Configs.js";
|
||||||
import Timeout = NodeJS.Timeout;
|
import Timeout = NodeJS.Timeout;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Guild } from "discord.js";
|
import { Guild } from "discord.js";
|
||||||
import { guildPlugin, guildPluginEventListener } from "knub";
|
import { guildPlugin, guildPluginEventListener } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { AllowedGuilds } from "../../data/AllowedGuilds.js";
|
import { AllowedGuilds } from "../../data/AllowedGuilds.js";
|
||||||
import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments.js";
|
import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments.js";
|
||||||
import { MINUTES } from "../../utils.js";
|
import { MINUTES } from "../../utils.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
export const zGuildInfoSaverConfig = z.strictObject({});
|
export const zGuildInfoSaverConfig = z.strictObject({});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { guildPlugin } from "knub";
|
import { guildPlugin } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { GuildMemberCache } from "../../data/GuildMemberCache.js";
|
import { GuildMemberCache } from "../../data/GuildMemberCache.js";
|
||||||
import { makePublicFn } from "../../pluginUtils.js";
|
import { makePublicFn } from "../../pluginUtils.js";
|
||||||
import { SECONDS } from "../../utils.js";
|
import { SECONDS } from "../../utils.js";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { GuildMemberCache } from "../../data/GuildMemberCache.js";
|
import { GuildMemberCache } from "../../data/GuildMemberCache.js";
|
||||||
|
|
||||||
export const zGuildMemberCacheConfig = z.strictObject({});
|
export const zGuildMemberCacheConfig = z.strictObject({});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { PluginOptions, guildPlugin } from "knub";
|
import { PluginOptions, guildPlugin } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { Queue } from "../../Queue.js";
|
import { Queue } from "../../Queue.js";
|
||||||
import { Webhooks } from "../../data/Webhooks.js";
|
import { Webhooks } from "../../data/Webhooks.js";
|
||||||
import { makePublicFn } from "../../pluginUtils.js";
|
import { makePublicFn } from "../../pluginUtils.js";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { WebhookClient } from "discord.js";
|
import { WebhookClient } from "discord.js";
|
||||||
import { BasePluginType } from "knub";
|
import { BasePluginType } from "knub";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { Queue } from "../../Queue.js";
|
import { Queue } from "../../Queue.js";
|
||||||
import { Webhooks } from "../../data/Webhooks.js";
|
import { Webhooks } from "../../data/Webhooks.js";
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const ListFollowCmd = locateUserCmd({
|
||||||
permission: "can_alert",
|
permission: "can_alert",
|
||||||
|
|
||||||
async run({ message: msg, pluginData }) {
|
async run({ message: msg, pluginData }) {
|
||||||
const alerts = await pluginData.state.alerts.getAlertsByRequestorId(msg.member.id);
|
const alerts = await pluginData.state.alerts.getAlertsByRequestorId(msg.author.id);
|
||||||
if (alerts.length === 0) {
|
if (alerts.length === 0) {
|
||||||
void pluginData.state.common.sendErrorMessage(msg, "You have no active alerts!");
|
void pluginData.state.common.sendErrorMessage(msg, "You have no active alerts!");
|
||||||
return;
|
return;
|
||||||
|
@ -41,7 +41,7 @@ export const DeleteFollowCmd = locateUserCmd({
|
||||||
},
|
},
|
||||||
|
|
||||||
async run({ message: msg, args, pluginData }) {
|
async run({ message: msg, args, pluginData }) {
|
||||||
const alerts = await pluginData.state.alerts.getAlertsByRequestorId(msg.member.id);
|
const alerts = await pluginData.state.alerts.getAlertsByRequestorId(msg.author.id);
|
||||||
alerts.sort(sorter("expires_at"));
|
alerts.sort(sorter("expires_at"));
|
||||||
|
|
||||||
if (args.num > alerts.length || args.num <= 0) {
|
if (args.num > alerts.length || args.num <= 0) {
|
||||||
|
|
|
@ -13,6 +13,6 @@ export const WhereCmd = locateUserCmd({
|
||||||
},
|
},
|
||||||
|
|
||||||
async run({ message: msg, args, pluginData }) {
|
async run({ message: msg, args, pluginData }) {
|
||||||
sendWhere(pluginData, args.member, msg.channel, `<@${msg.member.id}> | `);
|
sendWhere(pluginData, args.member, msg.channel, `<@${msg.author.id}> | `);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand, pluginUtils } from "knub";
|
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand, pluginUtils } from "knub";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { GuildVCAlerts } from "../../data/GuildVCAlerts.js";
|
import { GuildVCAlerts } from "../../data/GuildVCAlerts.js";
|
||||||
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
import { CommonPlugin } from "../Common/CommonPlugin.js";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { CooldownManager, PluginOptions, guildPlugin } from "knub";
|
import { CooldownManager, PluginOptions, guildPlugin } from "knub";
|
||||||
import DefaultLogMessages from "../../data/DefaultLogMessages.json" assert { type: "json" };
|
import DefaultLogMessages from "../../data/DefaultLogMessages.json" with { type: "json" };
|
||||||
import { GuildArchives } from "../../data/GuildArchives.js";
|
import { GuildArchives } from "../../data/GuildArchives.js";
|
||||||
import { GuildCases } from "../../data/GuildCases.js";
|
import { GuildCases } from "../../data/GuildCases.js";
|
||||||
import { GuildLogs } from "../../data/GuildLogs.js";
|
import { GuildLogs } from "../../data/GuildLogs.js";
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue