mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-13 21:35:02 +00:00
WIP: Note Slash Command
This commit is contained in:
parent
91339bb01e
commit
dfb0e2c19d
29 changed files with 319 additions and 178 deletions
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
ChatInputCommandInteraction,
|
||||
GuildMember,
|
||||
Message,
|
||||
MessageCreateOptions,
|
||||
|
@ -100,12 +101,19 @@ export function makeIoTsConfigParser<Schema extends t.Type<any>>(schema: Schema)
|
|||
};
|
||||
}
|
||||
|
||||
function isContextInteraction(
|
||||
context: TextBasedChannel | ChatInputCommandInteraction,
|
||||
): context is ChatInputCommandInteraction {
|
||||
return "commandId" in context && !!context.commandId;
|
||||
}
|
||||
|
||||
export async function sendSuccessMessage(
|
||||
pluginData: AnyPluginData<any>,
|
||||
channel: TextBasedChannel,
|
||||
context: TextBasedChannel | ChatInputCommandInteraction,
|
||||
body: string,
|
||||
allowedMentions?: MessageMentionOptions,
|
||||
responseInteraction?: ModalSubmitInteraction,
|
||||
ephemeral = false,
|
||||
): Promise<Message | undefined> {
|
||||
const emoji = pluginData.fullConfig.success_emoji || undefined;
|
||||
const formattedBody = successMessage(body, emoji);
|
||||
|
@ -117,23 +125,44 @@ export async function sendSuccessMessage(
|
|||
await responseInteraction
|
||||
.editReply({ content: formattedBody, embeds: [], components: [] })
|
||||
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
||||
} else {
|
||||
return channel
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isContextInteraction(context)) {
|
||||
// noinspection TypeScriptValidateJSTypes
|
||||
return context
|
||||
.send({ ...content }) // Force line break
|
||||
.catch((err) => {
|
||||
const channelInfo = "guild" in channel ? `${channel.id} (${channel.guild.id})` : channel.id;
|
||||
const channelInfo = "guild" in context ? `${context.id} (${context.guild.id})` : context.id;
|
||||
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
const replyMethod = context.replied ? "followUp" : "reply";
|
||||
|
||||
return context[replyMethod]({
|
||||
content: formattedBody,
|
||||
embeds: [],
|
||||
components: [],
|
||||
fetchReply: true,
|
||||
ephemeral,
|
||||
}).catch((err) => {
|
||||
logger.error(`Context reply failed: ${err}`);
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
export async function sendErrorMessage(
|
||||
pluginData: AnyPluginData<any>,
|
||||
channel: TextBasedChannel,
|
||||
context: TextBasedChannel | ChatInputCommandInteraction,
|
||||
body: string,
|
||||
allowedMentions?: MessageMentionOptions,
|
||||
responseInteraction?: ModalSubmitInteraction,
|
||||
ephemeral = false,
|
||||
): Promise<Message | undefined> {
|
||||
const emoji = pluginData.fullConfig.error_emoji || undefined;
|
||||
const formattedBody = errorMessage(body, emoji);
|
||||
|
@ -145,15 +174,34 @@ export async function sendErrorMessage(
|
|||
await responseInteraction
|
||||
.editReply({ content: formattedBody, embeds: [], components: [] })
|
||||
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
||||
} else {
|
||||
return channel
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isContextInteraction(context)) {
|
||||
// noinspection TypeScriptValidateJSTypes
|
||||
return context
|
||||
.send({ ...content }) // Force line break
|
||||
.catch((err) => {
|
||||
const channelInfo = "guild" in channel ? `${channel.id} (${channel.guild.id})` : channel.id;
|
||||
const channelInfo = "guild" in context ? `${context.id} (${context.guild.id})` : context.id;
|
||||
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
const replyMethod = context.replied ? "followUp" : "reply";
|
||||
|
||||
return context[replyMethod]({
|
||||
content: formattedBody,
|
||||
embeds: [],
|
||||
components: [],
|
||||
fetchReply: true,
|
||||
ephemeral,
|
||||
}).catch((err) => {
|
||||
logger.error(`Context reply failed: ${err}`);
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
export function getBaseUrl(pluginData: AnyPluginData<any>) {
|
||||
|
|
|
@ -28,13 +28,14 @@ import { MassbanCmd } from "./commands/MassBanCmd";
|
|||
import { MassunbanCmd } from "./commands/MassUnbanCmd";
|
||||
import { MassmuteCmd } from "./commands/MassmuteCmd";
|
||||
import { MuteCmd } from "./commands/MuteCmd";
|
||||
import { NoteCmd } from "./commands/NoteCmd";
|
||||
import { SoftbanCmd } from "./commands/SoftbanCommand";
|
||||
import { UnbanCmd } from "./commands/UnbanCmd";
|
||||
import { UnhideCaseCmd } from "./commands/UnhideCaseCmd";
|
||||
import { UnmuteCmd } from "./commands/UnmuteCmd";
|
||||
import { UpdateCmd } from "./commands/UpdateCmd";
|
||||
import { WarnCmd } from "./commands/WarnCmd";
|
||||
import { NoteMsgCmd } from "./commands/note/NoteMsgCmd";
|
||||
import { NoteSlashCmd } from "./commands/note/NoteSlashCmd";
|
||||
import { AuditLogEvents } from "./events/AuditLogEvents";
|
||||
import { CreateBanCaseOnManualBanEvt } from "./events/CreateBanCaseOnManualBanEvt";
|
||||
import { CreateUnbanCaseOnManualUnbanEvt } from "./events/CreateUnbanCaseOnManualUnbanEvt";
|
||||
|
@ -52,7 +53,14 @@ import { offModActionsEvent } from "./functions/offModActionsEvent";
|
|||
import { onModActionsEvent } from "./functions/onModActionsEvent";
|
||||
import { updateCase } from "./functions/updateCase";
|
||||
import { warnMember } from "./functions/warnMember";
|
||||
import { BanOptions, ConfigSchema, KickOptions, ModActionsPluginType, WarnOptions } from "./types";
|
||||
import {
|
||||
BanOptions,
|
||||
ConfigSchema,
|
||||
KickOptions,
|
||||
ModActionsPluginType,
|
||||
WarnOptions,
|
||||
modActionsSlashGroup,
|
||||
} from "./types";
|
||||
|
||||
const defaultOptions = {
|
||||
config: {
|
||||
|
@ -135,9 +143,18 @@ export const ModActionsPlugin = zeppelinGuildPlugin<ModActionsPluginType>()({
|
|||
|
||||
events: [CreateBanCaseOnManualBanEvt, CreateUnbanCaseOnManualUnbanEvt, PostAlertOnMemberJoinEvt, AuditLogEvents],
|
||||
|
||||
slashCommands: [
|
||||
modActionsSlashGroup({
|
||||
name: "mod",
|
||||
description: "Moderation actions",
|
||||
defaultMemberPermissions: "0",
|
||||
subcommands: [{ type: "slash", ...NoteSlashCmd }],
|
||||
}),
|
||||
],
|
||||
|
||||
messageCommands: [
|
||||
UpdateCmd,
|
||||
NoteCmd,
|
||||
NoteMsgCmd,
|
||||
WarnCmd,
|
||||
MuteCmd,
|
||||
ForcemuteCmd,
|
||||
|
|
|
@ -6,13 +6,13 @@ import { canActOn, hasPermission, sendErrorMessage, sendSuccessMessage } from ".
|
|||
import { renderUserUsername, resolveMember, resolveUser } from "../../../utils";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
};
|
||||
|
||||
export const AddCaseCmd = modActionsCmd({
|
||||
export const AddCaseCmd = modActionsMsgCmd({
|
||||
trigger: "addcase",
|
||||
permission: "can_addcase",
|
||||
description: "Add an arbitrary case to the specified user without taking any action",
|
||||
|
|
|
@ -13,7 +13,7 @@ import { banUserId } from "../functions/banUserId";
|
|||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { isBanned } from "../functions/isBanned";
|
||||
import { readContactMethodsFromArgs } from "../functions/readContactMethodsFromArgs";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
|
@ -22,7 +22,7 @@ const opts = {
|
|||
"delete-days": ct.number({ option: true, shortcut: "d" }),
|
||||
};
|
||||
|
||||
export const BanCmd = modActionsCmd({
|
||||
export const BanCmd = modActionsMsgCmd({
|
||||
trigger: "ban",
|
||||
permission: "can_ban",
|
||||
description: "Ban or Tempban the specified member",
|
||||
|
@ -45,13 +45,12 @@ export const BanCmd = modActionsCmd({
|
|||
|
||||
async run({ pluginData, message: msg, args }) {
|
||||
const user = await resolveUser(pluginData.client, args.user);
|
||||
|
||||
if (!user.id) {
|
||||
sendErrorMessage(pluginData, msg.channel, `User not found`);
|
||||
return;
|
||||
}
|
||||
const time = args["time"] ? args["time"] : null;
|
||||
|
||||
const reason = formatReasonWithAttachments(args.reason, [...msg.attachments.values()]);
|
||||
const memberToBan = await resolveMember(pluginData.client, pluginData.guild, user.id);
|
||||
// The moderator who did the action is the message author or, if used, the specified -mod
|
||||
let mod = msg.member;
|
||||
|
@ -64,13 +63,34 @@ export const BanCmd = modActionsCmd({
|
|||
mod = args.mod;
|
||||
}
|
||||
|
||||
const time = args["time"] ? args["time"] : null;
|
||||
const reason = formatReasonWithAttachments(args.reason, [...msg.attachments.values()]);
|
||||
|
||||
// acquire a lock because of the needed user-inputs below (if banned/not on server)
|
||||
const lock = await pluginData.locks.acquire(banLock(user));
|
||||
let forceban = false;
|
||||
const existingTempban = await pluginData.state.tempbans.findExistingTempbanForUserId(user.id);
|
||||
|
||||
if (!memberToBan) {
|
||||
const banned = await isBanned(pluginData, user.id);
|
||||
if (banned) {
|
||||
|
||||
if (!banned) {
|
||||
// Ask the mod if we should upgrade to a forceban as the user is not on the server
|
||||
const reply = await waitForButtonConfirm(
|
||||
msg.channel,
|
||||
{ content: "User not on server, forceban instead?" },
|
||||
{ confirmText: "Yes", cancelText: "No", restrictToId: msg.member.id },
|
||||
);
|
||||
|
||||
if (!reply) {
|
||||
sendErrorMessage(pluginData, msg.channel, "User not on server, ban cancelled by moderator");
|
||||
lock.unlock();
|
||||
return;
|
||||
} else {
|
||||
forceban = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Abort if trying to ban user indefinitely if they are already banned indefinitely
|
||||
if (!existingTempban && !time) {
|
||||
sendErrorMessage(pluginData, msg.channel, `User is already banned indefinitely.`);
|
||||
|
@ -83,11 +103,13 @@ export const BanCmd = modActionsCmd({
|
|||
{ content: "Failed to message the user. Log the warning anyway?" },
|
||||
{ confirmText: "Yes", cancelText: "No", restrictToId: msg.member.id },
|
||||
);
|
||||
|
||||
if (!reply) {
|
||||
sendErrorMessage(pluginData, msg.channel, "User already banned, update cancelled by moderator");
|
||||
lock.unlock();
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
|
||||
// Update or add new tempban / remove old tempban
|
||||
if (time && time > 0) {
|
||||
if (existingTempban) {
|
||||
|
@ -136,22 +158,6 @@ export const BanCmd = modActionsCmd({
|
|||
lock.unlock();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Ask the mod if we should upgrade to a forceban as the user is not on the server
|
||||
const reply = await waitForButtonConfirm(
|
||||
msg.channel,
|
||||
{ content: "User not on server, forceban instead?" },
|
||||
{ confirmText: "Yes", cancelText: "No", restrictToId: msg.member.id },
|
||||
);
|
||||
if (!reply) {
|
||||
sendErrorMessage(pluginData, msg.channel, "User not on server, ban cancelled by moderator");
|
||||
lock.unlock();
|
||||
return;
|
||||
} else {
|
||||
forceban = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we're allowed to ban this member if they are on the server
|
||||
if (!forceban && !canActOn(pluginData, msg.member, memberToBan!)) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { CasesPlugin } from "../../../plugins/Cases/CasesPlugin";
|
||||
import { sendErrorMessage } from "../../../pluginUtils";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
export const CaseCmd = modActionsCmd({
|
||||
export const CaseCmd = modActionsMsgCmd({
|
||||
trigger: "case",
|
||||
permission: "can_view",
|
||||
description: "Show information about a specific case",
|
||||
|
|
|
@ -7,7 +7,7 @@ import { createPaginatedMessage } from "../../../utils/createPaginatedMessage";
|
|||
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
|
||||
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
|
||||
import { CasesPlugin } from "../../Cases/CasesPlugin";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.userId({ option: true }),
|
||||
|
@ -15,7 +15,7 @@ const opts = {
|
|||
|
||||
const casesPerPage = 5;
|
||||
|
||||
export const CasesModCmd = modActionsCmd({
|
||||
export const CasesModCmd = modActionsMsgCmd({
|
||||
trigger: ["cases", "modlogs", "infractions"],
|
||||
permission: "can_view",
|
||||
description: "Show the most recent 5 cases by the specified -mod",
|
||||
|
|
|
@ -7,7 +7,7 @@ import { UnknownUser, chunkArray, emptyEmbedValue, renderUserUsername, resolveUs
|
|||
import { asyncMap } from "../../../utils/async";
|
||||
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
|
||||
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
expand: ct.bool({ option: true, isSwitch: true, shortcut: "e" }),
|
||||
|
@ -21,7 +21,7 @@ const opts = {
|
|||
unbans: ct.switchOption({ def: false, shortcut: "ub" }),
|
||||
};
|
||||
|
||||
export const CasesUserCmd = modActionsCmd({
|
||||
export const CasesUserCmd = modActionsMsgCmd({
|
||||
trigger: ["cases", "modlogs"],
|
||||
permission: "can_view",
|
||||
description: "Show a list of cases the specified user has",
|
||||
|
|
|
@ -6,9 +6,9 @@ import { SECONDS, trimLines } from "../../../utils";
|
|||
import { CasesPlugin } from "../../Cases/CasesPlugin";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
export const DeleteCaseCmd = modActionsCmd({
|
||||
export const DeleteCaseCmd = modActionsMsgCmd({
|
||||
trigger: ["delete_case", "deletecase"],
|
||||
permission: "can_deletecase",
|
||||
description: trimLines(`
|
||||
|
|
|
@ -9,13 +9,13 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
|||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
||||
import { isBanned } from "../functions/isBanned";
|
||||
import { IgnoredEventType, modActionsCmd } from "../types";
|
||||
import { IgnoredEventType, modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
};
|
||||
|
||||
export const ForcebanCmd = modActionsCmd({
|
||||
export const ForcebanCmd = modActionsMsgCmd({
|
||||
trigger: "forceban",
|
||||
permission: "can_ban",
|
||||
description: "Force-ban the specified user, even if they aren't on the server",
|
||||
|
|
|
@ -2,7 +2,7 @@ import { commandTypeHelpers as ct } from "../../../commandTypes";
|
|||
import { canActOn, sendErrorMessage } from "../../../pluginUtils";
|
||||
import { resolveMember, resolveUser } from "../../../utils";
|
||||
import { actualMuteUserCmd } from "../functions/actualMuteUserCmd";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
|
@ -10,7 +10,7 @@ const opts = {
|
|||
"notify-channel": ct.textChannel({ option: true }),
|
||||
};
|
||||
|
||||
export const ForcemuteCmd = modActionsCmd({
|
||||
export const ForcemuteCmd = modActionsMsgCmd({
|
||||
trigger: "forcemute",
|
||||
permission: "can_mute",
|
||||
description: "Force-mute the specified user, even if they're not on the server",
|
||||
|
|
|
@ -2,13 +2,13 @@ import { commandTypeHelpers as ct } from "../../../commandTypes";
|
|||
import { canActOn, sendErrorMessage } from "../../../pluginUtils";
|
||||
import { resolveMember, resolveUser } from "../../../utils";
|
||||
import { actualUnmuteCmd } from "../functions/actualUnmuteUserCmd";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
};
|
||||
|
||||
export const ForceUnmuteCmd = modActionsCmd({
|
||||
export const ForceUnmuteCmd = modActionsMsgCmd({
|
||||
trigger: "forceunmute",
|
||||
permission: "can_mute",
|
||||
description: "Force-unmute the specified user, even if they're not on the server",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
export const HideCaseCmd = modActionsCmd({
|
||||
export const HideCaseCmd = modActionsMsgCmd({
|
||||
trigger: ["hide", "hidecase", "hide_case"],
|
||||
permission: "can_hidecase",
|
||||
description: "Hide the specified case so it doesn't appear in !cases or !info",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { actualKickMemberCmd } from "../functions/actualKickMemberCmd";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
|
@ -9,7 +9,7 @@ const opts = {
|
|||
clean: ct.bool({ option: true, isSwitch: true }),
|
||||
};
|
||||
|
||||
export const KickCmd = modActionsCmd({
|
||||
export const KickCmd = modActionsMsgCmd({
|
||||
trigger: "kick",
|
||||
permission: "can_kick",
|
||||
description: "Kick the specified member",
|
||||
|
|
|
@ -11,9 +11,9 @@ import { DAYS, MINUTES, SECONDS, noop } from "../../../utils";
|
|||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
||||
import { IgnoredEventType, modActionsCmd } from "../types";
|
||||
import { IgnoredEventType, modActionsMsgCmd } from "../types";
|
||||
|
||||
export const MassbanCmd = modActionsCmd({
|
||||
export const MassbanCmd = modActionsMsgCmd({
|
||||
trigger: "massban",
|
||||
permission: "can_massban",
|
||||
description: "Mass-ban a list of user IDs",
|
||||
|
|
|
@ -9,9 +9,9 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
|||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
||||
import { isBanned } from "../functions/isBanned";
|
||||
import { IgnoredEventType, modActionsCmd } from "../types";
|
||||
import { IgnoredEventType, modActionsMsgCmd } from "../types";
|
||||
|
||||
export const MassunbanCmd = modActionsCmd({
|
||||
export const MassunbanCmd = modActionsMsgCmd({
|
||||
trigger: "massunban",
|
||||
permission: "can_massunban",
|
||||
description: "Mass-unban a list of user IDs",
|
||||
|
|
|
@ -7,9 +7,9 @@ import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginU
|
|||
import { MutesPlugin } from "../../../plugins/Mutes/MutesPlugin";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
export const MassmuteCmd = modActionsCmd({
|
||||
export const MassmuteCmd = modActionsMsgCmd({
|
||||
trigger: "massmute",
|
||||
permission: "can_massmute",
|
||||
description: "Mass-mute a list of user IDs",
|
||||
|
|
|
@ -4,7 +4,7 @@ import { resolveMember, resolveUser } from "../../../utils";
|
|||
import { waitForButtonConfirm } from "../../../utils/waitForInteraction";
|
||||
import { actualMuteUserCmd } from "../functions/actualMuteUserCmd";
|
||||
import { isBanned } from "../functions/isBanned";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
|
@ -12,7 +12,7 @@ const opts = {
|
|||
"notify-channel": ct.textChannel({ option: true }),
|
||||
};
|
||||
|
||||
export const MuteCmd = modActionsCmd({
|
||||
export const MuteCmd = modActionsMsgCmd({
|
||||
trigger: "mute",
|
||||
permission: "can_mute",
|
||||
description: "Mute the specified member",
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { CaseTypes } from "../../../data/CaseTypes";
|
||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||
import { renderUserUsername, resolveUser } from "../../../utils";
|
||||
import { CasesPlugin } from "../../Cases/CasesPlugin";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { modActionsCmd } from "../types";
|
||||
|
||||
export const NoteCmd = modActionsCmd({
|
||||
trigger: "note",
|
||||
permission: "can_note",
|
||||
description: "Add a note to the specified user",
|
||||
|
||||
signature: {
|
||||
user: ct.string(),
|
||||
note: ct.string({ required: false, catchAll: true }),
|
||||
},
|
||||
|
||||
async run({ pluginData, message: msg, args }) {
|
||||
const user = await resolveUser(pluginData.client, args.user);
|
||||
if (!user.id) {
|
||||
sendErrorMessage(pluginData, msg.channel, `User not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.note && msg.attachments.size === 0) {
|
||||
sendErrorMessage(pluginData, msg.channel, "Text or attachment required");
|
||||
return;
|
||||
}
|
||||
|
||||
const userName = renderUserUsername(user);
|
||||
const reason = formatReasonWithAttachments(args.note, [...msg.attachments.values()]);
|
||||
|
||||
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
||||
const createdCase = await casesPlugin.createCase({
|
||||
userId: user.id,
|
||||
modId: msg.author.id,
|
||||
type: CaseTypes.Note,
|
||||
reason,
|
||||
});
|
||||
|
||||
pluginData.getPlugin(LogsPlugin).logMemberNote({
|
||||
mod: msg.author,
|
||||
user,
|
||||
caseNumber: createdCase.case_number,
|
||||
reason,
|
||||
});
|
||||
|
||||
sendSuccessMessage(pluginData, msg.channel, `Note added on **${userName}** (Case #${createdCase.case_number})`);
|
||||
|
||||
pluginData.state.events.emit("note", user.id, reason);
|
||||
},
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { trimPluginDescription } from "../../../utils";
|
||||
import { actualKickMemberCmd } from "../functions/actualKickMemberCmd";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
|
@ -9,7 +9,7 @@ const opts = {
|
|||
"notify-channel": ct.textChannel({ option: true }),
|
||||
};
|
||||
|
||||
export const SoftbanCmd = modActionsCmd({
|
||||
export const SoftbanCmd = modActionsMsgCmd({
|
||||
trigger: "softban",
|
||||
permission: "can_kick",
|
||||
description: trimPluginDescription(`
|
||||
|
|
|
@ -9,13 +9,13 @@ import { resolveUser } from "../../../utils";
|
|||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
||||
import { IgnoredEventType, modActionsCmd } from "../types";
|
||||
import { IgnoredEventType, modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
};
|
||||
|
||||
export const UnbanCmd = modActionsCmd({
|
||||
export const UnbanCmd = modActionsMsgCmd({
|
||||
trigger: "unban",
|
||||
permission: "can_unban",
|
||||
description: "Unban the specified member",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
export const UnhideCaseCmd = modActionsCmd({
|
||||
export const UnhideCaseCmd = modActionsMsgCmd({
|
||||
trigger: ["unhide", "unhidecase", "unhide_case"],
|
||||
permission: "can_hidecase",
|
||||
description: "Un-hide the specified case, making it appear in !cases and !info again",
|
||||
|
|
|
@ -5,13 +5,13 @@ import { resolveMember, resolveUser } from "../../../utils";
|
|||
import { waitForButtonConfirm } from "../../../utils/waitForInteraction";
|
||||
import { actualUnmuteCmd } from "../functions/actualUnmuteUserCmd";
|
||||
import { isBanned } from "../functions/isBanned";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
const opts = {
|
||||
mod: ct.member({ option: true }),
|
||||
};
|
||||
|
||||
export const UnmuteCmd = modActionsCmd({
|
||||
export const UnmuteCmd = modActionsMsgCmd({
|
||||
trigger: "unmute",
|
||||
permission: "can_mute",
|
||||
description: "Unmute the specified member",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||
import { updateCase } from "../functions/updateCase";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
export const UpdateCmd = modActionsCmd({
|
||||
export const UpdateCmd = modActionsMsgCmd({
|
||||
trigger: ["update", "reason"],
|
||||
permission: "can_note",
|
||||
description:
|
||||
|
|
|
@ -8,9 +8,9 @@ import { formatReasonWithAttachments } from "../functions/formatReasonWithAttach
|
|||
import { isBanned } from "../functions/isBanned";
|
||||
import { readContactMethodsFromArgs } from "../functions/readContactMethodsFromArgs";
|
||||
import { warnMember } from "../functions/warnMember";
|
||||
import { modActionsCmd } from "../types";
|
||||
import { modActionsMsgCmd } from "../types";
|
||||
|
||||
export const WarnCmd = modActionsCmd({
|
||||
export const WarnCmd = modActionsMsgCmd({
|
||||
trigger: "warn",
|
||||
permission: "can_warn",
|
||||
description: "Send a warning to the specified user",
|
||||
|
|
31
backend/src/plugins/ModActions/commands/note/NoteMsgCmd.ts
Normal file
31
backend/src/plugins/ModActions/commands/note/NoteMsgCmd.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { commandTypeHelpers as ct } from "../../../../commandTypes";
|
||||
import { sendErrorMessage } from "../../../../pluginUtils";
|
||||
import { resolveUser } from "../../../../utils";
|
||||
import { actualNoteCmd } from "../../functions/actualNoteCmd";
|
||||
import { modActionsMsgCmd } from "../../types";
|
||||
|
||||
export const NoteMsgCmd = modActionsMsgCmd({
|
||||
trigger: "note",
|
||||
permission: "can_note",
|
||||
description: "Add a note to the specified user",
|
||||
|
||||
signature: {
|
||||
user: ct.string(),
|
||||
note: ct.string({ required: false, catchAll: true }),
|
||||
},
|
||||
|
||||
async run({ pluginData, message: msg, args }) {
|
||||
const user = await resolveUser(pluginData.client, args.user);
|
||||
if (!user.id) {
|
||||
sendErrorMessage(pluginData, msg.channel, `User not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.note && msg.attachments.size === 0) {
|
||||
sendErrorMessage(pluginData, msg.channel, "Text or attachment required");
|
||||
return;
|
||||
}
|
||||
|
||||
actualNoteCmd(pluginData, msg.channel, msg.author, [...msg.attachments.values()], user, args.note || "");
|
||||
},
|
||||
});
|
45
backend/src/plugins/ModActions/commands/note/NoteSlashCmd.ts
Normal file
45
backend/src/plugins/ModActions/commands/note/NoteSlashCmd.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { ApplicationCommandOptionType, ChatInputCommandInteraction } from "discord.js";
|
||||
import { slashOptions } from "knub";
|
||||
import { sendErrorMessage } from "../../../../pluginUtils";
|
||||
import { actualNoteCmd } from "../../functions/actualNoteCmd";
|
||||
|
||||
export const NoteSlashCmd = {
|
||||
name: "note",
|
||||
description: "Add a note to the specified user",
|
||||
allowDms: false,
|
||||
configPermission: "can_note",
|
||||
|
||||
signature: [
|
||||
slashOptions.user({ name: "user", description: "The user to add a note to", required: true }),
|
||||
slashOptions.string({ name: "note", description: "The note to add to the user", required: false }),
|
||||
...new Array(10).fill(0).map((_, i) => {
|
||||
return {
|
||||
name: `attachment${i + 1}`,
|
||||
description: "An attachment to add to the note",
|
||||
type: ApplicationCommandOptionType.Attachment,
|
||||
required: false,
|
||||
resolveValue: (interaction: ChatInputCommandInteraction) => {
|
||||
return interaction.options.getAttachment(`attachment${i + 1}`);
|
||||
},
|
||||
getExtraAPIProps: () => ({}),
|
||||
};
|
||||
}),
|
||||
],
|
||||
|
||||
async run({ interaction, options, pluginData }) {
|
||||
const attachments = new Array(10)
|
||||
.fill(0)
|
||||
.map((_, i) => {
|
||||
return options[`attachment${i + 1}`];
|
||||
})
|
||||
.filter((a) => a);
|
||||
|
||||
if ((!options.note || options.note.trim() === "") && attachments.length < 1) {
|
||||
sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
actualNoteCmd(pluginData, interaction, interaction.user, attachments, options.user, options.note || "");
|
||||
},
|
||||
};
|
47
backend/src/plugins/ModActions/functions/actualNoteCmd.ts
Normal file
47
backend/src/plugins/ModActions/functions/actualNoteCmd.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { Attachment, ChatInputCommandInteraction, TextBasedChannel, User } from "discord.js";
|
||||
import { GuildPluginData } from "knub";
|
||||
import { CaseTypes } from "../../../data/CaseTypes";
|
||||
import { sendSuccessMessage } from "../../../pluginUtils";
|
||||
import { UnknownUser, renderUserUsername } from "../../../utils";
|
||||
import { CasesPlugin } from "../../Cases/CasesPlugin";
|
||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||
import { ModActionsPluginType } from "../types";
|
||||
import { formatReasonWithAttachments } from "./formatReasonWithAttachments";
|
||||
|
||||
export async function actualNoteCmd(
|
||||
pluginData: GuildPluginData<ModActionsPluginType>,
|
||||
context: TextBasedChannel | ChatInputCommandInteraction,
|
||||
author: User,
|
||||
attachments: Array<Attachment>,
|
||||
user: User | UnknownUser,
|
||||
note: string,
|
||||
) {
|
||||
const userName = renderUserUsername(user);
|
||||
const reason = formatReasonWithAttachments(note, attachments);
|
||||
|
||||
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
||||
const createdCase = await casesPlugin.createCase({
|
||||
userId: user.id,
|
||||
modId: author.id,
|
||||
type: CaseTypes.Note,
|
||||
reason,
|
||||
});
|
||||
|
||||
pluginData.getPlugin(LogsPlugin).logMemberNote({
|
||||
mod: author,
|
||||
user,
|
||||
caseNumber: createdCase.case_number,
|
||||
reason,
|
||||
});
|
||||
|
||||
sendSuccessMessage(
|
||||
pluginData,
|
||||
context,
|
||||
`Note added on **${userName}** (Case #${createdCase.case_number})`,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
|
||||
pluginData.state.events.emit("note", user.id, reason);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { GuildTextBasedChannel } from "discord.js";
|
||||
import { EventEmitter } from "events";
|
||||
import * as t from "io-ts";
|
||||
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand } from "knub";
|
||||
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand, guildPluginSlashGroup } from "knub";
|
||||
import { Queue } from "../../Queue";
|
||||
import { GuildCases } from "../../data/GuildCases";
|
||||
import { GuildLogs } from "../../data/GuildLogs";
|
||||
|
@ -147,5 +147,6 @@ export interface BanOptions {
|
|||
|
||||
export type ModActionType = "note" | "warn" | "mute" | "unmute" | "kick" | "ban" | "unban";
|
||||
|
||||
export const modActionsCmd = guildPluginMessageCommand<ModActionsPluginType>();
|
||||
export const modActionsMsgCmd = guildPluginMessageCommand<ModActionsPluginType>();
|
||||
export const modActionsSlashGroup = guildPluginSlashGroup<ModActionsPluginType>();
|
||||
export const modActionsEvt = guildPluginEventListener<ModActionsPluginType>();
|
||||
|
|
|
@ -53,8 +53,8 @@ export const guildPlugins: Array<ZeppelinGuildPluginBlueprint<any>> = [
|
|||
PostPlugin,
|
||||
ReactionRolesPlugin,
|
||||
MessageSaverPlugin,
|
||||
// GuildMemberCachePlugin, // FIXME: New caching thing, or fix deadlocks with this plugin
|
||||
ModActionsPlugin,
|
||||
// GuildMemberCachePlugin, // FIXME: New caching thing, or fix deadlocks with this plugin
|
||||
NameHistoryPlugin,
|
||||
RemindersPlugin,
|
||||
RolesPlugin,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue