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 {
|
import {
|
||||||
|
ChatInputCommandInteraction,
|
||||||
GuildMember,
|
GuildMember,
|
||||||
Message,
|
Message,
|
||||||
MessageCreateOptions,
|
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(
|
export async function sendSuccessMessage(
|
||||||
pluginData: AnyPluginData<any>,
|
pluginData: AnyPluginData<any>,
|
||||||
channel: TextBasedChannel,
|
context: TextBasedChannel | ChatInputCommandInteraction,
|
||||||
body: string,
|
body: string,
|
||||||
allowedMentions?: MessageMentionOptions,
|
allowedMentions?: MessageMentionOptions,
|
||||||
responseInteraction?: ModalSubmitInteraction,
|
responseInteraction?: ModalSubmitInteraction,
|
||||||
|
ephemeral = false,
|
||||||
): Promise<Message | undefined> {
|
): Promise<Message | undefined> {
|
||||||
const emoji = pluginData.fullConfig.success_emoji || undefined;
|
const emoji = pluginData.fullConfig.success_emoji || undefined;
|
||||||
const formattedBody = successMessage(body, emoji);
|
const formattedBody = successMessage(body, emoji);
|
||||||
|
@ -117,23 +125,44 @@ export async function sendSuccessMessage(
|
||||||
await responseInteraction
|
await responseInteraction
|
||||||
.editReply({ content: formattedBody, embeds: [], components: [] })
|
.editReply({ content: formattedBody, embeds: [], components: [] })
|
||||||
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
||||||
} else {
|
|
||||||
return channel
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isContextInteraction(context)) {
|
||||||
|
// noinspection TypeScriptValidateJSTypes
|
||||||
|
return context
|
||||||
.send({ ...content }) // Force line break
|
.send({ ...content }) // Force line break
|
||||||
.catch((err) => {
|
.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}`);
|
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||||
|
|
||||||
return undefined;
|
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(
|
export async function sendErrorMessage(
|
||||||
pluginData: AnyPluginData<any>,
|
pluginData: AnyPluginData<any>,
|
||||||
channel: TextBasedChannel,
|
context: TextBasedChannel | ChatInputCommandInteraction,
|
||||||
body: string,
|
body: string,
|
||||||
allowedMentions?: MessageMentionOptions,
|
allowedMentions?: MessageMentionOptions,
|
||||||
responseInteraction?: ModalSubmitInteraction,
|
responseInteraction?: ModalSubmitInteraction,
|
||||||
|
ephemeral = false,
|
||||||
): Promise<Message | undefined> {
|
): Promise<Message | undefined> {
|
||||||
const emoji = pluginData.fullConfig.error_emoji || undefined;
|
const emoji = pluginData.fullConfig.error_emoji || undefined;
|
||||||
const formattedBody = errorMessage(body, emoji);
|
const formattedBody = errorMessage(body, emoji);
|
||||||
|
@ -145,15 +174,34 @@ export async function sendErrorMessage(
|
||||||
await responseInteraction
|
await responseInteraction
|
||||||
.editReply({ content: formattedBody, embeds: [], components: [] })
|
.editReply({ content: formattedBody, embeds: [], components: [] })
|
||||||
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
.catch((err) => logger.error(`Interaction reply failed: ${err}`));
|
||||||
} else {
|
|
||||||
return channel
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isContextInteraction(context)) {
|
||||||
|
// noinspection TypeScriptValidateJSTypes
|
||||||
|
return context
|
||||||
.send({ ...content }) // Force line break
|
.send({ ...content }) // Force line break
|
||||||
.catch((err) => {
|
.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}`);
|
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||||
return undefined;
|
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>) {
|
export function getBaseUrl(pluginData: AnyPluginData<any>) {
|
||||||
|
|
|
@ -28,13 +28,14 @@ import { MassbanCmd } from "./commands/MassBanCmd";
|
||||||
import { MassunbanCmd } from "./commands/MassUnbanCmd";
|
import { MassunbanCmd } from "./commands/MassUnbanCmd";
|
||||||
import { MassmuteCmd } from "./commands/MassmuteCmd";
|
import { MassmuteCmd } from "./commands/MassmuteCmd";
|
||||||
import { MuteCmd } from "./commands/MuteCmd";
|
import { MuteCmd } from "./commands/MuteCmd";
|
||||||
import { NoteCmd } from "./commands/NoteCmd";
|
|
||||||
import { SoftbanCmd } from "./commands/SoftbanCommand";
|
import { SoftbanCmd } from "./commands/SoftbanCommand";
|
||||||
import { UnbanCmd } from "./commands/UnbanCmd";
|
import { UnbanCmd } from "./commands/UnbanCmd";
|
||||||
import { UnhideCaseCmd } from "./commands/UnhideCaseCmd";
|
import { UnhideCaseCmd } from "./commands/UnhideCaseCmd";
|
||||||
import { UnmuteCmd } from "./commands/UnmuteCmd";
|
import { UnmuteCmd } from "./commands/UnmuteCmd";
|
||||||
import { UpdateCmd } from "./commands/UpdateCmd";
|
import { UpdateCmd } from "./commands/UpdateCmd";
|
||||||
import { WarnCmd } from "./commands/WarnCmd";
|
import { WarnCmd } from "./commands/WarnCmd";
|
||||||
|
import { NoteMsgCmd } from "./commands/note/NoteMsgCmd";
|
||||||
|
import { NoteSlashCmd } from "./commands/note/NoteSlashCmd";
|
||||||
import { AuditLogEvents } from "./events/AuditLogEvents";
|
import { AuditLogEvents } from "./events/AuditLogEvents";
|
||||||
import { CreateBanCaseOnManualBanEvt } from "./events/CreateBanCaseOnManualBanEvt";
|
import { CreateBanCaseOnManualBanEvt } from "./events/CreateBanCaseOnManualBanEvt";
|
||||||
import { CreateUnbanCaseOnManualUnbanEvt } from "./events/CreateUnbanCaseOnManualUnbanEvt";
|
import { CreateUnbanCaseOnManualUnbanEvt } from "./events/CreateUnbanCaseOnManualUnbanEvt";
|
||||||
|
@ -52,7 +53,14 @@ import { offModActionsEvent } from "./functions/offModActionsEvent";
|
||||||
import { onModActionsEvent } from "./functions/onModActionsEvent";
|
import { onModActionsEvent } from "./functions/onModActionsEvent";
|
||||||
import { updateCase } from "./functions/updateCase";
|
import { updateCase } from "./functions/updateCase";
|
||||||
import { warnMember } from "./functions/warnMember";
|
import { warnMember } from "./functions/warnMember";
|
||||||
import { BanOptions, ConfigSchema, KickOptions, ModActionsPluginType, WarnOptions } from "./types";
|
import {
|
||||||
|
BanOptions,
|
||||||
|
ConfigSchema,
|
||||||
|
KickOptions,
|
||||||
|
ModActionsPluginType,
|
||||||
|
WarnOptions,
|
||||||
|
modActionsSlashGroup,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
config: {
|
config: {
|
||||||
|
@ -135,9 +143,18 @@ export const ModActionsPlugin = zeppelinGuildPlugin<ModActionsPluginType>()({
|
||||||
|
|
||||||
events: [CreateBanCaseOnManualBanEvt, CreateUnbanCaseOnManualUnbanEvt, PostAlertOnMemberJoinEvt, AuditLogEvents],
|
events: [CreateBanCaseOnManualBanEvt, CreateUnbanCaseOnManualUnbanEvt, PostAlertOnMemberJoinEvt, AuditLogEvents],
|
||||||
|
|
||||||
|
slashCommands: [
|
||||||
|
modActionsSlashGroup({
|
||||||
|
name: "mod",
|
||||||
|
description: "Moderation actions",
|
||||||
|
defaultMemberPermissions: "0",
|
||||||
|
subcommands: [{ type: "slash", ...NoteSlashCmd }],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
messageCommands: [
|
messageCommands: [
|
||||||
UpdateCmd,
|
UpdateCmd,
|
||||||
NoteCmd,
|
NoteMsgCmd,
|
||||||
WarnCmd,
|
WarnCmd,
|
||||||
MuteCmd,
|
MuteCmd,
|
||||||
ForcemuteCmd,
|
ForcemuteCmd,
|
||||||
|
|
|
@ -6,13 +6,13 @@ import { canActOn, hasPermission, sendErrorMessage, sendSuccessMessage } from ".
|
||||||
import { renderUserUsername, resolveMember, resolveUser } from "../../../utils";
|
import { renderUserUsername, resolveMember, resolveUser } from "../../../utils";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AddCaseCmd = modActionsCmd({
|
export const AddCaseCmd = modActionsMsgCmd({
|
||||||
trigger: "addcase",
|
trigger: "addcase",
|
||||||
permission: "can_addcase",
|
permission: "can_addcase",
|
||||||
description: "Add an arbitrary case to the specified user without taking any action",
|
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 { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||||
import { isBanned } from "../functions/isBanned";
|
import { isBanned } from "../functions/isBanned";
|
||||||
import { readContactMethodsFromArgs } from "../functions/readContactMethodsFromArgs";
|
import { readContactMethodsFromArgs } from "../functions/readContactMethodsFromArgs";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
|
@ -22,7 +22,7 @@ const opts = {
|
||||||
"delete-days": ct.number({ option: true, shortcut: "d" }),
|
"delete-days": ct.number({ option: true, shortcut: "d" }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BanCmd = modActionsCmd({
|
export const BanCmd = modActionsMsgCmd({
|
||||||
trigger: "ban",
|
trigger: "ban",
|
||||||
permission: "can_ban",
|
permission: "can_ban",
|
||||||
description: "Ban or Tempban the specified member",
|
description: "Ban or Tempban the specified member",
|
||||||
|
@ -45,13 +45,12 @@ export const BanCmd = modActionsCmd({
|
||||||
|
|
||||||
async run({ pluginData, message: msg, args }) {
|
async run({ pluginData, message: msg, args }) {
|
||||||
const user = await resolveUser(pluginData.client, args.user);
|
const user = await resolveUser(pluginData.client, args.user);
|
||||||
|
|
||||||
if (!user.id) {
|
if (!user.id) {
|
||||||
sendErrorMessage(pluginData, msg.channel, `User not found`);
|
sendErrorMessage(pluginData, msg.channel, `User not found`);
|
||||||
return;
|
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);
|
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
|
// The moderator who did the action is the message author or, if used, the specified -mod
|
||||||
let mod = msg.member;
|
let mod = msg.member;
|
||||||
|
@ -64,85 +63,25 @@ export const BanCmd = modActionsCmd({
|
||||||
mod = args.mod;
|
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)
|
// acquire a lock because of the needed user-inputs below (if banned/not on server)
|
||||||
const lock = await pluginData.locks.acquire(banLock(user));
|
const lock = await pluginData.locks.acquire(banLock(user));
|
||||||
let forceban = false;
|
let forceban = false;
|
||||||
const existingTempban = await pluginData.state.tempbans.findExistingTempbanForUserId(user.id);
|
const existingTempban = await pluginData.state.tempbans.findExistingTempbanForUserId(user.id);
|
||||||
|
|
||||||
if (!memberToBan) {
|
if (!memberToBan) {
|
||||||
const banned = await isBanned(pluginData, user.id);
|
const banned = await isBanned(pluginData, user.id);
|
||||||
if (banned) {
|
|
||||||
// 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.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask the mod if we should update the existing ban
|
if (!banned) {
|
||||||
const reply = await waitForButtonConfirm(
|
|
||||||
msg.channel,
|
|
||||||
{ 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) {
|
|
||||||
await pluginData.state.tempbans.updateExpiryTime(user.id, time, mod.id);
|
|
||||||
} else {
|
|
||||||
await pluginData.state.tempbans.addTempban(user.id, time, mod.id);
|
|
||||||
}
|
|
||||||
const tempban = (await pluginData.state.tempbans.findExistingTempbanForUserId(user.id))!;
|
|
||||||
registerExpiringTempban(tempban);
|
|
||||||
} else if (existingTempban) {
|
|
||||||
clearExpiringTempban(existingTempban);
|
|
||||||
pluginData.state.tempbans.clear(user.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new case for the updated ban since we never stored the old case id and log the action
|
|
||||||
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
|
||||||
const createdCase = await casesPlugin.createCase({
|
|
||||||
modId: mod.id,
|
|
||||||
type: CaseTypes.Ban,
|
|
||||||
userId: user.id,
|
|
||||||
reason,
|
|
||||||
noteDetails: [`Ban updated to ${time ? humanizeDuration(time) : "indefinite"}`],
|
|
||||||
});
|
|
||||||
if (time) {
|
|
||||||
pluginData.getPlugin(LogsPlugin).logMemberTimedBan({
|
|
||||||
mod: mod.user,
|
|
||||||
user,
|
|
||||||
caseNumber: createdCase.case_number,
|
|
||||||
reason,
|
|
||||||
banTime: humanizeDuration(time),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
pluginData.getPlugin(LogsPlugin).logMemberBan({
|
|
||||||
mod: mod.user,
|
|
||||||
user,
|
|
||||||
caseNumber: createdCase.case_number,
|
|
||||||
reason,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sendSuccessMessage(
|
|
||||||
pluginData,
|
|
||||||
msg.channel,
|
|
||||||
`Ban updated to ${time ? "expire in " + humanizeDuration(time) + " from now" : "indefinite"}`,
|
|
||||||
);
|
|
||||||
lock.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Ask the mod if we should upgrade to a forceban as the user is not on the server
|
// Ask the mod if we should upgrade to a forceban as the user is not on the server
|
||||||
const reply = await waitForButtonConfirm(
|
const reply = await waitForButtonConfirm(
|
||||||
msg.channel,
|
msg.channel,
|
||||||
{ content: "User not on server, forceban instead?" },
|
{ content: "User not on server, forceban instead?" },
|
||||||
{ confirmText: "Yes", cancelText: "No", restrictToId: msg.member.id },
|
{ confirmText: "Yes", cancelText: "No", restrictToId: msg.member.id },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
sendErrorMessage(pluginData, msg.channel, "User not on server, ban cancelled by moderator");
|
sendErrorMessage(pluginData, msg.channel, "User not on server, ban cancelled by moderator");
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
@ -151,6 +90,73 @@ export const BanCmd = modActionsCmd({
|
||||||
forceban = true;
|
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.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask the mod if we should update the existing ban
|
||||||
|
const reply = await waitForButtonConfirm(
|
||||||
|
msg.channel,
|
||||||
|
{ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update or add new tempban / remove old tempban
|
||||||
|
if (time && time > 0) {
|
||||||
|
if (existingTempban) {
|
||||||
|
await pluginData.state.tempbans.updateExpiryTime(user.id, time, mod.id);
|
||||||
|
} else {
|
||||||
|
await pluginData.state.tempbans.addTempban(user.id, time, mod.id);
|
||||||
|
}
|
||||||
|
const tempban = (await pluginData.state.tempbans.findExistingTempbanForUserId(user.id))!;
|
||||||
|
registerExpiringTempban(tempban);
|
||||||
|
} else if (existingTempban) {
|
||||||
|
clearExpiringTempban(existingTempban);
|
||||||
|
pluginData.state.tempbans.clear(user.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new case for the updated ban since we never stored the old case id and log the action
|
||||||
|
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
||||||
|
const createdCase = await casesPlugin.createCase({
|
||||||
|
modId: mod.id,
|
||||||
|
type: CaseTypes.Ban,
|
||||||
|
userId: user.id,
|
||||||
|
reason,
|
||||||
|
noteDetails: [`Ban updated to ${time ? humanizeDuration(time) : "indefinite"}`],
|
||||||
|
});
|
||||||
|
if (time) {
|
||||||
|
pluginData.getPlugin(LogsPlugin).logMemberTimedBan({
|
||||||
|
mod: mod.user,
|
||||||
|
user,
|
||||||
|
caseNumber: createdCase.case_number,
|
||||||
|
reason,
|
||||||
|
banTime: humanizeDuration(time),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pluginData.getPlugin(LogsPlugin).logMemberBan({
|
||||||
|
mod: mod.user,
|
||||||
|
user,
|
||||||
|
caseNumber: createdCase.case_number,
|
||||||
|
reason,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSuccessMessage(
|
||||||
|
pluginData,
|
||||||
|
msg.channel,
|
||||||
|
`Ban updated to ${time ? "expire in " + humanizeDuration(time) + " from now" : "indefinite"}`,
|
||||||
|
);
|
||||||
|
lock.unlock();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we're allowed to ban this member if they are on the server
|
// Make sure we're allowed to ban this member if they are on the server
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { CasesPlugin } from "../../../plugins/Cases/CasesPlugin";
|
import { CasesPlugin } from "../../../plugins/Cases/CasesPlugin";
|
||||||
import { sendErrorMessage } from "../../../pluginUtils";
|
import { sendErrorMessage } from "../../../pluginUtils";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
export const CaseCmd = modActionsCmd({
|
export const CaseCmd = modActionsMsgCmd({
|
||||||
trigger: "case",
|
trigger: "case",
|
||||||
permission: "can_view",
|
permission: "can_view",
|
||||||
description: "Show information about a specific case",
|
description: "Show information about a specific case",
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { createPaginatedMessage } from "../../../utils/createPaginatedMessage";
|
||||||
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
|
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
|
||||||
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
|
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
|
||||||
import { CasesPlugin } from "../../Cases/CasesPlugin";
|
import { CasesPlugin } from "../../Cases/CasesPlugin";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.userId({ option: true }),
|
mod: ct.userId({ option: true }),
|
||||||
|
@ -15,7 +15,7 @@ const opts = {
|
||||||
|
|
||||||
const casesPerPage = 5;
|
const casesPerPage = 5;
|
||||||
|
|
||||||
export const CasesModCmd = modActionsCmd({
|
export const CasesModCmd = modActionsMsgCmd({
|
||||||
trigger: ["cases", "modlogs", "infractions"],
|
trigger: ["cases", "modlogs", "infractions"],
|
||||||
permission: "can_view",
|
permission: "can_view",
|
||||||
description: "Show the most recent 5 cases by the specified -mod",
|
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 { asyncMap } from "../../../utils/async";
|
||||||
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
|
import { getChunkedEmbedFields } from "../../../utils/getChunkedEmbedFields";
|
||||||
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
|
import { getGuildPrefix } from "../../../utils/getGuildPrefix";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
expand: ct.bool({ option: true, isSwitch: true, shortcut: "e" }),
|
expand: ct.bool({ option: true, isSwitch: true, shortcut: "e" }),
|
||||||
|
@ -21,7 +21,7 @@ const opts = {
|
||||||
unbans: ct.switchOption({ def: false, shortcut: "ub" }),
|
unbans: ct.switchOption({ def: false, shortcut: "ub" }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CasesUserCmd = modActionsCmd({
|
export const CasesUserCmd = modActionsMsgCmd({
|
||||||
trigger: ["cases", "modlogs"],
|
trigger: ["cases", "modlogs"],
|
||||||
permission: "can_view",
|
permission: "can_view",
|
||||||
description: "Show a list of cases the specified user has",
|
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 { CasesPlugin } from "../../Cases/CasesPlugin";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
|
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"],
|
trigger: ["delete_case", "deletecase"],
|
||||||
permission: "can_deletecase",
|
permission: "can_deletecase",
|
||||||
description: trimLines(`
|
description: trimLines(`
|
||||||
|
|
|
@ -9,13 +9,13 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
import { ignoreEvent } from "../functions/ignoreEvent";
|
||||||
import { isBanned } from "../functions/isBanned";
|
import { isBanned } from "../functions/isBanned";
|
||||||
import { IgnoredEventType, modActionsCmd } from "../types";
|
import { IgnoredEventType, modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ForcebanCmd = modActionsCmd({
|
export const ForcebanCmd = modActionsMsgCmd({
|
||||||
trigger: "forceban",
|
trigger: "forceban",
|
||||||
permission: "can_ban",
|
permission: "can_ban",
|
||||||
description: "Force-ban the specified user, even if they aren't on the server",
|
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 { canActOn, sendErrorMessage } from "../../../pluginUtils";
|
||||||
import { resolveMember, resolveUser } from "../../../utils";
|
import { resolveMember, resolveUser } from "../../../utils";
|
||||||
import { actualMuteUserCmd } from "../functions/actualMuteUserCmd";
|
import { actualMuteUserCmd } from "../functions/actualMuteUserCmd";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
|
@ -10,7 +10,7 @@ const opts = {
|
||||||
"notify-channel": ct.textChannel({ option: true }),
|
"notify-channel": ct.textChannel({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ForcemuteCmd = modActionsCmd({
|
export const ForcemuteCmd = modActionsMsgCmd({
|
||||||
trigger: "forcemute",
|
trigger: "forcemute",
|
||||||
permission: "can_mute",
|
permission: "can_mute",
|
||||||
description: "Force-mute the specified user, even if they're not on the server",
|
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 { canActOn, sendErrorMessage } from "../../../pluginUtils";
|
||||||
import { resolveMember, resolveUser } from "../../../utils";
|
import { resolveMember, resolveUser } from "../../../utils";
|
||||||
import { actualUnmuteCmd } from "../functions/actualUnmuteUserCmd";
|
import { actualUnmuteCmd } from "../functions/actualUnmuteUserCmd";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ForceUnmuteCmd = modActionsCmd({
|
export const ForceUnmuteCmd = modActionsMsgCmd({
|
||||||
trigger: "forceunmute",
|
trigger: "forceunmute",
|
||||||
permission: "can_mute",
|
permission: "can_mute",
|
||||||
description: "Force-unmute the specified user, even if they're not on the server",
|
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 { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
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"],
|
trigger: ["hide", "hidecase", "hide_case"],
|
||||||
permission: "can_hidecase",
|
permission: "can_hidecase",
|
||||||
description: "Hide the specified case so it doesn't appear in !cases or !info",
|
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 { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { actualKickMemberCmd } from "../functions/actualKickMemberCmd";
|
import { actualKickMemberCmd } from "../functions/actualKickMemberCmd";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
|
@ -9,7 +9,7 @@ const opts = {
|
||||||
clean: ct.bool({ option: true, isSwitch: true }),
|
clean: ct.bool({ option: true, isSwitch: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const KickCmd = modActionsCmd({
|
export const KickCmd = modActionsMsgCmd({
|
||||||
trigger: "kick",
|
trigger: "kick",
|
||||||
permission: "can_kick",
|
permission: "can_kick",
|
||||||
description: "Kick the specified member",
|
description: "Kick the specified member",
|
||||||
|
|
|
@ -11,9 +11,9 @@ import { DAYS, MINUTES, SECONDS, noop } from "../../../utils";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
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",
|
trigger: "massban",
|
||||||
permission: "can_massban",
|
permission: "can_massban",
|
||||||
description: "Mass-ban a list of user IDs",
|
description: "Mass-ban a list of user IDs",
|
||||||
|
|
|
@ -9,9 +9,9 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
import { ignoreEvent } from "../functions/ignoreEvent";
|
||||||
import { isBanned } from "../functions/isBanned";
|
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",
|
trigger: "massunban",
|
||||||
permission: "can_massunban",
|
permission: "can_massunban",
|
||||||
description: "Mass-unban a list of user IDs",
|
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 { MutesPlugin } from "../../../plugins/Mutes/MutesPlugin";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
export const MassmuteCmd = modActionsCmd({
|
export const MassmuteCmd = modActionsMsgCmd({
|
||||||
trigger: "massmute",
|
trigger: "massmute",
|
||||||
permission: "can_massmute",
|
permission: "can_massmute",
|
||||||
description: "Mass-mute a list of user IDs",
|
description: "Mass-mute a list of user IDs",
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { resolveMember, resolveUser } from "../../../utils";
|
||||||
import { waitForButtonConfirm } from "../../../utils/waitForInteraction";
|
import { waitForButtonConfirm } from "../../../utils/waitForInteraction";
|
||||||
import { actualMuteUserCmd } from "../functions/actualMuteUserCmd";
|
import { actualMuteUserCmd } from "../functions/actualMuteUserCmd";
|
||||||
import { isBanned } from "../functions/isBanned";
|
import { isBanned } from "../functions/isBanned";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
|
@ -12,7 +12,7 @@ const opts = {
|
||||||
"notify-channel": ct.textChannel({ option: true }),
|
"notify-channel": ct.textChannel({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MuteCmd = modActionsCmd({
|
export const MuteCmd = modActionsMsgCmd({
|
||||||
trigger: "mute",
|
trigger: "mute",
|
||||||
permission: "can_mute",
|
permission: "can_mute",
|
||||||
description: "Mute the specified member",
|
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 { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { trimPluginDescription } from "../../../utils";
|
import { trimPluginDescription } from "../../../utils";
|
||||||
import { actualKickMemberCmd } from "../functions/actualKickMemberCmd";
|
import { actualKickMemberCmd } from "../functions/actualKickMemberCmd";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
|
@ -9,7 +9,7 @@ const opts = {
|
||||||
"notify-channel": ct.textChannel({ option: true }),
|
"notify-channel": ct.textChannel({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SoftbanCmd = modActionsCmd({
|
export const SoftbanCmd = modActionsMsgCmd({
|
||||||
trigger: "softban",
|
trigger: "softban",
|
||||||
permission: "can_kick",
|
permission: "can_kick",
|
||||||
description: trimPluginDescription(`
|
description: trimPluginDescription(`
|
||||||
|
|
|
@ -9,13 +9,13 @@ import { resolveUser } from "../../../utils";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
import { formatReasonWithAttachments } from "../functions/formatReasonWithAttachments";
|
||||||
import { ignoreEvent } from "../functions/ignoreEvent";
|
import { ignoreEvent } from "../functions/ignoreEvent";
|
||||||
import { IgnoredEventType, modActionsCmd } from "../types";
|
import { IgnoredEventType, modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UnbanCmd = modActionsCmd({
|
export const UnbanCmd = modActionsMsgCmd({
|
||||||
trigger: "unban",
|
trigger: "unban",
|
||||||
permission: "can_unban",
|
permission: "can_unban",
|
||||||
description: "Unban the specified member",
|
description: "Unban the specified member",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
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"],
|
trigger: ["unhide", "unhidecase", "unhide_case"],
|
||||||
permission: "can_hidecase",
|
permission: "can_hidecase",
|
||||||
description: "Un-hide the specified case, making it appear in !cases and !info again",
|
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 { waitForButtonConfirm } from "../../../utils/waitForInteraction";
|
||||||
import { actualUnmuteCmd } from "../functions/actualUnmuteUserCmd";
|
import { actualUnmuteCmd } from "../functions/actualUnmuteUserCmd";
|
||||||
import { isBanned } from "../functions/isBanned";
|
import { isBanned } from "../functions/isBanned";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
mod: ct.member({ option: true }),
|
mod: ct.member({ option: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UnmuteCmd = modActionsCmd({
|
export const UnmuteCmd = modActionsMsgCmd({
|
||||||
trigger: "unmute",
|
trigger: "unmute",
|
||||||
permission: "can_mute",
|
permission: "can_mute",
|
||||||
description: "Unmute the specified member",
|
description: "Unmute the specified member",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { updateCase } from "../functions/updateCase";
|
import { updateCase } from "../functions/updateCase";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
export const UpdateCmd = modActionsCmd({
|
export const UpdateCmd = modActionsMsgCmd({
|
||||||
trigger: ["update", "reason"],
|
trigger: ["update", "reason"],
|
||||||
permission: "can_note",
|
permission: "can_note",
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -8,9 +8,9 @@ import { formatReasonWithAttachments } from "../functions/formatReasonWithAttach
|
||||||
import { isBanned } from "../functions/isBanned";
|
import { isBanned } from "../functions/isBanned";
|
||||||
import { readContactMethodsFromArgs } from "../functions/readContactMethodsFromArgs";
|
import { readContactMethodsFromArgs } from "../functions/readContactMethodsFromArgs";
|
||||||
import { warnMember } from "../functions/warnMember";
|
import { warnMember } from "../functions/warnMember";
|
||||||
import { modActionsCmd } from "../types";
|
import { modActionsMsgCmd } from "../types";
|
||||||
|
|
||||||
export const WarnCmd = modActionsCmd({
|
export const WarnCmd = modActionsMsgCmd({
|
||||||
trigger: "warn",
|
trigger: "warn",
|
||||||
permission: "can_warn",
|
permission: "can_warn",
|
||||||
description: "Send a warning to the specified user",
|
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 { GuildTextBasedChannel } from "discord.js";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand } from "knub";
|
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand, guildPluginSlashGroup } from "knub";
|
||||||
import { Queue } from "../../Queue";
|
import { Queue } from "../../Queue";
|
||||||
import { GuildCases } from "../../data/GuildCases";
|
import { GuildCases } from "../../data/GuildCases";
|
||||||
import { GuildLogs } from "../../data/GuildLogs";
|
import { GuildLogs } from "../../data/GuildLogs";
|
||||||
|
@ -147,5 +147,6 @@ export interface BanOptions {
|
||||||
|
|
||||||
export type ModActionType = "note" | "warn" | "mute" | "unmute" | "kick" | "ban" | "unban";
|
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>();
|
export const modActionsEvt = guildPluginEventListener<ModActionsPluginType>();
|
||||||
|
|
|
@ -53,8 +53,8 @@ export const guildPlugins: Array<ZeppelinGuildPluginBlueprint<any>> = [
|
||||||
PostPlugin,
|
PostPlugin,
|
||||||
ReactionRolesPlugin,
|
ReactionRolesPlugin,
|
||||||
MessageSaverPlugin,
|
MessageSaverPlugin,
|
||||||
// GuildMemberCachePlugin, // FIXME: New caching thing, or fix deadlocks with this plugin
|
|
||||||
ModActionsPlugin,
|
ModActionsPlugin,
|
||||||
|
// GuildMemberCachePlugin, // FIXME: New caching thing, or fix deadlocks with this plugin
|
||||||
NameHistoryPlugin,
|
NameHistoryPlugin,
|
||||||
RemindersPlugin,
|
RemindersPlugin,
|
||||||
RolesPlugin,
|
RolesPlugin,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue