zappyzep/backend/src/plugins/Automod/actions/reply.ts

107 lines
3.7 KiB
TypeScript
Raw Normal View History

2021-06-30 04:56:56 +02:00
import { MessageOptions, Permissions, Snowflake, TextChannel, User } from "discord.js";
import * as t from "io-ts";
2021-08-18 01:51:42 +03:00
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
import { LogType } from "../../../data/LogType";
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
import {
convertDelayStringToMS,
noop,
renderRecursively,
tDelayString,
tMessageContent,
tNullable,
unique,
verboseChannelMention,
} from "../../../utils";
import { hasDiscordPermissions } from "../../../utils/hasDiscordPermissions";
import { automodAction } from "../helpers";
import { AutomodContext } from "../types";
2021-08-18 01:51:42 +03:00
import { LogsPlugin } from "../../Logs/LogsPlugin";
export const ReplyAction = automodAction({
configType: t.union([
t.string,
t.type({
text: tMessageContent,
auto_delete: tNullable(t.union([tDelayString, t.number])),
}),
]),
defaultConfig: {},
async apply({ pluginData, contexts, actionConfig, ruleName }) {
const contextsWithTextChannels = contexts
.filter(c => c.message?.channel_id)
2021-06-30 04:56:56 +02:00
.filter(c => pluginData.guild.channels.cache.get(c.message!.channel_id as Snowflake) instanceof TextChannel);
const contextsByChannelId = contextsWithTextChannels.reduce((map: Map<string, AutomodContext[]>, context) => {
if (!map.has(context.message!.channel_id)) {
map.set(context.message!.channel_id, []);
}
map.get(context.message!.channel_id)!.push(context);
return map;
}, new Map());
for (const [channelId, _contexts] of contextsByChannelId.entries()) {
const users = unique(Array.from(new Set(_contexts.map(c => c.user).filter(Boolean)))) as User[];
const user = users[0];
const renderReplyText = async str =>
renderTemplate(
str,
new TemplateSafeValueContainer({
user: userToTemplateSafeUser(user),
}),
);
const formatted =
typeof actionConfig === "string"
? await renderReplyText(actionConfig)
: ((await renderRecursively(actionConfig.text, renderReplyText)) as MessageOptions);
if (formatted) {
2021-06-30 04:56:56 +02:00
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as TextChannel;
// 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,
)
) {
2021-08-18 01:51:42 +03:00
pluginData.getPlugin(LogsPlugin).logBotAlert({
body: `Missing permissions to reply in ${verboseChannelMention(channel)} in Automod rule \`${ruleName}\``,
});
continue;
}
// 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)
) {
2021-08-18 01:51:42 +03:00
pluginData.getPlugin(LogsPlugin).logBotAlert({
body: `Missing permissions to reply **with an embed** in ${verboseChannelMention(
channel,
)} in Automod rule \`${ruleName}\``,
});
continue;
}
const messageContent: MessageOptions = typeof formatted === "string" ? { content: formatted } : formatted;
const replyMsg = await channel.send({
...messageContent,
allowedMentions: {
users: [user.id],
},
});
if (typeof actionConfig === "object" && actionConfig.auto_delete) {
const delay = convertDelayStringToMS(String(actionConfig.auto_delete))!;
setTimeout(() => replyMsg.delete().catch(noop), delay);
}
}
}
},
});