3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-16 14:11:50 +00:00

half the number of errors

This commit is contained in:
almeidx 2023-03-11 19:31:36 +00:00
parent 7c5e6eb91f
commit 1dca8c4447
No known key found for this signature in database
GPG key ID: B1F4887CEBE2EDB1
261 changed files with 760 additions and 1023 deletions

View file

@ -13,8 +13,7 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"deep-diff": "^1.0.2", "deep-diff": "^1.0.2",
"discord-api-types": "^0.33.1", "discord.js": "14.7.2-dev.1678536262-1b29099.0",
"discord.js": "^14.7.1",
"dotenv": "^4.0.0", "dotenv": "^4.0.0",
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"erlpack": "github:discord/erlpack", "erlpack": "github:discord/erlpack",
@ -53,7 +52,7 @@
"tsconfig-paths": "^3.9.0", "tsconfig-paths": "^3.9.0",
"twemoji": "^12.1.4", "twemoji": "^12.1.4",
"typeorm": "^0.2.31", "typeorm": "^0.2.31",
"typescript": "4.9", "typescript": "~4.9.5",
"utf-8-validate": "^5.0.5", "utf-8-validate": "^5.0.5",
"uuid": "^3.3.2", "uuid": "^3.3.2",
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build", "yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
@ -158,6 +157,22 @@
"node": ">=16.9.0" "node": ">=16.9.0"
} }
}, },
"node_modules/@discordjs/formatters": {
"version": "0.1.1-dev.1678536268-1b29099.0",
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.1.1-dev.1678536268-1b29099.0.tgz",
"integrity": "sha512-cMjsbJPW23HolJdx6zefhtc12qfHO7AY10miC3pSMB47dnvO4w8yJwBy6N7Y8pKpQzf5GNqOrJ87Z16CTeWHjw==",
"dependencies": {
"discord-api-types": "^0.37.35"
},
"engines": {
"node": ">=16.9.0"
}
},
"node_modules/@discordjs/formatters/node_modules/discord-api-types": {
"version": "0.37.35",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.35.tgz",
"integrity": "sha512-iyKZ/82k7FX3lcmHiAvvWu5TmyfVo78RtghBV/YsehK6CID83k5SI03DKKopBcln+TiEIYw5MGgq7SJXSpNzMg=="
},
"node_modules/@discordjs/rest": { "node_modules/@discordjs/rest": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz",
@ -478,8 +493,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.3", "version": "8.5.4",
"license": "MIT", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==",
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
@ -1752,28 +1768,24 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/discord-api-types": {
"version": "0.33.4",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.4.tgz",
"integrity": "sha512-Y6RMvXsHKiBgQhm/q5MgRieXc4Tzh5p/JuDyqreI48lmy+AQfO+g9Xhz0tuGBaN1FtsrLT7mD+lbFONPo5vdwA=="
},
"node_modules/discord.js": { "node_modules/discord.js": {
"version": "14.7.1", "version": "14.7.2-dev.1678536262-1b29099.0",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.2-dev.1678536262-1b29099.0.tgz",
"integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", "integrity": "sha512-Z2D0Ae4yxeVvaPa9ot88fPMuzADsKqZuqCLFKJ91XGjY5AL7uZxUCrnNNMUoi4JfSrL4GIG6eA7ddX/lORoCmQ==",
"dependencies": { "dependencies": {
"@discordjs/builders": "^1.4.0", "@discordjs/builders": "^1.4.0",
"@discordjs/collection": "^1.3.0", "@discordjs/collection": "^1.3.0",
"@discordjs/rest": "^1.4.0", "@discordjs/formatters": "^0.1.0",
"@discordjs/rest": "^1.5.0",
"@discordjs/util": "^0.1.0", "@discordjs/util": "^0.1.0",
"@sapphire/snowflake": "^3.2.2", "@sapphire/snowflake": "^3.4.0",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.4",
"discord-api-types": "^0.37.20", "discord-api-types": "^0.37.35",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"lodash.snakecase": "^4.1.1", "lodash.snakecase": "^4.1.1",
"tslib": "^2.4.1", "tslib": "^2.5.0",
"undici": "^5.13.0", "undici": "^5.20.0",
"ws": "^8.11.0" "ws": "^8.12.1"
}, },
"engines": { "engines": {
"node": ">=16.9.0" "node": ">=16.9.0"
@ -5523,6 +5535,21 @@
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz",
"integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==" "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg=="
}, },
"@discordjs/formatters": {
"version": "0.1.1-dev.1678536268-1b29099.0",
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.1.1-dev.1678536268-1b29099.0.tgz",
"integrity": "sha512-cMjsbJPW23HolJdx6zefhtc12qfHO7AY10miC3pSMB47dnvO4w8yJwBy6N7Y8pKpQzf5GNqOrJ87Z16CTeWHjw==",
"requires": {
"discord-api-types": "^0.37.35"
},
"dependencies": {
"discord-api-types": {
"version": "0.37.35",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.35.tgz",
"integrity": "sha512-iyKZ/82k7FX3lcmHiAvvWu5TmyfVo78RtghBV/YsehK6CID83k5SI03DKKopBcln+TiEIYw5MGgq7SJXSpNzMg=="
}
}
},
"@discordjs/rest": { "@discordjs/rest": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz",
@ -5779,7 +5806,9 @@
"dev": true "dev": true
}, },
"@types/ws": { "@types/ws": {
"version": "8.5.3", "version": "8.5.4",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==",
"requires": { "requires": {
"@types/node": "*" "@types/node": "*"
} }
@ -6599,28 +6628,24 @@
"path-type": "^4.0.0" "path-type": "^4.0.0"
} }
}, },
"discord-api-types": {
"version": "0.33.4",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.4.tgz",
"integrity": "sha512-Y6RMvXsHKiBgQhm/q5MgRieXc4Tzh5p/JuDyqreI48lmy+AQfO+g9Xhz0tuGBaN1FtsrLT7mD+lbFONPo5vdwA=="
},
"discord.js": { "discord.js": {
"version": "14.7.1", "version": "14.7.2-dev.1678536262-1b29099.0",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.2-dev.1678536262-1b29099.0.tgz",
"integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", "integrity": "sha512-Z2D0Ae4yxeVvaPa9ot88fPMuzADsKqZuqCLFKJ91XGjY5AL7uZxUCrnNNMUoi4JfSrL4GIG6eA7ddX/lORoCmQ==",
"requires": { "requires": {
"@discordjs/builders": "^1.4.0", "@discordjs/builders": "^1.4.0",
"@discordjs/collection": "^1.3.0", "@discordjs/collection": "^1.3.0",
"@discordjs/rest": "^1.4.0", "@discordjs/formatters": "0.1.1-dev.1678536268-1b29099.0",
"@discordjs/rest": "^1.5.0",
"@discordjs/util": "^0.1.0", "@discordjs/util": "^0.1.0",
"@sapphire/snowflake": "^3.2.2", "@sapphire/snowflake": "^3.4.0",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.4",
"discord-api-types": "^0.37.20", "discord-api-types": "^0.37.35",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"lodash.snakecase": "^4.1.1", "lodash.snakecase": "^4.1.1",
"tslib": "^2.4.1", "tslib": "^2.5.0",
"undici": "^5.13.0", "undici": "^5.20.0",
"ws": "^8.11.0" "ws": "^8.12.1"
}, },
"dependencies": { "dependencies": {
"discord-api-types": { "discord-api-types": {
@ -7214,7 +7239,7 @@
"integrity": "sha512-tT27Qr8qpge+EWonrMyw54mZ67/1WP3oKF7QgTdK6cYArTdERuYxF9X7ngd9JXcVeW9/WYz/62jq42/w9lDzIA==", "integrity": "sha512-tT27Qr8qpge+EWonrMyw54mZ67/1WP3oKF7QgTdK6cYArTdERuYxF9X7ngd9JXcVeW9/WYz/62jq42/w9lDzIA==",
"requires": { "requires": {
"discord-api-types": "^0.37.10", "discord-api-types": "^0.37.10",
"discord.js": "^14", "discord.js": "14.7.2-dev.1678536262-1b29099.0",
"knub-command-manager": "^9.1.0", "knub-command-manager": "^9.1.0",
"ts-essentials": "^9", "ts-essentials": "^9",
"zod": "^3.19.1" "zod": "^3.19.1"

View file

@ -28,8 +28,7 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"deep-diff": "^1.0.2", "deep-diff": "^1.0.2",
"discord-api-types": "^0.33.1", "discord.js": "14.7.2-dev.1678536262-1b29099.0",
"discord.js": "^14.7.1",
"dotenv": "^4.0.0", "dotenv": "^4.0.0",
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"erlpack": "github:discord/erlpack", "erlpack": "github:discord/erlpack",
@ -68,7 +67,7 @@
"tsconfig-paths": "^3.9.0", "tsconfig-paths": "^3.9.0",
"twemoji": "^12.1.4", "twemoji": "^12.1.4",
"typeorm": "^0.2.31", "typeorm": "^0.2.31",
"typescript": "4.9", "typescript": "~4.9.5",
"utf-8-validate": "^5.0.5", "utf-8-validate": "^5.0.5",
"uuid": "^3.3.2", "uuid": "^3.3.2",
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build", "yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
@ -103,5 +102,11 @@
"require": [ "require": [
"./register-tsconfig-paths.js" "./register-tsconfig-paths.js"
] ]
},
"overrides": {
"@discordjs/formatters": "0.1.1-dev.1678536268-1b29099.0",
"knub": {
"discord.js": "14.7.2-dev.1678536262-1b29099.0"
}
} }
} }

View file

@ -5,7 +5,6 @@ import { validateGuildConfig } from "../../configValidator";
import { AllowedGuilds } from "../../data/AllowedGuilds"; import { AllowedGuilds } from "../../data/AllowedGuilds";
import { ApiPermissionAssignments, ApiPermissionTypes } from "../../data/ApiPermissionAssignments"; import { ApiPermissionAssignments, ApiPermissionTypes } from "../../data/ApiPermissionAssignments";
import { Configs } from "../../data/Configs"; import { Configs } from "../../data/Configs";
import { apiTokenAuthHandlers } from "../auth";
import { hasGuildPermission, requireGuildPermission } from "../permissions"; import { hasGuildPermission, requireGuildPermission } from "../permissions";
import { clientError, ok, serverError, unauthorized } from "../responses"; import { clientError, ok, serverError, unauthorized } from "../responses";
import { loadYamlSafely } from "../../utils/loadYamlSafely"; import { loadYamlSafely } from "../../utils/loadYamlSafely";
@ -15,8 +14,6 @@ import moment from "moment-timezone";
import { ApiAuditLog } from "../../data/ApiAuditLog"; import { ApiAuditLog } from "../../data/ApiAuditLog";
import { AuditLogEventTypes } from "../../data/apiAuditLogTypes"; import { AuditLogEventTypes } from "../../data/apiAuditLogTypes";
import { Queue } from "../../Queue"; import { Queue } from "../../Queue";
import { GuildCases } from "../../data/GuildCases";
import { z } from "zod";
const apiPermissionAssignments = new ApiPermissionAssignments(); const apiPermissionAssignments = new ApiPermissionAssignments();
const auditLog = new ApiAuditLog(); const auditLog = new ApiAuditLog();

View file

@ -4,7 +4,6 @@ import { BaseRepository } from "./BaseRepository";
import { AllowedGuild } from "./entities/AllowedGuild"; import { AllowedGuild } from "./entities/AllowedGuild";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { DBDateFormat } from "../utils"; import { DBDateFormat } from "../utils";
import { env } from "../env";
export class AllowedGuilds extends BaseRepository { export class AllowedGuilds extends BaseRepository {
private allowedGuilds: Repository<AllowedGuild>; private allowedGuilds: Repository<AllowedGuild>;

View file

@ -1,7 +1,6 @@
import { BaseRepository } from "./BaseRepository"; import { BaseRepository } from "./BaseRepository";
import { getRepository, Repository } from "typeorm/index"; import { getRepository, Repository } from "typeorm/index";
import { ApiAuditLogEntry } from "./entities/ApiAuditLogEntry"; import { ApiAuditLogEntry } from "./entities/ApiAuditLogEntry";
import { ApiLogin } from "./entities/ApiLogin";
import { AuditLogEventData, AuditLogEventType } from "./apiAuditLogTypes"; import { AuditLogEventData, AuditLogEventType } from "./apiAuditLogTypes";
export class ApiAuditLog extends BaseRepository { export class ApiAuditLog extends BaseRepository {

View file

@ -1,4 +1,4 @@
import { Guild, Snowflake, User } from "discord.js"; import { Guild, Snowflake } from "discord.js";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { isDefaultSticker } from "src/utils/isDefaultSticker"; import { isDefaultSticker } from "src/utils/isDefaultSticker";
import { getRepository, Repository } from "typeorm"; import { getRepository, Repository } from "typeorm";
@ -6,11 +6,7 @@ import { renderTemplate, TemplateSafeValueContainer } from "../templateFormatter
import { trimLines } from "../utils"; import { trimLines } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository"; import { BaseGuildRepository } from "./BaseGuildRepository";
import { ArchiveEntry } from "./entities/ArchiveEntry"; import { ArchiveEntry } from "./entities/ArchiveEntry";
import { import { channelToTemplateSafeChannel, guildToTemplateSafeGuild } from "../utils/templateSafeObjects";
channelToTemplateSafeChannel,
guildToTemplateSafeGuild,
userToTemplateSafeUser,
} from "../utils/templateSafeObjects";
import { SavedMessage } from "./entities/SavedMessage"; import { SavedMessage } from "./entities/SavedMessage";
import { decrypt, encrypt } from "../utils/crypt"; import { decrypt, encrypt } from "../utils/crypt";

View file

@ -4,7 +4,6 @@ import { CaseTypes } from "./CaseTypes";
import { connection } from "./db"; import { connection } from "./db";
import { Case } from "./entities/Case"; import { Case } from "./entities/Case";
import { CaseNote } from "./entities/CaseNote"; import { CaseNote } from "./entities/CaseNote";
import moment from "moment-timezone";
import { chunkArray } from "../utils"; import { chunkArray } from "../utils";
import { Queue } from "../Queue"; import { Queue } from "../Queue";

View file

@ -1,11 +1,5 @@
import { getRepository, Repository } from "typeorm"; import { getRepository, Repository } from "typeorm";
import { Reminder } from "./entities/Reminder";
import { BaseRepository } from "./BaseRepository";
import moment from "moment-timezone";
import { DBDateFormat } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository"; import { BaseGuildRepository } from "./BaseGuildRepository";
import { RoleQueueItem } from "./entities/RoleQueueItem";
import { connection } from "./db";
import { RoleButtonsItem } from "./entities/RoleButtonsItem"; import { RoleButtonsItem } from "./entities/RoleButtonsItem";
export class GuildRoleButtons extends BaseGuildRepository { export class GuildRoleButtons extends BaseGuildRepository {

View file

@ -1,8 +1,4 @@
import { getRepository, Repository } from "typeorm"; import { getRepository, Repository } from "typeorm";
import { Reminder } from "./entities/Reminder";
import { BaseRepository } from "./BaseRepository";
import moment from "moment-timezone";
import { DBDateFormat } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository"; import { BaseGuildRepository } from "./BaseGuildRepository";
import { RoleQueueItem } from "./entities/RoleQueueItem"; import { RoleQueueItem } from "./entities/RoleQueueItem";
import { connection } from "./db"; import { connection } from "./db";

View file

@ -1,13 +1,11 @@
import { GuildChannel, Message } from "discord.js"; import { GuildChannel, Message } from "discord.js";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm"; import { getRepository, Repository } from "typeorm";
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity";
import { QueuedEventEmitter } from "../QueuedEventEmitter"; import { QueuedEventEmitter } from "../QueuedEventEmitter";
import { BaseGuildRepository } from "./BaseGuildRepository"; import { BaseGuildRepository } from "./BaseGuildRepository";
import { ISavedMessageData, SavedMessage } from "./entities/SavedMessage"; import { ISavedMessageData, SavedMessage } from "./entities/SavedMessage";
import { buildEntity } from "./buildEntity"; import { buildEntity } from "./buildEntity";
import { noop } from "../utils"; import { noop } from "../utils";
import { decrypt } from "../utils/crypt";
import { decryptJson, encryptJson } from "../utils/cryptHelpers"; import { decryptJson, encryptJson } from "../utils/cryptHelpers";
import { asyncMap } from "../utils/async"; import { asyncMap } from "../utils/async";

View file

@ -1,5 +1,5 @@
import moment from "moment-timezone"; import moment from "moment-timezone";
import { Brackets, getRepository, Repository } from "typeorm"; import { getRepository, Repository } from "typeorm";
import { Mute } from "./entities/Mute"; import { Mute } from "./entities/Mute";
import { DAYS, DBDateFormat } from "../utils"; import { DAYS, DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository"; import { BaseRepository } from "./BaseRepository";

View file

@ -1,5 +1,4 @@
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; import { Column, Entity, PrimaryColumn } from "typeorm";
import { ApiUserInfo } from "./ApiUserInfo";
import { AuditLogEventData, AuditLogEventType } from "../apiAuditLogTypes"; import { AuditLogEventData, AuditLogEventType } from "../apiAuditLogTypes";
@Entity("api_audit_log") @Entity("api_audit_log")

View file

@ -2,7 +2,7 @@ import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
export const TRIGGER_COMPARISON_OPS = ["=", "!=", ">", "<", ">=", "<="] as const; export const TRIGGER_COMPARISON_OPS = ["=", "!=", ">", "<", ">=", "<="] as const;
export type TriggerComparisonOp = typeof TRIGGER_COMPARISON_OPS[number]; export type TriggerComparisonOp = (typeof TRIGGER_COMPARISON_OPS)[number];
const REVERSE_OPS: Record<TriggerComparisonOp, TriggerComparisonOp> = { const REVERSE_OPS: Record<TriggerComparisonOp, TriggerComparisonOp> = {
"=": "!=", "=": "!=",

View file

@ -1,4 +1,4 @@
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity("reminders") @Entity("reminders")
export class Reminder { export class Reminder {

View file

@ -1,5 +1,5 @@
import { Attachment } from "discord.js"; import { Attachment } from "discord.js";
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import { StrictMessageContent } from "../../utils"; import { StrictMessageContent } from "../../utils";
@Entity("scheduled_posts") @Entity("scheduled_posts")

View file

@ -1,4 +1,4 @@
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity("vc_alerts") @Entity("vc_alerts")
export class VCAlert { export class VCAlert {

View file

@ -2,7 +2,6 @@
import { lazyMemoize, MINUTES } from "../../utils"; import { lazyMemoize, MINUTES } from "../../utils";
import { Archives } from "../Archives"; import { Archives } from "../Archives";
import moment from "moment-timezone";
const LOOP_INTERVAL = 15 * MINUTES; const LOOP_INTERVAL = 15 * MINUTES;
const getArchivesRepository = lazyMemoize(() => new Archives()); const getArchivesRepository = lazyMemoize(() => new Archives());

View file

@ -1,6 +1,6 @@
// tslint:disable:no-console // tslint:disable:no-console
import { lazyMemoize, memoize, MINUTES } from "../../utils"; import { lazyMemoize, MINUTES } from "../../utils";
import { Mutes } from "../Mutes"; import { Mutes } from "../Mutes";
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
import moment from "moment-timezone"; import moment from "moment-timezone";

View file

@ -1,6 +1,6 @@
// tslint:disable:no-console // tslint:disable:no-console
import { HOURS, MINUTES } from "../../utils"; import { MINUTES } from "../../utils";
import { import {
deleteStalePhishermanCacheEntries, deleteStalePhishermanCacheEntries,
deleteStalePhishermanKeyCacheEntries, deleteStalePhishermanKeyCacheEntries,

View file

@ -1,4 +1,16 @@
import { Client, Constants, Intents, Options, TextChannel, ThreadChannel } from "discord.js"; import {
Client,
Events,
GatewayIntentBits,
GuildTextBasedChannel,
Message,
Options,
Partials,
RESTEvents,
TextBasedChannel,
TextChannel,
ThreadChannel,
} from "discord.js";
import { Knub, PluginError } from "knub"; import { Knub, PluginError } from "knub";
import { PluginLoadError } from "knub/dist/plugins/PluginLoadError"; import { PluginLoadError } from "knub/dist/plugins/PluginLoadError";
// Always use UTC internally // Always use UTC internally
@ -14,13 +26,11 @@ import { logger } from "./logger";
import { baseGuildPlugins, globalPlugins, guildPlugins } from "./plugins/availablePlugins"; import { baseGuildPlugins, globalPlugins, guildPlugins } from "./plugins/availablePlugins";
import { RecoverablePluginError } from "./RecoverablePluginError"; import { RecoverablePluginError } from "./RecoverablePluginError";
import { SimpleError } from "./SimpleError"; import { SimpleError } from "./SimpleError";
import { ZeppelinGlobalConfig, ZeppelinGuildConfig } from "./types";
import { startUptimeCounter } from "./uptime"; import { startUptimeCounter } from "./uptime";
import { errorMessage, isDiscordAPIError, isDiscordHTTPError, MINUTES, SECONDS, sleep, successMessage } from "./utils"; import { errorMessage, isDiscordAPIError, isDiscordHTTPError, MINUTES, SECONDS, sleep, successMessage } from "./utils";
import { loadYamlSafely } from "./utils/loadYamlSafely"; import { loadYamlSafely } from "./utils/loadYamlSafely";
import { DecayingCounter } from "./utils/DecayingCounter"; import { DecayingCounter } from "./utils/DecayingCounter";
import { PluginNotLoadedError } from "knub/dist/plugins/PluginNotLoadedError"; import { PluginNotLoadedError } from "knub/dist/plugins/PluginNotLoadedError";
import { logRestCall } from "./restCallStats";
import { logRateLimit } from "./rateLimitStats"; import { logRateLimit } from "./rateLimitStats";
import { runExpiringMutesLoop } from "./data/loops/expiringMutesLoop"; import { runExpiringMutesLoop } from "./data/loops/expiringMutesLoop";
import { runUpcomingRemindersLoop } from "./data/loops/upcomingRemindersLoop"; import { runUpcomingRemindersLoop } from "./data/loops/upcomingRemindersLoop";
@ -37,6 +47,19 @@ import { hasPhishermanMasterAPIKey } from "./data/Phisherman";
import { consumeQueryStats } from "./data/queryLogger"; import { consumeQueryStats } from "./data/queryLogger";
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { env } from "./env"; import { env } from "./env";
import { ZeppelinGlobalConfig, ZeppelinGuildConfig } from "./types";
// TODO: Remove this once fixed on upstream
declare module "knub/dist/helpers" {
export function waitForReply(
client: Client,
channel: GuildTextBasedChannel,
restrictToUserId?: string,
timeout?: number,
): Promise<Message | null>;
export function createChunkedMessage(channel: TextBasedChannel, messageText: string): Promise<Message[]>;
}
// Error handling // Error handling
let recentPluginErrors = 0; let recentPluginErrors = 0;
@ -188,17 +211,19 @@ setInterval(() => {
logger.info("Connecting to database"); logger.info("Connecting to database");
connect().then(async () => { connect().then(async () => {
const client = new Client({ const client = new Client({
partials: ["USER", "CHANNEL", "GUILD_MEMBER", "MESSAGE", "REACTION"], partials: [Partials.User, Partials.Channel, Partials.GuildMember, Partials.Message, Partials.Reaction],
makeCache: Options.cacheWithLimits({ makeCache: Options.cacheWithLimits({
...Options.defaultMakeCacheSettings, ...Options.DefaultMakeCacheSettings,
MessageManager: 1, MessageManager: 1,
// GuildMemberManager: 15000, // GuildMemberManager: 15000,
GuildInviteManager: 0, GuildInviteManager: 0,
}), }),
restGlobalRateLimit: 50, rest: {
// restTimeOffset: 1000, // globalRequestsPerSecond: 50,
// offset: 1000,
},
// Disable mentions by default // Disable mentions by default
allowedMentions: { allowedMentions: {
@ -209,25 +234,25 @@ connect().then(async () => {
}, },
intents: [ intents: [
// Privileged // Privileged
Intents.FLAGS.GUILD_MEMBERS, GatewayIntentBits.GuildMembers,
// Intents.FLAGS.GUILD_PRESENCES, // GatewayIntentBits.GuildPresences,
Intents.FLAGS.GUILD_MESSAGE_TYPING,
// Regular // Regular
Intents.FLAGS.DIRECT_MESSAGES, GatewayIntentBits.GuildMessageTyping,
Intents.FLAGS.GUILD_BANS, GatewayIntentBits.DirectMessages,
Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS, GatewayIntentBits.GuildModeration,
Intents.FLAGS.GUILD_INVITES, GatewayIntentBits.GuildEmojisAndStickers,
Intents.FLAGS.GUILD_MESSAGE_REACTIONS, GatewayIntentBits.GuildInvites,
Intents.FLAGS.GUILD_MESSAGES, GatewayIntentBits.GuildMessageReactions,
Intents.FLAGS.GUILDS, GatewayIntentBits.GuildMessages,
Intents.FLAGS.GUILD_VOICE_STATES, GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
], ],
}); });
// FIXME: TS doesn't see Client as a child of EventEmitter for some reason // FIXME: TS doesn't see Client as a child of EventEmitter for some reason
(client as unknown as EventEmitter).setMaxListeners(200); (client as unknown as EventEmitter).setMaxListeners(200);
client.on(Constants.Events.RATE_LIMIT, (data) => { client.rest.on(RESTEvents.RateLimited, (data) => {
// tslint:disable-next-line:no-console // tslint:disable-next-line:no-console
// console.log(`[DEBUG] [RATE_LIMIT] ${JSON.stringify(data)}`); // console.log(`[DEBUG] [RATE_LIMIT] ${JSON.stringify(data)}`);
}); });
@ -235,7 +260,7 @@ connect().then(async () => {
const safe429DecayInterval = 5 * SECONDS; const safe429DecayInterval = 5 * SECONDS;
const safe429MaxCount = 5; const safe429MaxCount = 5;
const safe429Counter = new DecayingCounter(safe429DecayInterval); const safe429Counter = new DecayingCounter(safe429DecayInterval);
client.on(Constants.Events.DEBUG, (errorText) => { client.on(Events.Debug, (errorText) => {
if (!errorText.includes("429")) { if (!errorText.includes("429")) {
return; return;
} }
@ -346,7 +371,7 @@ connect().then(async () => {
startUptimeCounter(); startUptimeCounter();
}); });
client.on(Constants.Events.RATE_LIMIT, (data) => { client.rest.on(RESTEvents.RateLimited, (data) => {
logRateLimit(data); logRateLimit(data);
}); });

View file

@ -2,17 +2,7 @@
* @file Utility functions that are plugin-instance-specific (i.e. use PluginData) * @file Utility functions that are plugin-instance-specific (i.e. use PluginData)
*/ */
import { import { GuildMember, Message, MessageCreateOptions, MessageMentionOptions, TextBasedChannel } from "discord.js";
ChannelType,
GuildMember,
GuildTextBasedChannel,
Message,
MessageCreateOptions,
MessageMentionOptions,
MessagePayload,
TextBasedChannel,
TextChannel,
} from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { CommandContext, configUtils, ConfigValidationError, GuildPluginData, helpers, PluginOptions } from "knub"; import { CommandContext, configUtils, ConfigValidationError, GuildPluginData, helpers, PluginOptions } from "knub";
import { PluginOverrideCriteria } from "knub/dist/config/configTypes"; import { PluginOverrideCriteria } from "knub/dist/config/configTypes";
@ -198,7 +188,7 @@ export function getPluginConfigPreprocessor(
export async function sendSuccessMessage( export async function sendSuccessMessage(
pluginData: AnyPluginData<any>, pluginData: AnyPluginData<any>,
channel: GuildTextBasedChannel, channel: TextBasedChannel,
body: string, body: string,
allowedMentions?: MessageMentionOptions, allowedMentions?: MessageMentionOptions,
): Promise<Message | undefined> { ): Promise<Message | undefined> {
@ -211,7 +201,7 @@ export async function sendSuccessMessage(
return channel return channel
.send({ ...content }) // Force line break .send({ ...content }) // Force line break
.catch((err) => { .catch((err) => {
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id; const channelInfo = "guild" in channel ? `${channel.id} (${channel.guild.id})` : channel.id;
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`); logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
return undefined; return undefined;
}); });
@ -232,7 +222,7 @@ export async function sendErrorMessage(
return channel return channel
.send({ ...content }) // Force line break .send({ ...content }) // Force line break
.catch((err) => { .catch((err) => {
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id; const channelInfo = "guild" in channel ? `${channel.id} (${channel.guild.id})` : channel.id;
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`); logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
return undefined; return undefined;
}); });

View file

@ -1,7 +1,6 @@
import { PermissionsBitField, Snowflake, TextChannel } from "discord.js"; import { PermissionsBitField, Snowflake } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { logger } from "../../../logger"; import { logger } from "../../../logger";
import { resolveUser, verboseChannelMention } from "../../../utils"; import { resolveUser, verboseChannelMention } from "../../../utils";
@ -47,7 +46,7 @@ export async function deleteNextItem(pluginData: GuildPluginData<AutoDeletePlugi
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin); const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id); pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
(channel as TextChannel).messages.delete(itemToDelete.message.id as Snowflake).catch((err) => { channel.messages.delete(itemToDelete.message.id as Snowflake).catch((err) => {
if (err.code === 10008) { if (err.code === 10008) {
// "Unknown Message", probably already deleted by automod or another bot, ignore // "Unknown Message", probably already deleted by automod or another bot, ignore
return; return;

View file

@ -1,6 +1,5 @@
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { SavedMessage } from "../../../data/entities/SavedMessage"; import { SavedMessage } from "../../../data/entities/SavedMessage";
import { LogType } from "../../../data/LogType";
import { convertDelayStringToMS, resolveMember } from "../../../utils"; import { convertDelayStringToMS, resolveMember } from "../../../utils";
import { AutoDeletePluginType, MAX_DELAY } from "../types"; import { AutoDeletePluginType, MAX_DELAY } from "../types";
import { addMessageToDeletionQueue } from "./addMessageToDeletionQueue"; import { addMessageToDeletionQueue } from "./addMessageToDeletionQueue";

View file

@ -1,4 +1,4 @@
import { GuildChannel, PermissionsBitField } from "discord.js"; import { PermissionsBitField } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { canUseEmoji, customEmojiRegex, isEmoji } from "../../../utils"; import { canUseEmoji, customEmojiRegex, isEmoji } from "../../../utils";

View file

@ -1,5 +1,4 @@
import { GuildChannel, GuildTextBasedChannel, PermissionsBitField } from "discord.js"; import { GuildTextBasedChannel, PermissionsBitField } from "discord.js";
import { LogType } from "../../../data/LogType";
import { isDiscordAPIError } from "../../../utils"; import { isDiscordAPIError } from "../../../utils";
import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions"; import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions";
import { missingPermissionError } from "../../../utils/missingPermissionError"; import { missingPermissionError } from "../../../utils/missingPermissionError";

View file

@ -1,6 +1,5 @@
import { PermissionsBitField, Snowflake } from "discord.js"; import { PermissionFlagsBits, Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType";
import { nonNullish, unique } from "../../../utils"; import { nonNullish, unique } from "../../../utils";
import { canAssignRole } from "../../../utils/canAssignRole"; import { canAssignRole } from "../../../utils/canAssignRole";
import { getMissingPermissions } from "../../../utils/getMissingPermissions"; import { getMissingPermissions } from "../../../utils/getMissingPermissions";
@ -10,7 +9,7 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
import { ignoreRoleChange } from "../functions/ignoredRoleChanges"; import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
const p = PermissionsBitField.Flags; const p = PermissionFlagsBits;
export const AddRolesAction = automodAction({ export const AddRolesAction = automodAction({
configType: t.array(t.string), configType: t.array(t.string),

View file

@ -1,5 +1,4 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType";
import { CountersPlugin } from "../../Counters/CountersPlugin"; import { CountersPlugin } from "../../Counters/CountersPlugin";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel, ThreadChannel } from "discord.js"; import { Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { erisAllowedMentionsToDjsMentionOptions } from "src/utils/erisAllowedMentionsToDjsMentionOptions"; import { erisAllowedMentionsToDjsMentionOptions } from "src/utils/erisAllowedMentionsToDjsMentionOptions";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
@ -9,9 +9,7 @@ import {
TemplateSafeValueContainer, TemplateSafeValueContainer,
} from "../../../templateFormatter"; } from "../../../templateFormatter";
import { import {
createChunkedMessage,
messageLink, messageLink,
stripObjectToScalars,
tAllowedMentions, tAllowedMentions,
tNormalizedNullOptional, tNormalizedNullOptional,
isTruthy, isTruthy,
@ -21,7 +19,7 @@ import {
} from "../../../utils"; } from "../../../utils";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
import { TemplateSafeUser, userToTemplateSafeUser } from "../../../utils/templateSafeObjects"; import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { messageIsEmpty } from "../../../utils/messageIsEmpty"; import { messageIsEmpty } from "../../../utils/messageIsEmpty";
import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin"; import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin";
@ -96,7 +94,7 @@ export const AlertAction = automodAction({
const chunks = chunkMessageLines(rendered); const chunks = chunkMessageLines(rendered);
for (const chunk of chunks) { for (const chunk of chunks) {
await poster.sendMessage(channel, { await poster.sendMessage(channel, {
content: rendered, content: chunk,
allowedMentions: erisAllowedMentionsToDjsMentionOptions(actionConfig.allowed_mentions), allowedMentions: erisAllowedMentionsToDjsMentionOptions(actionConfig.allowed_mentions),
}); });
} }

View file

@ -1,4 +1,4 @@
import { ThreadChannel } from "discord.js"; import { AnyThreadChannel } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { noop } from "../../../utils"; import { noop } from "../../../utils";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
@ -11,7 +11,7 @@ export const ArchiveThreadAction = automodAction({
const threads = contexts const threads = contexts
.filter((c) => c.message?.channel_id) .filter((c) => c.message?.channel_id)
.map((c) => pluginData.guild.channels.cache.get(c.message!.channel_id)) .map((c) => pluginData.guild.channels.cache.get(c.message!.channel_id))
.filter((c): c is ThreadChannel => c?.isThread() ?? false); .filter((c): c is AnyThreadChannel => c?.isThread() ?? false);
for (const thread of threads) { for (const thread of threads) {
await thread.setArchived().catch(noop); await thread.setArchived().catch(noop);

View file

@ -1,5 +1,4 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType";
import { nonNullish, unique } from "../../../utils"; import { nonNullish, unique } from "../../../utils";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";

View file

@ -1,4 +1,4 @@
import { GuildTextBasedChannel, Snowflake, TextChannel } from "discord.js"; import { GuildTextBasedChannel, Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { noop } from "../../../utils"; import { noop } from "../../../utils";

View file

@ -1,9 +1,7 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType"; import { isTruthy, unique } from "../../../utils";
import { isTruthy, stripObjectToScalars, unique } from "../../../utils";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
export const LogAction = automodAction({ export const LogAction = automodAction({
configType: t.boolean, configType: t.boolean,

View file

@ -1,5 +1,4 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType";
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
import { convertDelayStringToMS, nonNullish, tDelayString, tNullable, unique } from "../../../utils"; import { convertDelayStringToMS, nonNullish, tDelayString, tNullable, unique } from "../../../utils";
import { CaseArgs } from "../../Cases/types"; import { CaseArgs } from "../../Cases/types";

View file

@ -1,6 +1,5 @@
import { PermissionsBitField, Snowflake } from "discord.js"; import { PermissionFlagsBits, Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType";
import { nonNullish, unique } from "../../../utils"; import { nonNullish, unique } from "../../../utils";
import { canAssignRole } from "../../../utils/canAssignRole"; import { canAssignRole } from "../../../utils/canAssignRole";
import { getMissingPermissions } from "../../../utils/getMissingPermissions"; import { getMissingPermissions } from "../../../utils/getMissingPermissions";
@ -10,7 +9,7 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
import { ignoreRoleChange } from "../functions/ignoredRoleChanges"; import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
const p = PermissionsBitField.Flags; const p = PermissionFlagsBits;
export const RemoveRolesAction = automodAction({ export const RemoveRolesAction = automodAction({
configType: t.array(t.string), configType: t.array(t.string),

View file

@ -1,12 +1,4 @@
import { import { GuildTextBasedChannel, MessageCreateOptions, PermissionsBitField, Snowflake, User } from "discord.js";
GuildTextBasedChannel,
MessageOptions,
PermissionsBitField,
Snowflake,
TextChannel,
ThreadChannel,
User,
} from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects"; import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter"; import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
@ -71,7 +63,7 @@ export const ReplyAction = automodAction({
const formatted = const formatted =
typeof actionConfig === "string" typeof actionConfig === "string"
? await renderReplyText(actionConfig) ? await renderReplyText(actionConfig)
: ((await renderRecursively(actionConfig.text, renderReplyText)) as MessageOptions); : ((await renderRecursively(actionConfig.text, renderReplyText)) as MessageCreateOptions);
if (formatted) { if (formatted) {
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as GuildTextBasedChannel; const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as GuildTextBasedChannel;
@ -107,7 +99,7 @@ export const ReplyAction = automodAction({
const messageContent = validateAndParseMessageContent(formatted); const messageContent = validateAndParseMessageContent(formatted);
const messageOpts: MessageOptions = { const messageOpts: MessageCreateOptions = {
...messageContent, ...messageContent,
allowedMentions: { allowedMentions: {
users: [user.id], users: [user.id],

View file

@ -1,5 +1,4 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType";
import { CountersPlugin } from "../../Counters/CountersPlugin"; import { CountersPlugin } from "../../Counters/CountersPlugin";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";

View file

@ -1,6 +1,5 @@
import { ChannelType, GuildTextBasedChannel, Snowflake, TextChannel } from "discord.js"; import { ChannelType, GuildTextBasedChannel, Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { LogType } from "../../../data/LogType";
import { convertDelayStringToMS, isDiscordAPIError, tDelayString, tNullable } from "../../../utils"; import { convertDelayStringToMS, isDiscordAPIError, tDelayString, tNullable } from "../../../utils";
import { automodAction } from "../helpers"; import { automodAction } from "../helpers";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";
@ -42,9 +41,7 @@ export const SetSlowmodeAction = automodAction({
try { try {
for (const chan of channelsToSlowmode) { for (const chan of channelsToSlowmode) {
await chan.edit({ await chan.setRateLimitPerUser(slowmodeSeconds);
rateLimitPerUser: slowmodeSeconds,
});
} }
} catch (e) { } catch (e) {
// Check for invalid form body -> indicates duration was too large // Check for invalid form body -> indicates duration was too large

View file

@ -1,5 +1,4 @@
import { GuildFeature, ThreadAutoArchiveDuration } from "discord-api-types/v9"; import { ChannelType, GuildFeature, ThreadAutoArchiveDuration } from "discord.js";
import { BaseGuildTextChannel, ChannelType, GuildTextBasedChannel, TextChannel } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter"; import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
import { convertDelayStringToMS, MINUTES, noop, tDelayString, tNullable } from "../../../utils"; import { convertDelayStringToMS, MINUTES, noop, tDelayString, tNullable } from "../../../utils";
@ -35,8 +34,7 @@ export const StartThreadAction = automodAction({
// check against max threads per channel // check against max threads per channel
if (actionConfig.limit_per_channel && actionConfig.limit_per_channel > 0) { if (actionConfig.limit_per_channel && actionConfig.limit_per_channel > 0) {
const threadCount = channel.threads.cache.filter( const threadCount = channel.threads.cache.filter(
(tr) => (tr) => tr.ownerId === pluginData.client.user!.id && !tr.archived && tr.parentId === channel.id,
tr.ownerId === pluginData.client.user!.id && !tr.deleted && !tr.archived && tr.parentId === channel.id,
).size; ).size;
if (threadCount >= actionConfig.limit_per_channel) return false; if (threadCount >= actionConfig.limit_per_channel) return false;
} }
@ -52,7 +50,9 @@ export const StartThreadAction = automodAction({
: ThreadAutoArchiveDuration.OneHour; : ThreadAutoArchiveDuration.OneHour;
for (const threadContext of threads) { for (const threadContext of threads) {
const channel = pluginData.guild.channels.cache.get(threadContext.message!.channel_id) as BaseGuildTextChannel; const channel = pluginData.guild.channels.cache.get(threadContext.message!.channel_id);
if (!channel || !("threads" in channel)) continue;
const renderThreadName = async (str: string) => const renderThreadName = async (str: string) =>
renderTemplate( renderTemplate(
str, str,
@ -62,7 +62,7 @@ export const StartThreadAction = automodAction({
}), }),
); );
const threadName = await renderThreadName(actionConfig.name ?? "{user.tag}s thread"); const threadName = await renderThreadName(actionConfig.name ?? "{user.tag}s thread");
const thread = await channel!.threads const thread = await channel.threads
.create({ .create({
name: threadName, name: threadName,
autoArchiveDuration: autoArchive, autoArchiveDuration: autoArchive,

View file

@ -1,4 +1,3 @@
import { Snowflake } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { SavedMessage } from "../../../data/entities/SavedMessage"; import { SavedMessage } from "../../../data/entities/SavedMessage";

View file

@ -1,4 +1,4 @@
import { ActivityType, Snowflake, TextChannel } from "discord.js"; import { ActivityType, Snowflake } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { messageSummary, verboseChannelMention } from "../../../utils"; import { messageSummary, verboseChannelMention } from "../../../utils";
import { AutomodContext, AutomodPluginType } from "../types"; import { AutomodContext, AutomodPluginType } from "../types";

View file

@ -1,8 +1,9 @@
import { Constants, MessageEmbed } from "discord.js"; import { ActivityType, Embed } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { SavedMessage } from "../../../data/entities/SavedMessage"; import { SavedMessage } from "../../../data/entities/SavedMessage";
import { resolveMember } from "../../../utils"; import { resolveMember } from "../../../utils";
import { AutomodPluginType } from "../types"; import { AutomodPluginType } from "../types";
import { DeepMutable } from "../../../utils/typeUtils.js";
type TextTriggerWithMultipleMatchTypes = { type TextTriggerWithMultipleMatchTypes = {
match_messages: boolean; match_messages: boolean;
@ -33,7 +34,7 @@ export async function* matchMultipleTextTypesOnMessage(
} }
if (trigger.match_embeds && msg.data.embeds?.length) { if (trigger.match_embeds && msg.data.embeds?.length) {
const copiedEmbed: MessageEmbed = JSON.parse(JSON.stringify(msg.data.embeds[0])); const copiedEmbed: DeepMutable<Embed> = JSON.parse(JSON.stringify(msg.data.embeds[0]));
if (copiedEmbed.video) { if (copiedEmbed.video) {
copiedEmbed.description = ""; // The description is not rendered, hence it doesn't need to be matched copiedEmbed.description = ""; // The description is not rendered, hence it doesn't need to be matched
} }
@ -53,7 +54,7 @@ export async function* matchMultipleTextTypesOnMessage(
} }
for (const activity of member.presence?.activities ?? []) { for (const activity of member.presence?.activities ?? []) {
if (activity.type === Constants.ActivityTypes[4]) { if (activity.type === ActivityType.Custom) {
yield ["customstatus", `${activity.emoji} ${activity.name}`]; yield ["customstatus", `${activity.emoji} ${activity.name}`];
break; break;
} }

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel, ThreadChannel } from "discord.js"; import { Snowflake } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
import { disableUserNotificationStrings, UserNotificationMethod } from "../../../utils"; import { disableUserNotificationStrings, UserNotificationMethod } from "../../../utils";

View file

@ -1,4 +1,4 @@
import { GuildTextBasedChannel, Snowflake, TextChannel, ThreadChannel } from "discord.js"; import { GuildTextBasedChannel, Snowflake } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { availableActions } from "../actions/availableActions"; import { availableActions } from "../actions/availableActions";
import { CleanAction } from "../actions/clean"; import { CleanAction } from "../actions/clean";

View file

@ -1,7 +1,5 @@
import { User } from "discord.js"; import { User } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { LogType } from "../../../data/LogType";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";
import { runAutomodOnAntiraidLevel } from "../events/runAutomodOnAntiraidLevel"; import { runAutomodOnAntiraidLevel } from "../events/runAutomodOnAntiraidLevel";
import { AutomodPluginType } from "../types"; import { AutomodPluginType } from "../types";

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { verboseChannelMention } from "../../../utils"; import { verboseChannelMention } from "../../../utils";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";

View file

@ -1,4 +1,4 @@
import { escapeInlineCode, Snowflake, TextChannel } from "discord.js"; import { escapeInlineCode, Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils"; import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";
@ -66,7 +66,7 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
}, },
renderMatchInformation({ pluginData, contexts, matchResult }) { renderMatchInformation({ pluginData, contexts, matchResult }) {
const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake); const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake)!;
const prettyChannel = verboseChannelMention(channel); const prettyChannel = verboseChannelMention(channel);
return ( return (

View file

@ -1,4 +1,3 @@
import escapeStringRegexp from "escape-string-regexp";
import * as t from "io-ts"; import * as t from "io-ts";
import { allowTimeout } from "../../../RegExpRunner"; import { allowTimeout } from "../../../RegExpRunner";
import { getUrlsInString, tNullable } from "../../../utils"; import { getUrlsInString, tNullable } from "../../../utils";

View file

@ -1,7 +1,7 @@
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";
import * as t from "io-ts"; import * as t from "io-ts";
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils"; import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
import { escapeInlineCode, GuildChannel } from "discord.js"; import { escapeInlineCode } from "discord.js";
interface MatchResultType { interface MatchResultType {
matchedType: string; matchedType: string;
@ -65,8 +65,8 @@ export const MatchMimeTypeTrigger = automodTrigger<MatchResultType>()({
renderMatchInformation({ pluginData, contexts, matchResult }) { renderMatchInformation({ pluginData, contexts, matchResult }) {
const { message } = contexts[0]; const { message } = contexts[0];
const channel = pluginData.guild.channels.resolve(message!.channel_id); const channel = pluginData.guild.channels.resolve(message!.channel_id)!;
const prettyChannel = verboseChannelMention(channel as GuildChannel); const prettyChannel = verboseChannelMention(channel);
const { matchedType, mode } = matchResult.extra; const { matchedType, mode } = matchResult.extra;
return ( return (

View file

@ -1,5 +1,4 @@
import { Snowflake } from "discord-api-types/v9"; import { escapeBold, User, type Snowflake } from "discord.js";
import { escapeBold, User } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { tNullable } from "../../../utils"; import { tNullable } from "../../../utils";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";

View file

@ -1,5 +1,4 @@
import { Snowflake } from "discord-api-types/v9"; import { escapeBold, User, type Snowflake } from "discord.js";
import { escapeBold, User } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";

View file

@ -1,5 +1,4 @@
import { Snowflake } from "discord-api-types/v9"; import { escapeBold, User, type Snowflake } from "discord.js";
import { escapeBold, User } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";

View file

@ -1,5 +1,4 @@
import { Snowflake } from "discord-api-types/v9"; import { escapeBold, User, type Snowflake } from "discord.js";
import { escapeBold, User } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { tNullable } from "../../../utils"; import { tNullable } from "../../../utils";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";

View file

@ -1,4 +1,4 @@
import { GuildMember, GuildTextBasedChannel, PartialGuildMember, TextChannel, ThreadChannel, User } from "discord.js"; import { GuildMember, GuildTextBasedChannel, PartialGuildMember, ThreadChannel, User } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { BasePluginType, CooldownManager } from "knub"; import { BasePluginType, CooldownManager } from "knub";
import { SavedMessage } from "../../data/entities/SavedMessage"; import { SavedMessage } from "../../data/entities/SavedMessage";

View file

@ -1,5 +1,4 @@
import { ApiPermissions } from "@shared/apiPermissions"; import { ApiPermissions } from "@shared/apiPermissions";
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
@ -38,7 +37,7 @@ export const AddDashboardUserCmd = botControlCmd({
const userNameList = args.users.map((user) => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`); const userNameList = args.users.map((user) => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`);
sendSuccessMessage( sendSuccessMessage(
pluginData, pluginData,
msg.channel as TextChannel, msg.channel,
`The following users were given dashboard access for **${guild.name}**:\n\n${userNameList}`, `The following users were given dashboard access for **${guild.name}**:\n\n${userNameList}`,
); );
}, },

View file

@ -1,8 +1,7 @@
import { ApiPermissions } from "@shared/apiPermissions"; import { ApiPermissions } from "@shared/apiPermissions";
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { DBDateFormat, isGuildInvite, isSnowflake, resolveInvite } from "../../../utils"; import { DBDateFormat, isGuildInvite, resolveInvite } from "../../../utils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { isEligible } from "../functions/isEligible"; import { isEligible } from "../functions/isEligible";
@ -19,23 +18,19 @@ export const AddServerFromInviteCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const invite = await resolveInvite(pluginData.client, args.inviteCode, true); const invite = await resolveInvite(pluginData.client, args.inviteCode, true);
if (!invite || !isGuildInvite(invite)) { if (!invite || !isGuildInvite(invite)) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not resolve invite"); // :D sendErrorMessage(pluginData, msg.channel, "Could not resolve invite"); // :D
return; return;
} }
const existing = await pluginData.state.allowedGuilds.find(invite.guild.id); const existing = await pluginData.state.allowedGuilds.find(invite.guild.id);
if (existing) { if (existing) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Server is already allowed!"); sendErrorMessage(pluginData, msg.channel, "Server is already allowed!");
return; return;
} }
const { result, explanation } = await isEligible(pluginData, args.user, invite); const { result, explanation } = await isEligible(pluginData, args.user, invite);
if (!result) { if (!result) {
sendErrorMessage( sendErrorMessage(pluginData, msg.channel, `Could not add server because it's not eligible: ${explanation}`);
pluginData,
msg.channel as TextChannel,
`Could not add server because it's not eligible: ${explanation}`,
);
return; return;
} }
@ -56,10 +51,6 @@ export const AddServerFromInviteCmd = botControlCmd({
); );
} }
sendSuccessMessage( sendSuccessMessage(pluginData, msg.channel, "Server was eligible and is now allowed to use Zeppelin!");
pluginData,
msg.channel as TextChannel,
"Server was eligible and is now allowed to use Zeppelin!",
);
}, },
}); });

View file

@ -1,5 +1,4 @@
import { ApiPermissions } from "@shared/apiPermissions"; import { ApiPermissions } from "@shared/apiPermissions";
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { DBDateFormat, isSnowflake } from "../../../utils"; import { DBDateFormat, isSnowflake } from "../../../utils";
@ -21,17 +20,17 @@ export const AllowServerCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const existing = await pluginData.state.allowedGuilds.find(args.guildId); const existing = await pluginData.state.allowedGuilds.find(args.guildId);
if (existing) { if (existing) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Server is already allowed!"); sendErrorMessage(pluginData, msg.channel, "Server is already allowed!");
return; return;
} }
if (!isSnowflake(args.guildId)) { if (!isSnowflake(args.guildId)) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Invalid server ID!"); sendErrorMessage(pluginData, msg.channel, "Invalid server ID!");
return; return;
} }
if (args.userId && !isSnowflake(args.userId)) { if (args.userId && !isSnowflake(args.userId)) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Invalid user ID!"); sendErrorMessage(pluginData, msg.channel, "Invalid user ID!");
return; return;
} }
@ -52,6 +51,6 @@ export const AllowServerCmd = botControlCmd({
); );
} }
sendSuccessMessage(pluginData, msg.channel as TextChannel, "Server is now allowed to use Zeppelin!"); sendSuccessMessage(pluginData, msg.channel, "Server is now allowed to use Zeppelin!");
}, },
}); });

View file

@ -1,9 +1,6 @@
import { Guild, GuildChannel, TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isStaffPreFilter, sendErrorMessage } from "../../../pluginUtils";
import { GuildInvite, isGuildInvite, resolveInvite, verboseUserMention } from "../../../utils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
import { isEligible } from "../functions/isEligible";
export const ChannelToServerCmd = botControlCmd({ export const ChannelToServerCmd = botControlCmd({
trigger: ["channel_to_server", "channel2server"], trigger: ["channel_to_server", "channel2server"],
@ -19,13 +16,13 @@ export const ChannelToServerCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const channel = pluginData.client.channels.cache.get(args.channelId); const channel = pluginData.client.channels.cache.get(args.channelId);
if (!channel) { if (!channel) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Channel not found in cache!"); sendErrorMessage(pluginData, msg.channel, "Channel not found in cache!");
return; return;
} }
const channelName = channel.isVoice() ? channel.name : `#${(channel as TextChannel).name}`; const channelName = channel.isVoiceBased() ? channel.name : `#${"name" in channel ? channel.name : channel.id}`;
const guild: Guild | null = (channel as GuildChannel).guild ?? null; const guild = "guild" in channel ? channel.guild : null;
const guildInfo = guild ? `${guild.name} (\`${guild.id}\`)` : "Not a server"; const guildInfo = guild ? `${guild.name} (\`${guild.id}\`)` : "Not a server";
msg.channel.send(`**Channel:** ${channelName} (\`${channel.type}\`) (<#${channel.id}>)\n**Server:** ${guildInfo}`); msg.channel.send(`**Channel:** ${channelName} (\`${channel.type}\`) (<#${channel.id}>)\n**Server:** ${guildInfo}`);

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { noop } from "../../../utils"; import { noop } from "../../../utils";
@ -18,7 +18,7 @@ export const DisallowServerCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const existing = await pluginData.state.allowedGuilds.find(args.guildId); const existing = await pluginData.state.allowedGuilds.find(args.guildId);
if (!existing) { if (!existing) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "That server is not allowed in the first place!"); sendErrorMessage(pluginData, msg.channel, "That server is not allowed in the first place!");
return; return;
} }
@ -27,6 +27,6 @@ export const DisallowServerCmd = botControlCmd({
.get(args.guildId as Snowflake) .get(args.guildId as Snowflake)
?.leave() ?.leave()
.catch(noop); .catch(noop);
sendSuccessMessage(pluginData, msg.channel as TextChannel, "Server removed!"); sendSuccessMessage(pluginData, msg.channel, "Server removed!");
}, },
}); });

View file

@ -1,7 +1,6 @@
import { Guild, TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { GuildInvite, isGuildInvite, resolveInvite, verboseUserMention } from "../../../utils"; import { isGuildInvite, resolveInvite } from "../../../utils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
import { isEligible } from "../functions/isEligible"; import { isEligible } from "../functions/isEligible";
@ -17,17 +16,17 @@ export const EligibleCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const invite = await resolveInvite(pluginData.client, args.inviteCode, true); const invite = await resolveInvite(pluginData.client, args.inviteCode, true);
if (!invite || !isGuildInvite(invite)) { if (!invite || !isGuildInvite(invite)) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not resolve invite"); sendErrorMessage(pluginData, msg.channel, "Could not resolve invite");
return; return;
} }
const { result, explanation } = await isEligible(pluginData, args.user, invite); const { result, explanation } = await isEligible(pluginData, args.user, invite);
if (result) { if (result) {
sendSuccessMessage(pluginData, msg.channel as TextChannel, `Server is eligible: ${explanation}`); sendSuccessMessage(pluginData, msg.channel, `Server is eligible: ${explanation}`);
return; return;
} }
sendErrorMessage(pluginData, msg.channel as TextChannel, `Server is **NOT** eligible: ${explanation}`); sendErrorMessage(pluginData, msg.channel, `Server is **NOT** eligible: ${explanation}`);
}, },
}); });

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
@ -16,7 +16,7 @@ export const LeaveServerCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) { if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "I am not in that guild"); sendErrorMessage(pluginData, msg.channel, "I am not in that guild");
return; return;
} }
@ -26,10 +26,10 @@ export const LeaveServerCmd = botControlCmd({
try { try {
await pluginData.client.guilds.cache.get(args.guildId as Snowflake)?.leave(); await pluginData.client.guilds.cache.get(args.guildId as Snowflake)?.leave();
} catch (e) { } catch (e) {
sendErrorMessage(pluginData, msg.channel as TextChannel, `Failed to leave guild: ${e.message}`); sendErrorMessage(pluginData, msg.channel, `Failed to leave guild: ${e.message}`);
return; return;
} }
sendSuccessMessage(pluginData, msg.channel as TextChannel, `Left guild **${guildName}**`); sendSuccessMessage(pluginData, msg.channel, `Left guild **${guildName}**`);
}, },
}); });

View file

@ -1,8 +1,7 @@
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { AllowedGuild } from "../../../data/entities/AllowedGuild"; import { AllowedGuild } from "../../../data/entities/AllowedGuild";
import { ApiPermissionAssignment } from "../../../data/entities/ApiPermissionAssignment"; import { ApiPermissionAssignment } from "../../../data/entities/ApiPermissionAssignment";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { resolveUser } from "../../../utils"; import { resolveUser } from "../../../utils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
@ -17,7 +16,7 @@ export const ListDashboardPermsCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
if (!args.user && !args.guildId) { if (!args.user && !args.guildId) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Must specify at least guildId, user, or both."); sendErrorMessage(pluginData, msg.channel, "Must specify at least guildId, user, or both.");
return; return;
} }
@ -25,7 +24,7 @@ export const ListDashboardPermsCmd = botControlCmd({
if (args.guildId) { if (args.guildId) {
guild = await pluginData.state.allowedGuilds.find(args.guildId); guild = await pluginData.state.allowedGuilds.find(args.guildId);
if (!guild) { if (!guild) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Server is not using Zeppelin"); sendErrorMessage(pluginData, msg.channel, "Server is not using Zeppelin");
return; return;
} }
} }
@ -34,7 +33,7 @@ export const ListDashboardPermsCmd = botControlCmd({
if (args.user) { if (args.user) {
existingUserAssignment = await pluginData.state.apiPermissionAssignments.getByUserId(args.user.id); existingUserAssignment = await pluginData.state.apiPermissionAssignments.getByUserId(args.user.id);
if (existingUserAssignment.length === 0) { if (existingUserAssignment.length === 0) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "The user has no assigned permissions."); sendErrorMessage(pluginData, msg.channel, "The user has no assigned permissions.");
return; return;
} }
} }
@ -57,7 +56,7 @@ export const ListDashboardPermsCmd = botControlCmd({
if (finalMessage === "") { if (finalMessage === "") {
sendErrorMessage( sendErrorMessage(
pluginData, pluginData,
msg.channel as TextChannel, msg.channel,
`The user ${userInfo} has no assigned permissions on the specified server.`, `The user ${userInfo} has no assigned permissions on the specified server.`,
); );
return; return;
@ -68,11 +67,7 @@ export const ListDashboardPermsCmd = botControlCmd({
const existingGuildAssignment = await pluginData.state.apiPermissionAssignments.getByGuildId(guild.id); const existingGuildAssignment = await pluginData.state.apiPermissionAssignments.getByGuildId(guild.id);
if (existingGuildAssignment.length === 0) { if (existingGuildAssignment.length === 0) {
sendErrorMessage( sendErrorMessage(pluginData, msg.channel, `The server ${guildInfo} has no assigned permissions.`);
pluginData,
msg.channel as TextChannel,
`The server ${guildInfo} has no assigned permissions.`,
);
return; return;
} }
@ -83,6 +78,6 @@ export const ListDashboardPermsCmd = botControlCmd({
} }
} }
await sendSuccessMessage(pluginData, msg.channel as TextChannel, finalMessage.trim(), {}); await sendSuccessMessage(pluginData, msg.channel, finalMessage.trim(), {});
}, },
}); });

View file

@ -1,6 +1,5 @@
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { resolveUser } from "../../../utils"; import { resolveUser } from "../../../utils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
@ -15,7 +14,7 @@ export const ListDashboardUsersCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const guild = await pluginData.state.allowedGuilds.find(args.guildId); const guild = await pluginData.state.allowedGuilds.find(args.guildId);
if (!guild) { if (!guild) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Server is not using Zeppelin"); sendErrorMessage(pluginData, msg.channel, "Server is not using Zeppelin");
return; return;
} }
@ -33,7 +32,7 @@ export const ListDashboardUsersCmd = botControlCmd({
sendSuccessMessage( sendSuccessMessage(
pluginData, pluginData,
msg.channel as TextChannel, msg.channel,
`The following users have dashboard access for **${guild.name}**:\n\n${userNameList.join("\n")}`, `The following users have dashboard access for **${guild.name}**:\n\n${userNameList.join("\n")}`,
{}, {},
); );

View file

@ -1,7 +1,6 @@
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { getBaseUrl, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { getBaseUrl } from "../../../pluginUtils";
import { createChunkedMessage, formatNumber, resolveInvite, sorter, verboseUserMention } from "../../../utils"; import { sorter } from "../../../utils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
import { GuildArchives } from "../../../data/GuildArchives"; import { GuildArchives } from "../../../data/GuildArchives";
import moment from "moment-timezone"; import moment from "moment-timezone";

View file

@ -2,8 +2,7 @@ import { botControlCmd } from "../types";
import { getRateLimitStats } from "../../../rateLimitStats"; import { getRateLimitStats } from "../../../rateLimitStats";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { GuildArchives } from "../../../data/GuildArchives"; import { GuildArchives } from "../../../data/GuildArchives";
import { getBaseUrl, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { getBaseUrl, sendSuccessMessage } from "../../../pluginUtils";
import { TextChannel } from "discord.js";
export const RateLimitPerformanceCmd = botControlCmd({ export const RateLimitPerformanceCmd = botControlCmd({
trigger: ["rate_limit_performance"], trigger: ["rate_limit_performance"],
@ -14,7 +13,7 @@ export const RateLimitPerformanceCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const logItems = getRateLimitStats(); const logItems = getRateLimitStats();
if (logItems.length === 0) { if (logItems.length === 0) {
sendSuccessMessage(pluginData, msg.channel as TextChannel, `No rate limits hit`); sendSuccessMessage(pluginData, msg.channel, `No rate limits hit`);
return; return;
} }
@ -25,7 +24,7 @@ export const RateLimitPerformanceCmd = botControlCmd({
if (item.data.global) items.push("GLOBAL"); if (item.data.global) items.push("GLOBAL");
items.push(item.data.method.toUpperCase()); items.push(item.data.method.toUpperCase());
items.push(item.data.route); items.push(item.data.route);
items.push(`stalled for ${item.data.timeout}ms`); items.push(`stalled for ${item.data.timeToReset}ms`);
items.push(`(max requests ${item.data.limit})`); items.push(`(max requests ${item.data.limit})`);
return items.join(" "); return items.join(" ");
}); });

View file

@ -1,5 +1,4 @@
import { TextChannel } from "discord.js"; import { isStaffPreFilter, sendErrorMessage } from "../../../pluginUtils";
import { isStaffPreFilter } from "../../../pluginUtils";
import { getActiveReload, setActiveReload } from "../activeReload"; import { getActiveReload, setActiveReload } from "../activeReload";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
@ -13,7 +12,13 @@ export const ReloadGlobalPluginsCmd = botControlCmd({
async run({ pluginData, message }) { async run({ pluginData, message }) {
if (getActiveReload()) return; if (getActiveReload()) return;
setActiveReload((message.channel as TextChannel).guild?.id, message.channel.id); const guildId = "guild" in message.channel ? message.channel.guild.id : null;
if (!guildId) {
sendErrorMessage(pluginData, message.channel, "This command can only be used in a server");
return;
}
setActiveReload(guildId, message.channel.id);
await message.channel.send("Reloading global plugins..."); await message.channel.send("Reloading global plugins...");
pluginData.getKnubInstance().reloadGlobalContext(); pluginData.getKnubInstance().reloadGlobalContext();

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
@ -16,18 +16,18 @@ export const ReloadServerCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) { if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "I am not in that guild"); sendErrorMessage(pluginData, msg.channel, "I am not in that guild");
return; return;
} }
try { try {
await pluginData.getKnubInstance().reloadGuild(args.guildId); await pluginData.getKnubInstance().reloadGuild(args.guildId);
} catch (e) { } catch (e) {
sendErrorMessage(pluginData, msg.channel as TextChannel, `Failed to reload guild: ${e.message}`); sendErrorMessage(pluginData, msg.channel, `Failed to reload guild: ${e.message}`);
return; return;
} }
const guild = await pluginData.client.guilds.fetch(args.guildId as Snowflake); const guild = await pluginData.client.guilds.fetch(args.guildId as Snowflake);
sendSuccessMessage(pluginData, msg.channel as TextChannel, `Reloaded guild **${guild?.name || "???"}**`); sendSuccessMessage(pluginData, msg.channel, `Reloaded guild **${guild?.name || "???"}**`);
}, },
}); });

View file

@ -1,4 +1,3 @@
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
@ -18,7 +17,7 @@ export const RemoveDashboardUserCmd = botControlCmd({
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg, args }) {
const guild = await pluginData.state.allowedGuilds.find(args.guildId); const guild = await pluginData.state.allowedGuilds.find(args.guildId);
if (!guild) { if (!guild) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Server is not using Zeppelin"); sendErrorMessage(pluginData, msg.channel, "Server is not using Zeppelin");
return; return;
} }
@ -37,7 +36,7 @@ export const RemoveDashboardUserCmd = botControlCmd({
const userNameList = args.users.map((user) => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`); const userNameList = args.users.map((user) => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`);
sendSuccessMessage( sendSuccessMessage(
pluginData, pluginData,
msg.channel as TextChannel, msg.channel,
`The following users were removed from the dashboard for **${guild.name}**:\n\n${userNameList}`, `The following users were removed from the dashboard for **${guild.name}**:\n\n${userNameList}`,
); );
}, },

View file

@ -1,7 +1,5 @@
import { TextChannel } from "discord.js";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { createChunkedMessage } from "../../../utils";
import { createChunkedMessage, formatNumber, resolveInvite, sorter, verboseUserMention } from "../../../utils";
import { botControlCmd } from "../types"; import { botControlCmd } from "../types";
import { getTopRestCallStats } from "../../../restCallStats"; import { getTopRestCallStats } from "../../../restCallStats";
@ -22,6 +20,6 @@ export const RestPerformanceCmd = botControlCmd({
const cleanSource = callStats.source.replace(leadingPathRegex, ""); const cleanSource = callStats.source.replace(leadingPathRegex, "");
return `**${callStats.count} calls**\n${callStats.method.toUpperCase()} ${callStats.path}\n${cleanSource}`; return `**${callStats.count} calls**\n${callStats.method.toUpperCase()} ${callStats.path}\n${cleanSource}`;
}); });
createChunkedMessage(msg.channel as TextChannel, `Top rest calls:\n\n${formatted.join("\n")}`); createChunkedMessage(msg.channel, `Top rest calls:\n\n${formatted.join("\n")}`);
}, },
}); });

View file

@ -1,4 +1,3 @@
import { TextChannel } from "discord.js";
import escapeStringRegexp from "escape-string-regexp"; import escapeStringRegexp from "escape-string-regexp";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isStaffPreFilter } from "../../../pluginUtils"; import { isStaffPreFilter } from "../../../pluginUtils";
@ -51,7 +50,7 @@ export const ServersCmd = botControlCmd({
const owner = getUser(pluginData.client, g.ownerId); const owner = getUser(pluginData.client, g.ownerId);
return `\`${paddedId}\` **${g.name}** (${g.memberCount} members) (owner **${owner.tag}** \`${owner.id}\`)`; return `\`${paddedId}\` **${g.name}** (${g.memberCount} members) (owner **${owner.tag}** \`${owner.id}\`)`;
}); });
createChunkedMessage(msg.channel as TextChannel, lines.join("\n")); createChunkedMessage(msg.channel, lines.join("\n"));
} else { } else {
msg.channel.send("No servers matched the filters"); msg.channel.send("No servers matched the filters");
} }

View file

@ -1,10 +1,10 @@
import type { Snowflake } from "discord-api-types/globals";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { logger } from "../../../logger"; import { logger } from "../../../logger";
import { resolveUser } from "../../../utils"; import { resolveUser } from "../../../utils";
import { CaseArgs, CasesPluginType } from "../types"; import { CaseArgs, CasesPluginType } from "../types";
import { createCaseNote } from "./createCaseNote"; import { createCaseNote } from "./createCaseNote";
import { postCaseToCaseLogChannel } from "./postToCaseLogChannel"; import { postCaseToCaseLogChannel } from "./postToCaseLogChannel";
import type { Snowflake } from "discord.js";
export async function createCase(pluginData: GuildPluginData<CasesPluginType>, args: CaseArgs) { export async function createCase(pluginData: GuildPluginData<CasesPluginType>, args: CaseArgs) {
const user = await resolveUser(pluginData.client, args.userId); const user = await resolveUser(pluginData.client, args.userId);

View file

@ -1,4 +1,4 @@
import { escapeCodeBlock, MessageEditOptions, MessageOptions } from "discord.js"; import { escapeCodeBlock, MessageEditOptions, MessageCreateOptions } 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"; import { CaseTypes } from "../../../data/CaseTypes";
@ -14,7 +14,7 @@ export async function getCaseEmbed(
caseOrCaseId: Case | number, caseOrCaseId: Case | number,
requestMemberId?: string, requestMemberId?: string,
noOriginalCaseLink?: boolean, noOriginalCaseLink?: boolean,
): Promise<MessageOptions & MessageEditOptions> { ): Promise<MessageCreateOptions & MessageEditOptions> {
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");

View file

@ -1,4 +1,4 @@
import { FileOptions, MessageOptions, NewsChannel, Snowflake, TextChannel } from "discord.js"; import { MessageCreateOptions, NewsChannel, RESTJSONErrorCodes, Snowflake, TextChannel } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { Case } from "../../../data/entities/Case"; import { Case } from "../../../data/entities/Case";
import { isDiscordAPIError } from "../../../utils"; import { isDiscordAPIError } from "../../../utils";
@ -11,8 +11,8 @@ import { InternalPosterMessageResult } from "../../InternalPoster/functions/send
export async function postToCaseLogChannel( export async function postToCaseLogChannel(
pluginData: GuildPluginData<CasesPluginType>, pluginData: GuildPluginData<CasesPluginType>,
content: MessageOptions, content: MessageCreateOptions,
file?: FileOptions[], files?: MessageCreateOptions["files"],
): Promise<InternalPosterMessageResult | null> { ): Promise<InternalPosterMessageResult | null> {
const caseLogChannelId = pluginData.config.get().case_log_channel; const caseLogChannelId = pluginData.config.get().case_log_channel;
if (!caseLogChannelId) return null; if (!caseLogChannelId) return null;
@ -23,13 +23,16 @@ export async function postToCaseLogChannel(
let result: InternalPosterMessageResult | null = null; let result: InternalPosterMessageResult | null = null;
try { try {
if (file != null) { if (files != null) {
content.files = file; content.files = files;
} }
const poster = pluginData.getPlugin(InternalPosterPlugin); const poster = pluginData.getPlugin(InternalPosterPlugin);
result = await poster.sendMessage(caseLogChannel, { ...content }); result = await poster.sendMessage(caseLogChannel, { ...content });
} catch (e) { } catch (e) {
if (isDiscordAPIError(e) && (e.code === 50013 || e.code === 50001)) { if (
isDiscordAPIError(e) &&
(e.code === RESTJSONErrorCodes.MissingPermissions || e.code === RESTJSONErrorCodes.MissingAccess)
) {
pluginData.getPlugin(LogsPlugin).logBotAlert({ pluginData.getPlugin(LogsPlugin).logBotAlert({
body: `Missing permissions to post mod cases in <#${caseLogChannel.id}>`, body: `Missing permissions to post mod cases in <#${caseLogChannel.id}>`,
}); });
@ -57,10 +60,12 @@ export async function postCaseToCaseLogChannel(
try { try {
const poster = pluginData.getPlugin(InternalPosterPlugin); const poster = pluginData.getPlugin(InternalPosterPlugin);
const channel = pluginData.guild.channels.resolve(channelId as Snowflake) as TextChannel; const channel = pluginData.guild.channels.resolve(channelId as Snowflake);
const message = await channel.messages.fetch(messageId); if (channel?.isTextBased()) {
if (message) { const message = await channel.messages.fetch(messageId);
await poster.editMessage(message, caseEmbed); if (message) {
await poster.editMessage(message, caseEmbed);
}
} }
return; return;
} catch {} // tslint:disable-line:no-empty } catch {} // tslint:disable-line:no-empty

View file

@ -1,4 +1,4 @@
import { Invite, MessageEmbed } from "discord.js"; import { Invite, Embed } from "discord.js";
import escapeStringRegexp from "escape-string-regexp"; import escapeStringRegexp from "escape-string-regexp";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
@ -19,7 +19,7 @@ export async function applyFiltersToMsg(
let messageContent = savedMessage.data.content || ""; let messageContent = savedMessage.data.content || "";
if (savedMessage.data.attachments) messageContent += " " + JSON.stringify(savedMessage.data.attachments); if (savedMessage.data.attachments) messageContent += " " + JSON.stringify(savedMessage.data.attachments);
if (savedMessage.data.embeds) { if (savedMessage.data.embeds) {
const embeds = (savedMessage.data.embeds as MessageEmbed[]).map((e) => cloneDeep(e)); const embeds = (savedMessage.data.embeds as Embed[]).map((e) => cloneDeep(e));
for (const embed of embeds) { for (const embed of embeds) {
if (embed.type === "video") { if (embed.type === "video") {
// Ignore video descriptions as they're not actually shown on the embed // Ignore video descriptions as they're not actually shown on the embed

View file

@ -1,6 +1,5 @@
import { BaseGuildTextChannel, GuildTextBasedChannel, Snowflake, TextChannel, ThreadChannel } from "discord.js"; import { GuildTextBasedChannel, Snowflake } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { SavedMessage } from "../../../data/entities/SavedMessage"; import { SavedMessage } from "../../../data/entities/SavedMessage";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { resolveUser } from "../../../utils"; import { resolveUser } from "../../../utils";
@ -15,8 +14,8 @@ export async function censorMessage(
pluginData.state.serverLogs.ignoreLog(LogType.MESSAGE_DELETE, savedMessage.id); pluginData.state.serverLogs.ignoreLog(LogType.MESSAGE_DELETE, savedMessage.id);
try { try {
const resolvedChannel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake) as TextChannel; const resolvedChannel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake);
await resolvedChannel.messages.delete(savedMessage.id as Snowflake); if (resolvedChannel?.isTextBased()) await resolvedChannel.messages.delete(savedMessage.id as Snowflake);
} catch { } catch {
return; return;
} }

View file

@ -1,4 +1,4 @@
import { Collection, Message, Snowflake } from "discord.js"; import { Snowflake } from "discord.js";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { isOwner, sendErrorMessage } from "../../../pluginUtils"; import { isOwner, sendErrorMessage } from "../../../pluginUtils";

View file

@ -1,14 +1,11 @@
import { MessageAttachment, MessageOptions, TextChannel, ThreadChannel } from "discord.js"; import { GuildTextBasedChannel, Attachment, MessageCreateOptions } from "discord.js";
import fs from "fs"; import fs from "fs";
import { downloadFile } from "../../utils"; import { downloadFile } from "../../utils";
const fsp = fs.promises; const fsp = fs.promises;
const MAX_ATTACHMENT_REHOST_SIZE = 1024 * 1024 * 8; const MAX_ATTACHMENT_REHOST_SIZE = 1024 * 1024 * 8;
export async function rehostAttachment( export async function rehostAttachment(attachment: Attachment, targetChannel: GuildTextBasedChannel): Promise<string> {
attachment: MessageAttachment,
targetChannel: TextChannel | ThreadChannel,
): Promise<string> {
if (attachment.size > MAX_ATTACHMENT_REHOST_SIZE) { if (attachment.size > MAX_ATTACHMENT_REHOST_SIZE) {
return "Attachment too big to rehost"; return "Attachment too big to rehost";
} }
@ -21,7 +18,7 @@ export async function rehostAttachment(
} }
try { try {
const content: MessageOptions = { const content: MessageCreateOptions = {
content: `Rehost of attachment ${attachment.id}`, content: `Rehost of attachment ${attachment.id}`,
files: [{ name: attachment.name ? attachment.name : undefined, attachment: await fsp.readFile(downloaded.path) }], files: [{ name: attachment.name ? attachment.name : undefined, attachment: await fsp.readFile(downloaded.path) }],
}; };

View file

@ -1,6 +1,5 @@
import { ContextMenuInteraction, TextChannel } from "discord.js"; import { ContextMenuCommandInteraction, TextChannel } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { LogType } from "../../../data/LogType";
import { UtilityPlugin } from "../../../plugins/Utility/UtilityPlugin"; import { UtilityPlugin } from "../../../plugins/Utility/UtilityPlugin";
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";
@ -9,7 +8,7 @@ import { ContextMenuPluginType } from "../types";
export async function cleanAction( export async function cleanAction(
pluginData: GuildPluginData<ContextMenuPluginType>, pluginData: GuildPluginData<ContextMenuPluginType>,
amount: number, amount: number,
interaction: ContextMenuInteraction, interaction: ContextMenuCommandInteraction,
) { ) {
interaction.deferReply({ ephemeral: true }); interaction.deferReply({ ephemeral: true });
const executingMember = await pluginData.guild.members.fetch(interaction.user.id); const executingMember = await pluginData.guild.members.fetch(interaction.user.id);

View file

@ -1,9 +1,8 @@
import { ContextMenuInteraction } from "discord.js"; import { ContextMenuCommandInteraction } from "discord.js";
import humanizeDuration from "humanize-duration"; import humanizeDuration from "humanize-duration";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { ModActionsPlugin } from "src/plugins/ModActions/ModActionsPlugin"; import { ModActionsPlugin } from "src/plugins/ModActions/ModActionsPlugin";
import { canActOn } from "src/pluginUtils"; import { canActOn } from "src/pluginUtils";
import { LogType } from "../../../data/LogType";
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError"; import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
import { convertDelayStringToMS } from "../../../utils"; import { convertDelayStringToMS } from "../../../utils";
import { CaseArgs } from "../../Cases/types"; import { CaseArgs } from "../../Cases/types";
@ -14,7 +13,7 @@ import { ContextMenuPluginType } from "../types";
export async function muteAction( export async function muteAction(
pluginData: GuildPluginData<ContextMenuPluginType>, pluginData: GuildPluginData<ContextMenuPluginType>,
duration: string | undefined, duration: string | undefined,
interaction: ContextMenuInteraction, interaction: ContextMenuCommandInteraction,
) { ) {
interaction.deferReply({ ephemeral: true }); interaction.deferReply({ ephemeral: true });
const executingMember = await pluginData.guild.members.fetch(interaction.user.id); const executingMember = await pluginData.guild.members.fetch(interaction.user.id);

View file

@ -1,11 +1,11 @@
import { ContextMenuInteraction } from "discord.js"; import { ContextMenuCommandInteraction } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { UtilityPlugin } from "../../../plugins/Utility/UtilityPlugin"; import { UtilityPlugin } from "../../../plugins/Utility/UtilityPlugin";
import { ContextMenuPluginType } from "../types"; import { ContextMenuPluginType } from "../types";
export async function userInfoAction( export async function userInfoAction(
pluginData: GuildPluginData<ContextMenuPluginType>, pluginData: GuildPluginData<ContextMenuPluginType>,
interaction: ContextMenuInteraction, interaction: ContextMenuCommandInteraction,
) { ) {
interaction.deferReply({ ephemeral: true }); interaction.deferReply({ ephemeral: true });
const executingMember = await pluginData.guild.members.fetch(interaction.user.id); const executingMember = await pluginData.guild.members.fetch(interaction.user.id);

View file

@ -1,4 +1,3 @@
import { ContextMenuInteraction } from "discord.js";
import { contextMenuEvt } from "../types"; import { contextMenuEvt } from "../types";
import { routeContextAction } from "../utils/contextRouter"; import { routeContextAction } from "../utils/contextRouter";
@ -6,8 +5,8 @@ export const ContextClickedEvt = contextMenuEvt({
event: "interactionCreate", event: "interactionCreate",
async listener(meta) { async listener(meta) {
if (!meta.args.interaction.isContextMenu) return; if (!meta.args.interaction.isContextMenuCommand()) return;
const inter = meta.args.interaction as ContextMenuInteraction; const inter = meta.args.interaction;
await routeContextAction(meta.pluginData, inter); await routeContextAction(meta.pluginData, inter);
}, },
}); });

View file

@ -1,11 +1,11 @@
import { ContextMenuInteraction } from "discord.js"; import { ContextMenuCommandInteraction } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { ContextMenuPluginType } from "../types"; import { ContextMenuPluginType } from "../types";
import { hardcodedActions } from "./hardcodedContextOptions"; import { hardcodedActions } from "./hardcodedContextOptions";
export async function routeContextAction( export async function routeContextAction(
pluginData: GuildPluginData<ContextMenuPluginType>, pluginData: GuildPluginData<ContextMenuPluginType>,
interaction: ContextMenuInteraction, interaction: ContextMenuCommandInteraction,
) { ) {
const contextLink = await pluginData.state.contextMenuLinks.get(interaction.commandId); const contextLink = await pluginData.state.contextMenuLinks.get(interaction.commandId);
if (!contextLink) return; if (!contextLink) return;

View file

@ -1,5 +1,4 @@
import { ApplicationCommandData, Constants } from "discord.js"; import { ApplicationCommandData, ApplicationCommandType } from "discord.js";
import { LogType } from "../../../data/LogType";
import { LogsPlugin } from "../../../plugins/Logs/LogsPlugin"; import { LogsPlugin } from "../../../plugins/Logs/LogsPlugin";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { ContextMenuPluginType } from "../types"; import { ContextMenuPluginType } from "../types";
@ -14,9 +13,7 @@ export async function loadAllCommands(pluginData: GuildPluginData<ContextMenuPlu
for (const [name, label] of Object.entries(hardcodedContext)) { for (const [name, label] of Object.entries(hardcodedContext)) {
if (!cfg[name]) continue; if (!cfg[name]) continue;
const type = name.startsWith("user") const type = name.startsWith("user") ? ApplicationCommandType.User : ApplicationCommandType.Message;
? Constants.ApplicationCommandTypes.USER
: Constants.ApplicationCommandTypes.MESSAGE;
const data: ApplicationCommandData = { const data: ApplicationCommandData = {
type, type,
name: label, name: label,

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake } from "discord.js";
import { guildPluginMessageCommand } from "knub"; import { guildPluginMessageCommand } from "knub";
import { waitForReply } from "knub/dist/helpers"; import { waitForReply } from "knub/dist/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";

View file

@ -1,11 +1,11 @@
import { parseSignature, guildPluginMessageCommand } from "knub"; import { parseSignature, guildPluginMessageCommand } from "knub";
import { commandTypes } from "../../commandTypes"; import { commandTypes } from "../../commandTypes";
import { stripObjectToScalars, UnknownUser } from "../../utils"; import { UnknownUser } from "../../utils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint"; import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { runEvent } from "./functions/runEvent"; import { runEvent } from "./functions/runEvent";
import { ConfigSchema, CustomEventsPluginType } from "./types"; import { ConfigSchema, CustomEventsPluginType } from "./types";
import { createTypedTemplateSafeValueContainer, TemplateSafeValueContainer } from "../../templateFormatter"; import { createTypedTemplateSafeValueContainer, TemplateSafeValueContainer } from "../../templateFormatter";
import { Channel, GuildChannel, GuildMember, ThreadChannel, User } from "discord.js"; import { GuildChannel, GuildMember, ThreadChannel, User } from "discord.js";
import { import {
channelToTemplateSafeChannel, channelToTemplateSafeChannel,
memberToTemplateSafeMember, memberToTemplateSafeMember,

View file

@ -1,4 +1,3 @@
import { Snowflake } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { canActOn } from "../../../pluginUtils"; import { canActOn } from "../../../pluginUtils";

View file

@ -25,22 +25,10 @@ export async function makeRoleMentionableAction(
throw new ActionError(`Unknown role: ${role}`); throw new ActionError(`Unknown role: ${role}`);
} }
await role.edit( await role.setMentionable(true, `Custom event: ${event.name}`);
{
mentionable: true,
},
`Custom event: ${event.name}`,
);
const timeout = convertDelayStringToMS(action.timeout)!; const timeout = convertDelayStringToMS(action.timeout)!;
setTimeout(() => { setTimeout(() => {
role role.setMentionable(false, `Custom event: ${event.name}`).catch(noop);
.edit(
{
mentionable: false,
},
`Custom event: ${event.name}`,
)
.catch(noop);
}, timeout); }, timeout);
} }

View file

@ -23,10 +23,5 @@ export async function makeRoleUnmentionableAction(
throw new ActionError(`Unknown role: ${role}`); throw new ActionError(`Unknown role: ${role}`);
} }
await role.edit( await role.setMentionable(false, `Custom event: ${event.name}`);
{
mentionable: false,
},
`Custom event: ${event.name}`,
);
} }

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel, PermissionsString, PermissionsBitField } from "discord.js"; import { Snowflake, PermissionsString, PermissionsBitField } from "discord.js";
import * as t from "io-ts"; import * as t from "io-ts";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { ActionError } from "../ActionError"; import { ActionError } from "../ActionError";
@ -26,8 +26,8 @@ export async function setChannelPermissionOverridesAction(
event: TCustomEvent, event: TCustomEvent,
eventData: any, eventData: any,
) { ) {
const channel = pluginData.guild.channels.cache.get(action.channel as Snowflake) as TextChannel; const channel = pluginData.guild.channels.cache.get(action.channel as Snowflake);
if (!channel) { if (!channel || channel.isThread() || !("guild" in channel)) {
throw new ActionError(`Unknown channel: ${action.channel}`); throw new ActionError(`Unknown channel: ${action.channel}`);
} }

View file

@ -1,4 +1,4 @@
import { Message, TextChannel } from "discord.js"; import { Message } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { ActionError } from "../ActionError"; import { ActionError } from "../ActionError";
@ -39,7 +39,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") {
sendErrorMessage(pluginData, (eventData.msg as Message).channel as TextChannel, e.message); sendErrorMessage(pluginData, (eventData.msg as Message).channel, 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?
} }

View file

@ -1,5 +1,5 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { GuildPluginData, guildPluginEventListener } from "knub"; import { guildPluginEventListener } from "knub";
import { AllowedGuilds } from "../../data/AllowedGuilds"; import { AllowedGuilds } from "../../data/AllowedGuilds";
import { MINUTES } from "../../utils"; import { MINUTES } from "../../utils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint"; import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";

View file

@ -1,5 +1,4 @@
import { BasePluginType } from "knub"; import { BasePluginType } from "knub";
import { AllowedGuilds } from "../../data/AllowedGuilds";
export interface GuildInfoSaverPluginType extends BasePluginType { export interface GuildInfoSaverPluginType extends BasePluginType {
state: { state: {

View file

@ -1,13 +1,6 @@
import { PluginOptions, guildPluginMessageCommand } from "knub"; import { PluginOptions } from "knub";
import { GuildPingableRoles } from "../../data/GuildPingableRoles";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint"; import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { ConfigSchema, InternalPosterPluginType } from "./types"; import { ConfigSchema, InternalPosterPluginType } from "./types";
import {
getPhishermanDomainInfo,
hasPhishermanMasterAPIKey,
phishermanApiKeyIsValid,
reportTrackedDomainsToPhisherman,
} from "../../data/Phisherman";
import { mapToPublicFn } from "../../pluginUtils"; import { mapToPublicFn } from "../../pluginUtils";
import { Webhooks } from "../../data/Webhooks"; import { Webhooks } from "../../data/Webhooks";
import { Queue } from "../../Queue"; import { Queue } from "../../Queue";

View file

@ -1,11 +1,4 @@
import { import { Message, MessageEditOptions, WebhookClient, WebhookMessageEditOptions } from "discord.js";
Message,
MessageEditOptions,
NewsChannel,
TextChannel,
WebhookClient,
WebhookEditMessageOptions,
} from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { InternalPosterPluginType } from "../types"; import { InternalPosterPluginType } from "../types";
import { isDiscordAPIError, noop } from "../../../utils"; import { isDiscordAPIError, noop } from "../../../utils";
@ -16,14 +9,13 @@ import { isDiscordAPIError, noop } from "../../../utils";
export async function editMessage( export async function editMessage(
pluginData: GuildPluginData<InternalPosterPluginType>, pluginData: GuildPluginData<InternalPosterPluginType>,
message: Message, message: Message,
content: MessageEditOptions & WebhookEditMessageOptions, content: MessageEditOptions & WebhookMessageEditOptions,
): Promise<void> { ): Promise<void> {
if (!(message.channel instanceof TextChannel || message.channel instanceof NewsChannel)) { const channel = message.channel;
if (!channel.isTextBased()) {
return; return;
} }
const channel = message.channel as TextChannel | NewsChannel;
await pluginData.state.queue.add(async () => { await pluginData.state.queue.add(async () => {
if (message.webhookId) { if (message.webhookId) {
const webhook = await pluginData.state.webhooks.find(message.webhookId); const webhook = await pluginData.state.webhooks.find(message.webhookId);

View file

@ -1,13 +1,6 @@
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { InternalPosterPluginType } from "../types"; import { InternalPosterPluginType } from "../types";
import { import { GuildBasedChannel, PermissionsBitField } from "discord.js";
GuildBasedChannel,
GuildChannel,
MessageManager,
NewsChannel,
PermissionsBitField,
TextChannel,
} from "discord.js";
import { isDiscordAPIError } from "../../../utils"; import { isDiscordAPIError } from "../../../utils";
type WebhookInfo = [id: string, token: string]; type WebhookInfo = [id: string, token: string];

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake } from "discord.js";
import { locateUserEvt } from "../types"; import { locateUserEvt } from "../types";
import { sendAlerts } from "../utils/sendAlerts"; import { sendAlerts } from "../utils/sendAlerts";
@ -20,11 +20,13 @@ export const VoiceStateUpdateAlertEvt = locateUserEvt({
const voiceChannel = meta.args.oldState.channel!; const voiceChannel = meta.args.oldState.channel!;
triggeredAlerts.forEach((alert) => { triggeredAlerts.forEach((alert) => {
const txtChannel = meta.pluginData.guild.channels.resolve(alert.channel_id as Snowflake) as TextChannel; const txtChannel = meta.pluginData.guild.channels.resolve(alert.channel_id as Snowflake);
txtChannel.send({ if (txtChannel?.isTextBased()) {
content: `🔴 <@!${alert.requestor_id}> the user <@!${alert.user_id}> disconnected out of \`${voiceChannel.name}\``, txtChannel.send({
allowedMentions: { users: [alert.requestor_id as Snowflake] }, content: `🔴 <@!${alert.requestor_id}> the user <@!${alert.user_id}> disconnected out of \`${voiceChannel.name}\``,
}); allowedMentions: { users: [alert.requestor_id as Snowflake] },
});
}
}); });
} }
}, },

View file

@ -1,7 +1,6 @@
import * as t from "io-ts"; import * as t from "io-ts";
import { BasePluginType, guildPluginMessageCommand, guildPluginEventListener } from "knub"; import { BasePluginType, guildPluginMessageCommand, guildPluginEventListener } from "knub";
import { GuildVCAlerts } from "../../data/GuildVCAlerts"; import { GuildVCAlerts } from "../../data/GuildVCAlerts";
import Timeout = NodeJS.Timeout;
export const ConfigSchema = t.type({ export const ConfigSchema = t.type({
can_where: t.boolean, can_where: t.boolean,

View file

@ -1,4 +1,4 @@
import { GuildMember, Snowflake, TextChannel } from "discord.js"; import { GuildMember, Snowflake, GuildTextBasedChannel } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { LocateUserPluginType } from "../types"; import { LocateUserPluginType } from "../types";
@ -7,7 +7,7 @@ export async function moveMember(
pluginData: GuildPluginData<LocateUserPluginType>, pluginData: GuildPluginData<LocateUserPluginType>,
toMoveID: string, toMoveID: string,
target: GuildMember, target: GuildMember,
errorChannel: TextChannel, errorChannel: GuildTextBasedChannel,
) { ) {
const modMember: GuildMember = await pluginData.guild.members.fetch(toMoveID as Snowflake); const modMember: GuildMember = await pluginData.guild.members.fetch(toMoveID as Snowflake);
if (modMember.voice.channelId != null) { if (modMember.voice.channelId != null) {

View file

@ -1,4 +1,4 @@
import { Snowflake, TextChannel } from "discord.js"; import { Snowflake } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { resolveMember } from "../../../utils"; import { resolveMember } from "../../../utils";
import { LocateUserPluginType } from "../types"; import { LocateUserPluginType } from "../types";
@ -12,10 +12,12 @@ export async function sendAlerts(pluginData: GuildPluginData<LocateUserPluginTyp
triggeredAlerts.forEach((alert) => { triggeredAlerts.forEach((alert) => {
const prepend = `<@!${alert.requestor_id}>, an alert requested by you has triggered!\nReminder: \`${alert.body}\`\n`; const prepend = `<@!${alert.requestor_id}>, an alert requested by you has triggered!\nReminder: \`${alert.body}\`\n`;
const txtChannel = pluginData.guild.channels.resolve(alert.channel_id as Snowflake) as TextChannel; const txtChannel = pluginData.guild.channels.resolve(alert.channel_id as Snowflake);
sendWhere(pluginData, member, txtChannel, prepend); if (txtChannel?.isTextBased()) {
if (alert.active) { sendWhere(pluginData, member, txtChannel, prepend);
moveMember(pluginData, alert.requestor_id, member, txtChannel); if (alert.active) {
moveMember(pluginData, alert.requestor_id, member, txtChannel);
}
} }
}); });
} }

View file

@ -1,4 +1,4 @@
import { GuildMember, Invite, TextChannel, VoiceChannel } from "discord.js"; import { GuildMember, GuildTextBasedChannel, Invite, VoiceChannel } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { getInviteLink } from "knub/dist/helpers"; import { getInviteLink } from "knub/dist/helpers";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
@ -8,7 +8,7 @@ import { createOrReuseInvite } from "./createOrReuseInvite";
export async function sendWhere( export async function sendWhere(
pluginData: GuildPluginData<LocateUserPluginType>, pluginData: GuildPluginData<LocateUserPluginType>,
member: GuildMember, member: GuildMember,
channel: TextChannel, channel: GuildTextBasedChannel,
prepend: string, prepend: string,
) { ) {
const voice = member.voice.channelId const voice = member.voice.channelId

View file

@ -35,11 +35,7 @@ import { log } from "./util/log";
import { onMessageDelete } from "./util/onMessageDelete"; import { onMessageDelete } from "./util/onMessageDelete";
import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk"; import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk";
import { onMessageUpdate } from "./util/onMessageUpdate"; import { onMessageUpdate } from "./util/onMessageUpdate";
import { import { createTypedTemplateSafeValueContainer, TypedTemplateSafeValueContainer } from "../../templateFormatter";
createTypedTemplateSafeValueContainer,
TemplateSafeValueContainer,
TypedTemplateSafeValueContainer,
} from "../../templateFormatter";
import { mapToPublicFn } from "../../pluginUtils"; import { mapToPublicFn } from "../../pluginUtils";
import { logAutomodAction } from "./logFunctions/logAutomodAction"; import { logAutomodAction } from "./logFunctions/logAutomodAction";

Some files were not shown because too many files have changed in this diff Show more