mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-10 12:25:02 +00:00
Update djs & knub (#395)
* update pkgs
Signed-off-by: GitHub <noreply@github.com>
* new knub typings
Signed-off-by: GitHub <noreply@github.com>
* more pkg updates
Signed-off-by: GitHub <noreply@github.com>
* more fixes
Signed-off-by: GitHub <noreply@github.com>
* channel typings
Signed-off-by: GitHub <noreply@github.com>
* more message utils typings fixes
Signed-off-by: GitHub <noreply@github.com>
* migrate permissions
Signed-off-by: GitHub <noreply@github.com>
* fix: InternalPoster webhookables
Signed-off-by: GitHub <noreply@github.com>
* djs typings: Attachment & Util
Signed-off-by: GitHub <noreply@github.com>
* more typings
Signed-off-by: GitHub <noreply@github.com>
* fix: rename permissionNames
Signed-off-by: GitHub <noreply@github.com>
* more fixes
Signed-off-by: GitHub <noreply@github.com>
* half the number of errors
* knub commands => messageCommands
Signed-off-by: GitHub <noreply@github.com>
* configPreprocessor => configParser
Signed-off-by: GitHub <noreply@github.com>
* fix channel.messages
Signed-off-by: GitHub <noreply@github.com>
* revert automod any typing
Signed-off-by: GitHub <noreply@github.com>
* more configParser typings
Signed-off-by: GitHub <noreply@github.com>
* revert
Signed-off-by: GitHub <noreply@github.com>
* remove knub type params
Signed-off-by: GitHub <noreply@github.com>
* fix more MessageEmbed / MessageOptions
Signed-off-by: GitHub <noreply@github.com>
* dumb commit for @almeidx to see why this is stupid
Signed-off-by: GitHub <noreply@github.com>
* temp disable custom_events
Signed-off-by: GitHub <noreply@github.com>
* more minor typings fixes - 23 err left
Signed-off-by: GitHub <noreply@github.com>
* update djs dep
* +debug build method (revert this)
Signed-off-by: GitHub <noreply@github.com>
* Revert "+debug build method (revert this)"
This reverts commit a80af1e729
.
* Redo +debug build (Revert this)
Signed-off-by: GitHub <noreply@github.com>
* uniform before/after Load shorthands
Signed-off-by: GitHub <noreply@github.com>
* remove unused imports & add prettier plugin
Signed-off-by: GitHub <noreply@github.com>
* env fixes for web platform hosting
Signed-off-by: GitHub <noreply@github.com>
* feat: knub v32-next; related fixes
* fix: allow legacy keys in change_perms action
* fix: request Message Content intent
* fix: use Knub's config validation logic in API
* fix(dashboard): fix error when there are no message and/or slash commands in a plugin
* fix(automod): start_thread action thread options
* fix(CustomEvents): message command types
* chore: remove unneeded type annotation
* feat: add forum channel icon; use thread icon for news threads
* chore: make tslint happy
* chore: fix formatting
---------
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: almeidx <almeidx@pm.me>
Co-authored-by: Dragory <2606411+Dragory@users.noreply.github.com>
This commit is contained in:
parent
293115af22
commit
06877e90cc
476 changed files with 2965 additions and 3251 deletions
|
@ -1,6 +1,5 @@
|
|||
import { Permissions, Snowflake } from "discord.js";
|
||||
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { nonNullish, unique } from "../../../utils";
|
||||
import { canAssignRole } from "../../../utils/canAssignRole";
|
||||
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
||||
|
@ -10,7 +9,7 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
|||
import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
|
||||
import { automodAction } from "../helpers";
|
||||
|
||||
const p = Permissions.FLAGS;
|
||||
const p = PermissionFlagsBits;
|
||||
|
||||
export const AddRolesAction = automodAction({
|
||||
configType: t.array(t.string),
|
||||
|
@ -20,7 +19,7 @@ export const AddRolesAction = automodAction({
|
|||
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||
|
||||
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
||||
const missingPermissions = getMissingPermissions(me.permissions, p.ManageRoles);
|
||||
if (missingPermissions) {
|
||||
const logs = pluginData.getPlugin(LogsPlugin);
|
||||
logs.logBotAlert({
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
|
||||
export const AddToCounterAction = automodAction({
|
||||
configType: t.type({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Snowflake, TextChannel, ThreadChannel } from "discord.js";
|
||||
import { Snowflake } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { erisAllowedMentionsToDjsMentionOptions } from "src/utils/erisAllowedMentionsToDjsMentionOptions";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
|
@ -9,21 +9,19 @@ import {
|
|||
TemplateSafeValueContainer,
|
||||
} from "../../../templateFormatter";
|
||||
import {
|
||||
createChunkedMessage,
|
||||
chunkMessageLines,
|
||||
isTruthy,
|
||||
messageLink,
|
||||
stripObjectToScalars,
|
||||
tAllowedMentions,
|
||||
tNormalizedNullOptional,
|
||||
isTruthy,
|
||||
verboseChannelMention,
|
||||
validateAndParseMessageContent,
|
||||
chunkMessageLines,
|
||||
verboseChannelMention,
|
||||
} from "../../../utils";
|
||||
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
||||
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||
import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
import { TemplateSafeUser, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
||||
import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin";
|
||||
|
||||
export const AlertAction = automodAction({
|
||||
configType: t.type({
|
||||
|
@ -38,7 +36,7 @@ export const AlertAction = automodAction({
|
|||
const channel = pluginData.guild.channels.cache.get(actionConfig.channel as Snowflake);
|
||||
const logs = pluginData.getPlugin(LogsPlugin);
|
||||
|
||||
if (channel?.isText()) {
|
||||
if (channel?.isTextBased()) {
|
||||
const text = actionConfig.text;
|
||||
const theMessageLink =
|
||||
contexts[0].message && messageLink(pluginData.guild.id, contexts[0].message.channel_id, contexts[0].message.id);
|
||||
|
@ -96,7 +94,7 @@ export const AlertAction = automodAction({
|
|||
const chunks = chunkMessageLines(rendered);
|
||||
for (const chunk of chunks) {
|
||||
await poster.sendMessage(channel, {
|
||||
content: rendered,
|
||||
content: chunk,
|
||||
allowedMentions: erisAllowedMentionsToDjsMentionOptions(actionConfig.allowed_mentions),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ThreadChannel } from "discord.js";
|
||||
import { AnyThreadChannel } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { noop } from "../../../utils";
|
||||
import { automodAction } from "../helpers";
|
||||
|
@ -11,7 +11,7 @@ export const ArchiveThreadAction = automodAction({
|
|||
const threads = contexts
|
||||
.filter((c) => 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) {
|
||||
await thread.setArchived().catch(noop);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { nonNullish, unique } from "../../../utils";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
|
|
|
@ -1,20 +1,72 @@
|
|||
import { Permissions, PermissionString } from "discord.js";
|
||||
import { PermissionsBitField, PermissionsString } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { automodAction } from "../helpers";
|
||||
import { tNullable, isValidSnowflake, tPartialDictionary } from "../../../utils";
|
||||
import { noop } from "knub/dist/utils";
|
||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
||||
import { isValidSnowflake, noop, tNullable, tPartialDictionary } from "../../../utils";
|
||||
import {
|
||||
guildToTemplateSafeGuild,
|
||||
savedMessageToTemplateSafeSavedMessage,
|
||||
userToTemplateSafeUser,
|
||||
} from "../../../utils/templateSafeObjects";
|
||||
import { automodAction } from "../helpers";
|
||||
|
||||
type LegacyPermMap = Record<string, keyof (typeof PermissionsBitField)["Flags"]>;
|
||||
const legacyPermMap = {
|
||||
CREATE_INSTANT_INVITE: "CreateInstantInvite",
|
||||
KICK_MEMBERS: "KickMembers",
|
||||
BAN_MEMBERS: "BanMembers",
|
||||
ADMINISTRATOR: "Administrator",
|
||||
MANAGE_CHANNELS: "ManageChannels",
|
||||
MANAGE_GUILD: "ManageGuild",
|
||||
ADD_REACTIONS: "AddReactions",
|
||||
VIEW_AUDIT_LOG: "ViewAuditLog",
|
||||
PRIORITY_SPEAKER: "PrioritySpeaker",
|
||||
STREAM: "Stream",
|
||||
VIEW_CHANNEL: "ViewChannel",
|
||||
SEND_MESSAGES: "SendMessages",
|
||||
SEND_TTSMESSAGES: "SendTTSMessages",
|
||||
MANAGE_MESSAGES: "ManageMessages",
|
||||
EMBED_LINKS: "EmbedLinks",
|
||||
ATTACH_FILES: "AttachFiles",
|
||||
READ_MESSAGE_HISTORY: "ReadMessageHistory",
|
||||
MENTION_EVERYONE: "MentionEveryone",
|
||||
USE_EXTERNAL_EMOJIS: "UseExternalEmojis",
|
||||
VIEW_GUILD_INSIGHTS: "ViewGuildInsights",
|
||||
CONNECT: "Connect",
|
||||
SPEAK: "Speak",
|
||||
MUTE_MEMBERS: "MuteMembers",
|
||||
DEAFEN_MEMBERS: "DeafenMembers",
|
||||
MOVE_MEMBERS: "MoveMembers",
|
||||
USE_VAD: "UseVAD",
|
||||
CHANGE_NICKNAME: "ChangeNickname",
|
||||
MANAGE_NICKNAMES: "ManageNicknames",
|
||||
MANAGE_ROLES: "ManageRoles",
|
||||
MANAGE_WEBHOOKS: "ManageWebhooks",
|
||||
MANAGE_EMOJIS_AND_STICKERS: "ManageEmojisAndStickers",
|
||||
USE_APPLICATION_COMMANDS: "UseApplicationCommands",
|
||||
REQUEST_TO_SPEAK: "RequestToSpeak",
|
||||
MANAGE_EVENTS: "ManageEvents",
|
||||
MANAGE_THREADS: "ManageThreads",
|
||||
CREATE_PUBLIC_THREADS: "CreatePublicThreads",
|
||||
CREATE_PRIVATE_THREADS: "CreatePrivateThreads",
|
||||
USE_EXTERNAL_STICKERS: "UseExternalStickers",
|
||||
SEND_MESSAGES_IN_THREADS: "SendMessagesInThreads",
|
||||
USE_EMBEDDED_ACTIVITIES: "UseEmbeddedActivities",
|
||||
MODERATE_MEMBERS: "ModerateMembers",
|
||||
} satisfies LegacyPermMap;
|
||||
|
||||
const realToLegacyMap = Object.entries(legacyPermMap).reduce((map, pair) => {
|
||||
map[pair[1]] = pair[0];
|
||||
return map;
|
||||
}, {}) as Record<keyof typeof PermissionsBitField.Flags, keyof typeof legacyPermMap>;
|
||||
|
||||
export const ChangePermsAction = automodAction({
|
||||
configType: t.type({
|
||||
target: t.string,
|
||||
channel: tNullable(t.string),
|
||||
perms: tPartialDictionary(t.keyof(Permissions.FLAGS), tNullable(t.boolean)),
|
||||
perms: tPartialDictionary(
|
||||
t.union([t.keyof(PermissionsBitField.Flags), t.keyof(legacyPermMap)]),
|
||||
tNullable(t.boolean),
|
||||
),
|
||||
}),
|
||||
defaultConfig: {},
|
||||
|
||||
|
@ -52,13 +104,15 @@ export const ChangePermsAction = automodAction({
|
|||
const channel = pluginData.guild.channels.resolve(channelId);
|
||||
if (!channel || channel.isThread()) return;
|
||||
const overwrite = channel.permissionOverwrites.cache.find((pw) => pw.id === target);
|
||||
const allow = new Permissions(overwrite?.allow ?? 0n).serialize();
|
||||
const deny = new Permissions(overwrite?.deny ?? 0n).serialize();
|
||||
const newPerms: Partial<Record<PermissionString, boolean | null>> = {};
|
||||
const allow = new PermissionsBitField(overwrite?.allow ?? 0n).serialize();
|
||||
const deny = new PermissionsBitField(overwrite?.deny ?? 0n).serialize();
|
||||
const newPerms: Partial<Record<PermissionsString, boolean | null>> = {};
|
||||
|
||||
for (const key in allow) {
|
||||
if (typeof actionConfig.perms[key] !== "undefined") {
|
||||
newPerms[key] = actionConfig.perms[key];
|
||||
const legacyKey = realToLegacyMap[key];
|
||||
const configEntry = actionConfig.perms[key] ?? actionConfig.perms[legacyKey];
|
||||
if (typeof configEntry !== "undefined") {
|
||||
newPerms[key] = configEntry;
|
||||
continue;
|
||||
}
|
||||
if (allow[key]) {
|
||||
|
@ -86,11 +140,12 @@ export const ChangePermsAction = automodAction({
|
|||
|
||||
if (!role) return;
|
||||
|
||||
const perms = new Permissions(role.permissions).serialize();
|
||||
const perms = new PermissionsBitField(role.permissions).serialize();
|
||||
for (const key in actionConfig.perms) {
|
||||
perms[key] = actionConfig.perms[key];
|
||||
const realKey = legacyPermMap[key] ?? key;
|
||||
perms[realKey] = actionConfig.perms[key];
|
||||
}
|
||||
const permsArray = <PermissionString[]>Object.keys(perms).filter((key) => perms[key]);
|
||||
await role.setPermissions(new Permissions(permsArray)).catch(noop);
|
||||
const permsArray = <PermissionsString[]>Object.keys(perms).filter((key) => perms[key]);
|
||||
await role.setPermissions(new PermissionsBitField(permsArray)).catch(noop);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Snowflake, TextChannel } from "discord.js";
|
||||
import { GuildTextBasedChannel, Snowflake } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { noop } from "../../../utils";
|
||||
|
@ -32,7 +32,7 @@ export const CleanAction = automodAction({
|
|||
pluginData.state.logs.ignoreLog(LogType.MESSAGE_DELETE, id);
|
||||
}
|
||||
|
||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as TextChannel;
|
||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as GuildTextBasedChannel;
|
||||
await channel.bulkDelete(messageIds as Snowflake[]).catch(noop);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { isTruthy, stripObjectToScalars, unique } from "../../../utils";
|
||||
import { isTruthy, unique } from "../../../utils";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||
|
||||
export const LogAction = automodAction({
|
||||
configType: t.boolean,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
|
||||
import { convertDelayStringToMS, nonNullish, tDelayString, tNullable, unique } from "../../../utils";
|
||||
import { CaseArgs } from "../../Cases/types";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Permissions, Snowflake } from "discord.js";
|
||||
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { nonNullish, unique } from "../../../utils";
|
||||
import { canAssignRole } from "../../../utils/canAssignRole";
|
||||
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
||||
|
@ -10,7 +9,7 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
|||
import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
|
||||
import { automodAction } from "../helpers";
|
||||
|
||||
const p = Permissions.FLAGS;
|
||||
const p = PermissionFlagsBits;
|
||||
|
||||
export const RemoveRolesAction = automodAction({
|
||||
configType: t.array(t.string),
|
||||
|
@ -21,7 +20,7 @@ export const RemoveRolesAction = automodAction({
|
|||
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||
|
||||
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
||||
const missingPermissions = getMissingPermissions(me.permissions, p.ManageRoles);
|
||||
if (missingPermissions) {
|
||||
const logs = pluginData.getPlugin(LogsPlugin);
|
||||
logs.logBotAlert({
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { MessageOptions, Permissions, Snowflake, TextChannel, ThreadChannel, User } from "discord.js";
|
||||
import { GuildTextBasedChannel, MessageCreateOptions, PermissionsBitField, Snowflake, User } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
||||
import {
|
||||
convertDelayStringToMS,
|
||||
|
@ -14,10 +13,11 @@ import {
|
|||
verboseChannelMention,
|
||||
} from "../../../utils";
|
||||
import { hasDiscordPermissions } from "../../../utils/hasDiscordPermissions";
|
||||
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
||||
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
import { AutomodContext } from "../types";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
||||
|
||||
export const ReplyAction = automodAction({
|
||||
configType: t.union([
|
||||
|
@ -36,7 +36,7 @@ export const ReplyAction = automodAction({
|
|||
.filter((c) => c.message?.channel_id)
|
||||
.filter((c) => {
|
||||
const channel = pluginData.guild.channels.cache.get(c.message!.channel_id as Snowflake);
|
||||
return channel?.isText();
|
||||
return channel?.isTextBased();
|
||||
});
|
||||
|
||||
const contextsByChannelId = contextsWithTextChannels.reduce((map: Map<string, AutomodContext[]>, context) => {
|
||||
|
@ -63,16 +63,16 @@ export const ReplyAction = automodAction({
|
|||
const formatted =
|
||||
typeof actionConfig === "string"
|
||||
? await renderReplyText(actionConfig)
|
||||
: ((await renderRecursively(actionConfig.text, renderReplyText)) as MessageOptions);
|
||||
: ((await renderRecursively(actionConfig.text, renderReplyText)) as MessageCreateOptions);
|
||||
|
||||
if (formatted) {
|
||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as TextChannel;
|
||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as GuildTextBasedChannel;
|
||||
|
||||
// Check for basic Send Messages and View Channel permissions
|
||||
if (
|
||||
!hasDiscordPermissions(
|
||||
channel.permissionsFor(pluginData.client.user!.id),
|
||||
Permissions.FLAGS.SEND_MESSAGES | Permissions.FLAGS.VIEW_CHANNEL,
|
||||
PermissionsBitField.Flags.SendMessages | PermissionsBitField.Flags.ViewChannel,
|
||||
)
|
||||
) {
|
||||
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
||||
|
@ -84,7 +84,10 @@ export const ReplyAction = automodAction({
|
|||
// If the message is an embed, check for embed permissions
|
||||
if (
|
||||
typeof formatted !== "string" &&
|
||||
!hasDiscordPermissions(channel.permissionsFor(pluginData.client.user!.id), Permissions.FLAGS.EMBED_LINKS)
|
||||
!hasDiscordPermissions(
|
||||
channel.permissionsFor(pluginData.client.user!.id),
|
||||
PermissionsBitField.Flags.EmbedLinks,
|
||||
)
|
||||
) {
|
||||
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
||||
body: `Missing permissions to reply **with an embed** in ${verboseChannelMention(
|
||||
|
@ -96,7 +99,7 @@ export const ReplyAction = automodAction({
|
|||
|
||||
const messageContent = validateAndParseMessageContent(formatted);
|
||||
|
||||
const messageOpts: MessageOptions = {
|
||||
const messageOpts: MessageCreateOptions = {
|
||||
...messageContent,
|
||||
allowedMentions: {
|
||||
users: [user.id],
|
||||
|
@ -118,7 +121,7 @@ export const ReplyAction = automodAction({
|
|||
|
||||
if (typeof actionConfig === "object" && actionConfig.auto_delete) {
|
||||
const delay = convertDelayStringToMS(String(actionConfig.auto_delete))!;
|
||||
setTimeout(() => !replyMsg.deleted && replyMsg.delete().catch(noop), delay);
|
||||
setTimeout(() => replyMsg.deletable && replyMsg.delete().catch(noop), delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import * as t from "io-ts";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
|
||||
export const SetCounterAction = automodAction({
|
||||
configType: t.type({
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import { Snowflake, TextChannel } from "discord.js";
|
||||
import { ChannelType, GuildTextBasedChannel, Snowflake } from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { ChannelTypeStrings } from "src/types";
|
||||
import { LogType } from "../../../data/LogType";
|
||||
import { convertDelayStringToMS, isDiscordAPIError, tDelayString, tNullable } from "../../../utils";
|
||||
import { automodAction } from "../helpers";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { automodAction } from "../helpers";
|
||||
|
||||
export const SetSlowmodeAction = automodAction({
|
||||
configType: t.type({
|
||||
|
@ -23,29 +21,27 @@ export const SetSlowmodeAction = automodAction({
|
|||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake);
|
||||
|
||||
// Only text channels and text channels within categories support slowmodes
|
||||
if (!channel || !(channel.type === ChannelTypeStrings.TEXT || ChannelTypeStrings.CATEGORY)) {
|
||||
if (!channel || (!channel.isTextBased() && channel.type !== ChannelType.GuildCategory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const channelsToSlowmode: TextChannel[] = [];
|
||||
if (channel.type === ChannelTypeStrings.CATEGORY) {
|
||||
const channelsToSlowmode: GuildTextBasedChannel[] = [];
|
||||
if (channel.type === ChannelType.GuildCategory) {
|
||||
// Find all text channels within the category
|
||||
for (const ch of pluginData.guild.channels.cache.values()) {
|
||||
if (ch.parentId === channel.id && ch.type === ChannelTypeStrings.TEXT) {
|
||||
channelsToSlowmode.push(ch as TextChannel);
|
||||
if (ch.parentId === channel.id && ch.type === ChannelType.GuildText) {
|
||||
channelsToSlowmode.push(ch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channelsToSlowmode.push(channel as TextChannel);
|
||||
channelsToSlowmode.push(channel);
|
||||
}
|
||||
|
||||
const slowmodeSeconds = Math.ceil(slowmodeMs / 1000);
|
||||
|
||||
try {
|
||||
for (const chan of channelsToSlowmode) {
|
||||
await chan.edit({
|
||||
rateLimitPerUser: slowmodeSeconds,
|
||||
});
|
||||
await chan.setRateLimitPerUser(slowmodeSeconds);
|
||||
}
|
||||
} catch (e) {
|
||||
// Check for invalid form body -> indicates duration was too large
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import { GuildFeature, ThreadAutoArchiveDuration } from "discord-api-types/v9";
|
||||
import { TextChannel } from "discord.js";
|
||||
import {
|
||||
ChannelType,
|
||||
GuildFeature,
|
||||
GuildTextThreadCreateOptions,
|
||||
ThreadAutoArchiveDuration,
|
||||
ThreadChannel,
|
||||
} from "discord.js";
|
||||
import * as t from "io-ts";
|
||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
||||
import { ChannelTypeStrings } from "../../../types";
|
||||
import { convertDelayStringToMS, MINUTES, noop, tDelayString, tNullable } from "../../../utils";
|
||||
import { savedMessageToTemplateSafeSavedMessage, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||
import { automodAction } from "../helpers";
|
||||
|
@ -32,12 +36,11 @@ export const StartThreadAction = automodAction({
|
|||
const threads = contexts.filter((c) => {
|
||||
if (!c.message || !c.user) return false;
|
||||
const channel = pluginData.guild.channels.cache.get(c.message.channel_id);
|
||||
if (channel?.type !== ChannelTypeStrings.TEXT || !channel.isText()) return false; // for some reason the typing here for channel.type defaults to ThreadChannelTypes (?)
|
||||
if (channel?.type !== ChannelType.GuildText || !channel.isTextBased()) return false; // for some reason the typing here for channel.type defaults to ThreadChannelTypes (?)
|
||||
// check against max threads per channel
|
||||
if (actionConfig.limit_per_channel && actionConfig.limit_per_channel > 0) {
|
||||
const threadCount = channel.threads.cache.filter(
|
||||
(tr) =>
|
||||
tr.ownerId === pluginData.client.user!.id && !tr.deleted && !tr.archived && tr.parentId === channel.id,
|
||||
(tr) => tr.ownerId === pluginData.client.user!.id && !tr.archived && tr.parentId === channel.id,
|
||||
).size;
|
||||
if (threadCount >= actionConfig.limit_per_channel) return false;
|
||||
}
|
||||
|
@ -53,7 +56,9 @@ export const StartThreadAction = automodAction({
|
|||
: ThreadAutoArchiveDuration.OneHour;
|
||||
|
||||
for (const threadContext of threads) {
|
||||
const channel = pluginData.guild.channels.cache.get(threadContext.message!.channel_id) as TextChannel;
|
||||
const channel = pluginData.guild.channels.cache.get(threadContext.message!.channel_id);
|
||||
if (!channel || !("threads" in channel) || channel.type === ChannelType.GuildForum) continue;
|
||||
|
||||
const renderThreadName = async (str: string) =>
|
||||
renderTemplate(
|
||||
str,
|
||||
|
@ -63,20 +68,35 @@ export const StartThreadAction = automodAction({
|
|||
}),
|
||||
);
|
||||
const threadName = await renderThreadName(actionConfig.name ?? "{user.tag}s thread");
|
||||
const thread = await channel.threads
|
||||
.create({
|
||||
name: threadName,
|
||||
autoArchiveDuration: autoArchive,
|
||||
type:
|
||||
actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
||||
? ChannelTypeStrings.PRIVATE_THREAD
|
||||
: ChannelTypeStrings.PUBLIC_THREAD,
|
||||
startMessage:
|
||||
!actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
||||
? threadContext.message!.id
|
||||
: undefined,
|
||||
})
|
||||
.catch(noop);
|
||||
const threadOptions: GuildTextThreadCreateOptions<unknown> = {
|
||||
name: threadName,
|
||||
autoArchiveDuration: autoArchive,
|
||||
startMessage:
|
||||
!actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
||||
? threadContext.message!.id
|
||||
: undefined,
|
||||
};
|
||||
|
||||
let thread: ThreadChannel | undefined;
|
||||
if (channel.type === ChannelType.GuildNews) {
|
||||
thread = await channel.threads
|
||||
.create({
|
||||
...threadOptions,
|
||||
type: ChannelType.AnnouncementThread,
|
||||
})
|
||||
.catch(() => undefined);
|
||||
} else {
|
||||
thread = await channel.threads
|
||||
.create({
|
||||
...threadOptions,
|
||||
type: actionConfig.private ? ChannelType.PrivateThread : ChannelType.PublicThread,
|
||||
startMessage:
|
||||
!actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
||||
? threadContext.message!.id
|
||||
: undefined,
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
if (actionConfig.slowmode && thread) {
|
||||
const dur = Math.ceil(Math.max(convertDelayStringToMS(actionConfig.slowmode) ?? 0, 0) / 1000);
|
||||
if (dur > 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue