3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-11 20:55:01 +00:00

Finish preliminary rework, ready to test

This commit is contained in:
Dark 2021-06-02 04:07:50 +02:00
parent 57893e7f76
commit d0a1beb809
No known key found for this signature in database
GPG key ID: 2CD6ACB6B0A87B8A
177 changed files with 854 additions and 707 deletions

View file

@ -9,6 +9,7 @@ import { formatReasonWithAttachments } from "./formatReasonWithAttachments";
import { kickMember } from "./kickMember";
import { ignoreEvent } from "./ignoreEvent";
import { isBanned } from "./isBanned";
import { GuildMember, TextChannel } from "discord.js";
export async function actualKickMemberCmd(
pluginData: GuildPluginData<ModActionsPluginType>,
@ -16,7 +17,7 @@ export async function actualKickMemberCmd(
args: {
user: string;
reason: string;
mod: Member;
mod: GuildMember;
notify?: string;
"notify-channel"?: TextChannel;
clean?: boolean;
@ -81,7 +82,7 @@ export async function actualKickMemberCmd(
ignoreEvent(pluginData, IgnoredEventType.Ban, memberToKick.id);
try {
await memberToKick.ban(1, encodeURIComponent("kick -clean"));
await memberToKick.ban({ days: 1, reason: encodeURIComponent("kick -clean") });
} catch {
sendErrorMessage(pluginData, msg.channel, "Failed to ban the user to clean messages (-clean)");
}
@ -90,14 +91,14 @@ export async function actualKickMemberCmd(
ignoreEvent(pluginData, IgnoredEventType.Unban, memberToKick.id);
try {
await pluginData.guild.unbanMember(memberToKick.id, encodeURIComponent("kick -clean"));
await pluginData.guild.bans.remove(memberToKick.id, encodeURIComponent("kick -clean"));
} catch {
sendErrorMessage(pluginData, msg.channel, "Failed to unban the user after banning them (-clean)");
}
}
if (kickResult.status === "failed") {
msg.channel.createMessage(errorMessage(`Failed to kick user`));
msg.channel.send(errorMessage(`Failed to kick user`));
return;
}

View file

@ -9,6 +9,7 @@ import { MutesPlugin } from "../../Mutes/MutesPlugin";
import { readContactMethodsFromArgs } from "./readContactMethodsFromArgs";
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
import { logger } from "../../../logger";
import { User, Message, TextChannel, GuildMember } from "discord.js";
/**
* The actual function run by both !mute and !forcemute.
@ -17,16 +18,16 @@ import { logger } from "../../../logger";
export async function actualMuteUserCmd(
pluginData: GuildPluginData<ModActionsPluginType>,
user: User | UnknownUser,
msg: Message<GuildTextableChannel>,
args: { time?: number; reason?: string; mod: Member; notify?: string; "notify-channel"?: TextChannel },
msg: Message,
args: { time?: number; reason?: string; mod: GuildMember; notify?: string; "notify-channel"?: TextChannel },
) {
// The moderator who did the action is the message author or, if used, the specified -mod
let mod: Member = msg.member;
let mod: GuildMember = msg.member!;
let pp: User | null = null;
if (args.mod) {
if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) {
sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod");
sendErrorMessage(pluginData, msg.channel as TextChannel, "You don't have permission to use -mod");
return;
}
@ -35,7 +36,7 @@ export async function actualMuteUserCmd(
}
const timeUntilUnmute = args.time && humanizeDuration(args.time);
const reason = args.reason ? formatReasonWithAttachments(args.reason, msg.attachments) : undefined;
const reason = args.reason ? formatReasonWithAttachments(args.reason, msg.attachments.array()) : undefined;
let muteResult: MuteResult;
const mutesPlugin = pluginData.getPlugin(MutesPlugin);
@ -44,7 +45,7 @@ export async function actualMuteUserCmd(
try {
contactMethods = readContactMethodsFromArgs(args);
} catch (e) {
sendErrorMessage(pluginData, msg.channel, e.message);
sendErrorMessage(pluginData, msg.channel as TextChannel, e.message);
return;
}
@ -58,16 +59,16 @@ export async function actualMuteUserCmd(
});
} catch (e) {
if (e instanceof RecoverablePluginError && e.code === ERRORS.NO_MUTE_ROLE_IN_CONFIG) {
sendErrorMessage(pluginData, msg.channel, "Could not mute the user: no mute role set in config");
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not mute the user: no mute role set in config");
} else if (isDiscordRESTError(e) && e.code === 10007) {
sendErrorMessage(pluginData, msg.channel, "Could not mute the user: unknown member");
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not mute the user: unknown member");
} else {
logger.error(`Failed to mute user ${user.id}: ${e.stack}`);
if (user.id == null) {
// tslint-disable-next-line:no-console
console.trace("[DEBUG] Null user.id for mute");
}
sendErrorMessage(pluginData, msg.channel, "Could not mute the user");
sendErrorMessage(pluginData, msg.channel as TextChannel, "Could not mute the user");
}
return;
@ -102,5 +103,5 @@ export async function actualMuteUserCmd(
}
if (muteResult.notifyResult.text) response += ` (${muteResult.notifyResult.text})`;
sendSuccessMessage(pluginData, msg.channel, response);
sendSuccessMessage(pluginData, msg.channel as TextChannel, response);
}

View file

@ -6,12 +6,13 @@ import { sendErrorMessage, sendSuccessMessage, hasPermission } from "../../../pl
import { formatReasonWithAttachments } from "./formatReasonWithAttachments";
import { MutesPlugin } from "../../../plugins/Mutes/MutesPlugin";
import humanizeDuration from "humanize-duration";
import { User, Message, GuildMember, TextChannel } from "discord.js";
export async function actualUnmuteCmd(
pluginData: GuildPluginData<ModActionsPluginType>,
user: User | UnknownUser,
msg: Message,
args: { time?: number; reason?: string; mod?: Member },
args: { time?: number; reason?: string; mod?: GuildMember },
) {
// The moderator who did the action is the message author or, if used, the specified -mod
let mod = msg.author;
@ -19,7 +20,7 @@ export async function actualUnmuteCmd(
if (args.mod) {
if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg, channelId: msg.channel.id }))) {
sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod");
sendErrorMessage(pluginData, msg.channel as TextChannel, "You don't have permission to use -mod");
return;
}
@ -27,7 +28,7 @@ export async function actualUnmuteCmd(
pp = msg.author;
}
const reason = args.reason ? formatReasonWithAttachments(args.reason, msg.attachments) : undefined;
const reason = args.reason ? formatReasonWithAttachments(args.reason, msg.attachments.array()) : undefined;
const mutesPlugin = pluginData.getPlugin(MutesPlugin);
const result = await mutesPlugin.unmuteUser(user.id, args.time, {
@ -37,7 +38,7 @@ export async function actualUnmuteCmd(
});
if (!result) {
sendErrorMessage(pluginData, msg.channel, "User is not muted!");
sendErrorMessage(pluginData, msg.channel as TextChannel, "User is not muted!");
return;
}
@ -46,7 +47,7 @@ export async function actualUnmuteCmd(
const timeUntilUnmute = args.time && humanizeDuration(args.time);
sendSuccessMessage(
pluginData,
msg.channel,
msg.channel as TextChannel,
asSingleLine(`
Unmuting **${user.username}#${user.discriminator}**
in ${timeUntilUnmute} (Case #${result.case.case_number})
@ -55,7 +56,7 @@ export async function actualUnmuteCmd(
} else {
sendSuccessMessage(
pluginData,
msg.channel,
msg.channel as TextChannel,
asSingleLine(`
Unmuted **${user.username}#${user.discriminator}**
(Case #${result.case.case_number})

View file

@ -17,6 +17,7 @@ import { CasesPlugin } from "../../Cases/CasesPlugin";
import { CaseTypes } from "../../../data/CaseTypes";
import { logger } from "../../../logger";
import humanizeDuration from "humanize-duration";
import { DiscordAPIError, User } from "discord.js";
/**
* Ban the specified user id, whether or not they're actually on the server at the time. Generates a case.
@ -77,14 +78,13 @@ export async function banUserId(
ignoreEvent(pluginData, IgnoredEventType.Ban, userId);
try {
const deleteMessageDays = Math.min(30, Math.max(0, banOptions.deleteMessageDays ?? 1));
await pluginData.guild.banMember(
userId,
deleteMessageDays,
reason != null ? encodeURIComponent(reason) : undefined,
);
await pluginData.guild.bans.create(userId, {
days: deleteMessageDays,
reason: reason != null ? encodeURIComponent(reason) : undefined,
});
} catch (e) {
let errorMessage;
if (e instanceof DiscordRESTError) {
if (e instanceof DiscordAPIError) {
errorMessage = `API error ${e.code}: ${e.message}`;
} else {
logger.warn(`Error applying ban to ${userId}: ${e}`);

View file

@ -1,4 +1,6 @@
export function formatReasonWithAttachments(reason: string, attachments: Attachment[]) {
import { MessageAttachment } from "discord.js";
export function formatReasonWithAttachments(reason: string, attachments: MessageAttachment[]) {
const attachmentUrls = attachments.map(a => a.url);
return ((reason || "") + " " + attachmentUrls.join(" ")).trim();
}

View file

@ -1,6 +1,7 @@
import { GuildPluginData } from "knub";
import { ModActionsPluginType } from "../types";
import { UserNotificationMethod } from "../../../utils";
import { TextChannel } from "discord.js";
export function getDefaultContactMethods(
pluginData: GuildPluginData<ModActionsPluginType>,

View file

@ -4,6 +4,7 @@ import { isDiscordHTTPError, isDiscordRESTError, SECONDS, sleep } from "../../..
import { LogsPlugin } from "../../Logs/LogsPlugin";
import { LogType } from "../../../data/LogType";
import { hasDiscordPermissions } from "../../../utils/hasDiscordPermissions";
import { Permissions } from "discord.js";
export async function isBanned(
pluginData: GuildPluginData<ModActionsPluginType>,
@ -11,7 +12,7 @@ export async function isBanned(
timeout: number = 5 * SECONDS,
): Promise<boolean> {
const botMember = pluginData.guild.members.cache.get(pluginData.client.user!.id);
if (botMember && !hasDiscordPermissions(botMember.permissions, Constants.Permissions.banMembers)) {
if (botMember && !hasDiscordPermissions(botMember.permissions, Permissions.FLAGS.BAN_MEMBERS)) {
pluginData.getPlugin(LogsPlugin).log(LogType.BOT_ALERT, {
body: `Missing "Ban Members" permission to check for existing bans`,
});
@ -19,7 +20,7 @@ export async function isBanned(
}
try {
const potentialBan = await Promise.race([pluginData.guild.getBan(userId), sleep(timeout)]);
const potentialBan = await Promise.race([pluginData.guild.bans.fetch({ user: userId }), sleep(timeout)]);
return potentialBan != null;
} catch (e) {
if (isDiscordRESTError(e) && e.code === 10026) {

View file

@ -15,13 +15,14 @@ import { LogType } from "../../../data/LogType";
import { ignoreEvent } from "./ignoreEvent";
import { CaseTypes } from "../../../data/CaseTypes";
import { CasesPlugin } from "../../Cases/CasesPlugin";
import { GuildMember } from "discord.js";
/**
* Kick the specified server member. Generates a case.
*/
export async function kickMember(
pluginData: GuildPluginData<ModActionsPluginType>,
member: Member,
member: GuildMember,
reason?: string,
kickOptions: KickOptions = {},
): Promise<KickResult> {

View file

@ -30,7 +30,7 @@ export async function outdatedTempbansLoop(pluginData: GuildPluginData<ModAction
);
try {
ignoreEvent(pluginData, IgnoredEventType.Unban, tempban.user_id);
await pluginData.guild.unbanMember(tempban.user_id, reason != null ? encodeURIComponent(reason) : undefined);
await pluginData.guild.bans.remove(tempban.user_id, reason != null ? encodeURIComponent(reason) : undefined);
} catch (e) {
pluginData.state.serverLogs.log(LogType.BOT_ALERT, {
body: `Encountered an error trying to automatically unban ${tempban.user_id} after tempban timeout`,

View file

@ -1,3 +1,4 @@
import { TextChannel } from "discord.js";
import { disableUserNotificationStrings, UserNotificationMethod } from "../../../utils";
export function readContactMethodsFromArgs(args: {

View file

@ -1,3 +1,4 @@
import { Message, TextChannel } from "discord.js";
import { CaseTypes } from "../../../data/CaseTypes";
import { Case } from "../../../data/entities/Case";
import { LogType } from "../../../data/LogType";
@ -14,16 +15,16 @@ export async function updateCase(pluginData, msg: Message, args) {
}
if (!theCase) {
sendErrorMessage(pluginData, msg.channel, "Case not found");
sendErrorMessage(pluginData, msg.channel as TextChannel, "Case not found");
return;
}
if (!args.note && msg.attachments.length === 0) {
sendErrorMessage(pluginData, msg.channel, "Text or attachment required");
if (!args.note && msg.attachments.size === 0) {
sendErrorMessage(pluginData, msg.channel as TextChannel, "Text or attachment required");
return;
}
const note = formatReasonWithAttachments(args.note, msg.attachments);
const note = formatReasonWithAttachments(args.note, msg.attachments.array());
const casesPlugin = pluginData.getPlugin(CasesPlugin);
await casesPlugin.createCaseNote({
@ -39,5 +40,5 @@ export async function updateCase(pluginData, msg: Message, args) {
note,
});
sendSuccessMessage(pluginData, msg.channel, `Case \`#${theCase.case_number}\` updated`);
sendSuccessMessage(pluginData, msg.channel as TextChannel, `Case \`#${theCase.case_number}\` updated`);
}

View file

@ -10,15 +10,15 @@ import {
ucfirst,
UserNotificationResult,
} from "../../../utils";
import { waitForReaction } from "knub/dist/helpers";
import { CasesPlugin } from "../../Cases/CasesPlugin";
import { CaseTypes } from "../../../data/CaseTypes";
import { LogType } from "../../../data/LogType";
import { renderTemplate } from "../../../templateFormatter";
import { GuildMember } from "discord.js";
export async function warnMember(
pluginData: GuildPluginData<ModActionsPluginType>,
member: Member,
member: GuildMember,
reason: string,
warnOptions: WarnOptions = {},
): Promise<WarnResult> {
@ -42,13 +42,13 @@ export async function warnMember(
}
if (!notifyResult.success) {
if (warnOptions.retryPromptChannel && pluginData.guild.channels.has(warnOptions.retryPromptChannel.id)) {
const failedMsg = await warnOptions.retryPromptChannel.createMessage(
if (warnOptions.retryPromptChannel && pluginData.guild.channels.resolve(warnOptions.retryPromptChannel.id)) {
const failedMsg = await warnOptions.retryPromptChannel.send(
"Failed to message the user. Log the warning anyway?",
);
const reply = await waitForReaction(pluginData.client, failedMsg, ["✅", "❌"]);
const reply = false; //await waitForReaction(pluginData.client, failedMsg, ["✅", "❌"]); FIXME waiting on waitForButton
failedMsg.delete();
if (!reply || reply.name === "❌") {
if (!reply /*|| reply.name === "❌"*/) {
return {
status: "failed",
error: "Failed to message user",