3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-15 05:41:51 +00:00

More rework progress, mostly done up to ModActions

This commit is contained in:
Dark 2021-06-01 04:33:02 +02:00
parent 52839cc9f3
commit 57893e7f76
No known key found for this signature in database
GPG key ID: 2CD6ACB6B0A87B8A
38 changed files with 199 additions and 241 deletions

View file

@ -9,6 +9,7 @@ import { censorMessage } from "./censorMessage";
import escapeStringRegexp from "escape-string-regexp"; import escapeStringRegexp from "escape-string-regexp";
import { logger } from "../../../logger"; import { logger } from "../../../logger";
import { allowTimeout } from "../../../RegExpRunner"; import { allowTimeout } from "../../../RegExpRunner";
import { MessageEmbed, Invite } from "discord.js";
export async function applyFiltersToMsg( export async function applyFiltersToMsg(
pluginData: GuildPluginData<CensorPluginType>, pluginData: GuildPluginData<CensorPluginType>,
@ -20,7 +21,7 @@ export async function applyFiltersToMsg(
let messageContent = savedMessage.data.content || ""; let messageContent = savedMessage.data.content || "";
if (savedMessage.data.attachments) messageContent += " " + JSON.stringify(savedMessage.data.attachments); if (savedMessage.data.attachments) messageContent += " " + JSON.stringify(savedMessage.data.attachments);
if (savedMessage.data.embeds) { if (savedMessage.data.embeds) {
const embeds = (savedMessage.data.embeds as Embed[]).map(e => cloneDeep(e)); const embeds = (savedMessage.data.embeds as MessageEmbed[]).map(e => cloneDeep(e));
for (const embed of embeds) { for (const embed of embeds) {
if (embed.type === "video") { if (embed.type === "video") {
// Ignore video descriptions as they're not actually shown on the embed // Ignore video descriptions as they're not actually shown on the embed
@ -69,20 +70,20 @@ export async function applyFiltersToMsg(
} }
if (isGuildInvite(invite)) { if (isGuildInvite(invite)) {
if (inviteGuildWhitelist && !inviteGuildWhitelist.includes(invite.guild.id)) { if (inviteGuildWhitelist && !inviteGuildWhitelist.includes(invite.guild!.id)) {
censorMessage( censorMessage(
pluginData, pluginData,
savedMessage, savedMessage,
`invite guild (**${invite.guild.name}** \`${invite.guild.id}\`) not found in whitelist`, `invite guild (**${invite.guild!.name}** \`${invite.guild!.id}\`) not found in whitelist`,
); );
return true; return true;
} }
if (inviteGuildBlacklist && inviteGuildBlacklist.includes(invite.guild.id)) { if (inviteGuildBlacklist && inviteGuildBlacklist.includes(invite.guild!.id)) {
censorMessage( censorMessage(
pluginData, pluginData,
savedMessage, savedMessage,
`invite guild (**${invite.guild.name}** \`${invite.guild.id}\`) found in blacklist`, `invite guild (**${invite.guild!.name}** \`${invite.guild!.id}\`) found in blacklist`,
); );
return true; return true;
} }

View file

@ -4,6 +4,7 @@ import { SavedMessage } from "../../../data/entities/SavedMessage";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { stripObjectToScalars, resolveUser } from "../../../utils"; import { stripObjectToScalars, resolveUser } from "../../../utils";
import { disableCodeBlocks, deactivateMentions } from "knub/dist/helpers"; import { disableCodeBlocks, deactivateMentions } from "knub/dist/helpers";
import { TextChannel } from "discord.js";
export async function censorMessage( export async function censorMessage(
pluginData: GuildPluginData<CensorPluginType>, pluginData: GuildPluginData<CensorPluginType>,
@ -13,7 +14,8 @@ export async function censorMessage(
pluginData.state.serverLogs.ignoreLog(LogType.MESSAGE_DELETE, savedMessage.id); pluginData.state.serverLogs.ignoreLog(LogType.MESSAGE_DELETE, savedMessage.id);
try { try {
await pluginData.client.deleteMessage(savedMessage.channel_id, savedMessage.id, "Censored"); const channel = pluginData.guild.channels.resolve(savedMessage.channel_id) as TextChannel
await channel.messages.delete(savedMessage.id);
} catch { } catch {
return; return;
} }

View file

@ -51,7 +51,7 @@ export const ArchiveChannelCmd = channelArchiverCmd({
let previousId: string | undefined; let previousId: string | undefined;
const startTime = Date.now(); const startTime = Date.now();
const progressMsg = await msg.channel.createMessage("Creating archive..."); const progressMsg = await msg.channel.send("Creating archive...");
const progressUpdateInterval = setInterval(() => { const progressUpdateInterval = setInterval(() => {
const secondsSinceStart = Math.round((Date.now() - startTime) / 1000); const secondsSinceStart = Math.round((Date.now() - startTime) / 1000);
progressMsg progressMsg
@ -61,16 +61,16 @@ export const ArchiveChannelCmd = channelArchiverCmd({
while (archivedMessages < maxMessagesToArchive) { while (archivedMessages < maxMessagesToArchive) {
const messagesToFetch = Math.min(MAX_MESSAGES_PER_FETCH, maxMessagesToArchive - archivedMessages); const messagesToFetch = Math.min(MAX_MESSAGES_PER_FETCH, maxMessagesToArchive - archivedMessages);
const messages = await args.channel.getMessages(messagesToFetch, previousId); const messages = await args.channel.messages.fetch({ limit: messagesToFetch, before: previousId });
if (messages.length === 0) break; if (messages.size === 0) break;
for (const message of messages) { for (const message of messages.values()) {
const ts = moment.utc(message.timestamp).format("YYYY-MM-DD HH:mm:ss"); const ts = moment.utc(message.createdTimestamp).format("YYYY-MM-DD HH:mm:ss");
let content = `[${ts}] [${message.author.id}] [${message.author.username}#${ let content = `[${ts}] [${message.author.id}] [${message.author.username}#${
message.author.discriminator message.author.discriminator
}]: ${message.content || "<no text content>"}`; }]: ${message.content || "<no text content>"}`;
if (message.attachments.length) { if (message.attachments.size) {
if (args["attachment-channel"]) { if (args["attachment-channel"]) {
const rehostedAttachmentUrl = await rehostAttachment(message.attachments[0], args["attachment-channel"]); const rehostedAttachmentUrl = await rehostAttachment(message.attachments[0], args["attachment-channel"]);
content += `\n-- Attachment: ${rehostedAttachmentUrl}`; content += `\n-- Attachment: ${rehostedAttachmentUrl}`;
@ -104,9 +104,6 @@ export const ArchiveChannelCmd = channelArchiverCmd({
result += `\n\n${archiveLines.join("\n")}\n`; result += `\n\n${archiveLines.join("\n")}\n`;
progressMsg.delete().catch(noop); progressMsg.delete().catch(noop);
msg.channel.createMessage("Archive created!", { msg.channel.send({ content: "Archive created!", files: [{attachment: Buffer.from(result), name: `archive-${args.channel.name}-${moment.utc().format("YYYY-MM-DD-HH-mm-ss")}.txt`}], split: false });
file: Buffer.from(result),
name: `archive-${args.channel.name}-${moment.utc().format("YYYY-MM-DD-HH-mm-ss")}.txt`,
});
}, },
}); });

View file

@ -1,10 +1,11 @@
import { downloadFile } from "../../utils"; import { downloadFile } from "../../utils";
import fs from "fs"; import fs from "fs";
import { MessageAttachment, MessageOptions, TextChannel } from "discord.js";
const fsp = fs.promises; const fsp = fs.promises;
const MAX_ATTACHMENT_REHOST_SIZE = 1024 * 1024 * 8; const MAX_ATTACHMENT_REHOST_SIZE = 1024 * 1024 * 8;
export async function rehostAttachment(attachment: Attachment, targetChannel: TextChannel): Promise<string> { export async function rehostAttachment(attachment: MessageAttachment, targetChannel: TextChannel): Promise<string> {
if (attachment.size > MAX_ATTACHMENT_REHOST_SIZE) { if (attachment.size > MAX_ATTACHMENT_REHOST_SIZE) {
return "Attachment too big to rehost"; return "Attachment too big to rehost";
} }
@ -17,11 +18,9 @@ export async function rehostAttachment(attachment: Attachment, targetChannel: Te
} }
try { try {
const rehostMessage = await targetChannel.createMessage(`Rehost of attachment ${attachment.id}`, { const content: MessageOptions = { content: `Rehost of attachment ${attachment.id}`, files: [{ name: attachment.name ? attachment.name : undefined, attachment: await fsp.readFile(downloaded.path)}]}
name: attachment.filename, const rehostMessage = await targetChannel.send({ content, split: false });
file: await fsp.readFile(downloaded.path), return rehostMessage.attachments.values()[0].url;
});
return rehostMessage.attachments[0].url;
} catch { } catch {
return "Failed to rehost attachment"; return "Failed to rehost attachment";
} }

View file

@ -1,11 +1,9 @@
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint"; import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { CompanionChannelsPluginType, ConfigSchema, TCompanionChannelOpts } from "./types"; import { CompanionChannelsPluginType, ConfigSchema } from "./types";
import { VoiceChannelJoinEvt } from "./events/VoiceChannelJoinEvt";
import { VoiceChannelSwitchEvt } from "./events/VoiceChannelSwitchEvt";
import { VoiceChannelLeaveEvt } from "./events/VoiceChannelLeaveEvt";
import { trimPluginDescription } from "../../utils"; import { trimPluginDescription } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin"; import { LogsPlugin } from "../Logs/LogsPlugin";
import { CooldownManager } from "knub"; import { CooldownManager } from "knub";
import { VoiceStateUpdateEvt } from "./events/VoiceStateUpdateEvt";
const defaultOptions = { const defaultOptions = {
config: { config: {
@ -29,7 +27,7 @@ export const CompanionChannelsPlugin = zeppelinGuildPlugin<CompanionChannelsPlug
configSchema: ConfigSchema, configSchema: ConfigSchema,
defaultOptions, defaultOptions,
events: [VoiceChannelJoinEvt, VoiceChannelSwitchEvt, VoiceChannelLeaveEvt], events: [VoiceStateUpdateEvt],
beforeLoad(pluginData) { beforeLoad(pluginData) {
pluginData.state.errorCooldownManager = new CooldownManager(); pluginData.state.errorCooldownManager = new CooldownManager();

View file

@ -1,10 +0,0 @@
import { companionChannelsEvt } from "../types";
import { handleCompanionPermissions } from "../functions/handleCompanionPermissions";
import { stripObjectToScalars } from "../../../utils";
export const VoiceChannelJoinEvt = companionChannelsEvt({
event: "voiceChannelJoin",
listener({ pluginData, args: { member, newChannel } }) {
handleCompanionPermissions(pluginData, member.id, newChannel);
},
});

View file

@ -1,9 +0,0 @@
import { companionChannelsEvt } from "../types";
import { handleCompanionPermissions } from "../functions/handleCompanionPermissions";
export const VoiceChannelLeaveEvt = companionChannelsEvt({
event: "voiceChannelLeave",
listener({ pluginData, args: { member, oldChannel } }) {
handleCompanionPermissions(pluginData, member.id, null, oldChannel);
},
});

View file

@ -1,9 +0,0 @@
import { companionChannelsEvt } from "../types";
import { handleCompanionPermissions } from "../functions/handleCompanionPermissions";
export const VoiceChannelSwitchEvt = companionChannelsEvt({
event: "voiceChannelSwitch",
listener({ pluginData, args: { member, oldChannel, newChannel } }) {
handleCompanionPermissions(pluginData, member.id, newChannel, oldChannel);
},
});

View file

@ -0,0 +1,12 @@
import { companionChannelsEvt } from "../types";
import { handleCompanionPermissions } from "../functions/handleCompanionPermissions";
export const VoiceStateUpdateEvt = companionChannelsEvt({
event: "voiceStateUpdate",
listener({ pluginData, args: { oldState, newState } }) {
const oldChannel = oldState.channel;
const newChannel = newState.channel;
const memberId = newState.member ? newState.member.id : oldState.member!.id;
handleCompanionPermissions(pluginData, memberId, newChannel, oldChannel);
},
});

View file

@ -1,3 +1,4 @@
import { StageChannel, VoiceChannel } from "discord.js";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { CompanionChannelsPluginType, TCompanionChannelOpts } from "../types"; import { CompanionChannelsPluginType, TCompanionChannelOpts } from "../types";
@ -8,7 +9,7 @@ const defaultCompanionChannelOpts: Partial<TCompanionChannelOpts> = {
export async function getCompanionChannelOptsForVoiceChannelId( export async function getCompanionChannelOptsForVoiceChannelId(
pluginData: GuildPluginData<CompanionChannelsPluginType>, pluginData: GuildPluginData<CompanionChannelsPluginType>,
userId: string, userId: string,
voiceChannel: VoiceChannel, voiceChannel: VoiceChannel | StageChannel,
): Promise<TCompanionChannelOpts[]> { ): Promise<TCompanionChannelOpts[]> {
const config = await pluginData.config.getMatchingConfig({ userId, channelId: voiceChannel.id }); const config = await pluginData.config.getMatchingConfig({ userId, channelId: voiceChannel.id });
return Object.values(config.entries) return Object.values(config.entries)

View file

@ -5,6 +5,7 @@ import { GuildPluginData } from "knub";
import { isDiscordRESTError, MINUTES } from "../../../utils"; import { isDiscordRESTError, MINUTES } from "../../../utils";
import { LogsPlugin } from "../../Logs/LogsPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { VoiceChannel, TextChannel, Permissions, StageChannel } from "discord.js";
const ERROR_COOLDOWN_KEY = "errorCooldown"; const ERROR_COOLDOWN_KEY = "errorCooldown";
const ERROR_COOLDOWN = 5 * MINUTES; const ERROR_COOLDOWN = 5 * MINUTES;
@ -12,20 +13,8 @@ const ERROR_COOLDOWN = 5 * MINUTES;
export async function handleCompanionPermissions( export async function handleCompanionPermissions(
pluginData: GuildPluginData<CompanionChannelsPluginType>, pluginData: GuildPluginData<CompanionChannelsPluginType>,
userId: string, userId: string,
voiceChannel: VoiceChannel, voiceChannel: VoiceChannel | StageChannel | null,
oldChannel?: VoiceChannel, oldChannel?: VoiceChannel | StageChannel | null,
);
export async function handleCompanionPermissions(
pluginData: GuildPluginData<CompanionChannelsPluginType>,
userId: string,
voiceChannel: null,
oldChannel: VoiceChannel,
);
export async function handleCompanionPermissions(
pluginData: GuildPluginData<CompanionChannelsPluginType>,
userId: string,
voiceChannel: VoiceChannel | null,
oldChannel?: VoiceChannel,
) { ) {
if (pluginData.state.errorCooldownManager.isOnCooldown(ERROR_COOLDOWN_KEY)) { if (pluginData.state.errorCooldownManager.isOnCooldown(ERROR_COOLDOWN_KEY)) {
return; return;
@ -65,18 +54,16 @@ export async function handleCompanionPermissions(
for (const channelId of permsToDelete) { for (const channelId of permsToDelete) {
const channel = pluginData.guild.channels.cache.get(channelId); const channel = pluginData.guild.channels.cache.get(channelId);
if (!channel || !(channel instanceof TextChannel)) continue; if (!channel || !(channel instanceof TextChannel)) continue;
await channel.deletePermission(userId, `Companion Channel for ${oldChannel!.id} | User Left`); await channel.permissionOverwrites.get(userId)?.delete(`Companion Channel for ${oldChannel!.id} | User Left`);
} }
for (const [channelId, permissions] of permsToSet) { for (const [channelId, permissions] of permsToSet) {
const channel = pluginData.guild.channels.cache.get(channelId); const channel = pluginData.guild.channels.cache.get(channelId);
if (!channel || !(channel instanceof TextChannel)) continue; if (!channel || !(channel instanceof TextChannel)) continue;
await channel.editPermission( await channel.updateOverwrite(
userId, userId,
permissions, new Permissions(BigInt(permissions)).serialize(),
0, {reason: `Companion Channel for ${voiceChannel!.id} | User Joined`},
"member",
`Companion Channel for ${voiceChannel!.id} | User Joined`,
); );
} }
} catch (e) { } catch (e) {

View file

@ -2,10 +2,11 @@ import { typedGuildCommand } from "knub";
import { CountersPluginType } from "../types"; import { CountersPluginType } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { resolveChannel, waitForReply } from "knub/dist/helpers"; import { waitForReply } from "knub/dist/helpers";
import { resolveUser, UnknownUser } from "../../../utils"; import { resolveUser, UnknownUser } from "../../../utils";
import { changeCounterValue } from "../functions/changeCounterValue"; import { changeCounterValue } from "../functions/changeCounterValue";
import { TextChannel } from "discord.js";
export const AddCounterCmd = typedGuildCommand<CountersPluginType>()({ export const AddCounterCmd = typedGuildCommand<CountersPluginType>()({
trigger: ["counters add", "counter add", "addcounter"], trigger: ["counters add", "counter add", "addcounter"],
@ -66,14 +67,14 @@ export const AddCounterCmd = typedGuildCommand<CountersPluginType>()({
let channel = args.channel; let channel = args.channel;
if (!channel && counter.per_channel) { if (!channel && counter.per_channel) {
message.channel.createMessage(`Which channel's counter value would you like to add to?`); message.channel.send(`Which channel's counter value would you like to add to?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
return; return;
} }
const potentialChannel = resolveChannel(pluginData.guild, reply.content); const potentialChannel = pluginData.guild.channels.resolve(reply.content);
if (!potentialChannel || !(potentialChannel instanceof TextChannel)) { if (!potentialChannel || !(potentialChannel instanceof TextChannel)) {
sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling");
return; return;
@ -84,7 +85,7 @@ export const AddCounterCmd = typedGuildCommand<CountersPluginType>()({
let user = args.user; let user = args.user;
if (!user && counter.per_user) { if (!user && counter.per_user) {
message.channel.createMessage(`Which user's counter value would you like to add to?`); message.channel.send(`Which user's counter value would you like to add to?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
@ -102,7 +103,7 @@ export const AddCounterCmd = typedGuildCommand<CountersPluginType>()({
let amount = args.amount; let amount = args.amount;
if (!amount) { if (!amount) {
message.channel.createMessage("How much would you like to add to the counter's value?"); message.channel.send("How much would you like to add to the counter's value?");
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
@ -123,19 +124,19 @@ export const AddCounterCmd = typedGuildCommand<CountersPluginType>()({
const counterName = counter.name || args.counterName; const counterName = counter.name || args.counterName;
if (channel && user) { if (channel && user) {
message.channel.createMessage( message.channel.send(
`Added ${amount} to **${counterName}** for <@!${user.id}> in <#${channel.id}>. The value is now ${newValue}.`, `Added ${amount} to **${counterName}** for <@!${user.id}> in <#${channel.id}>. The value is now ${newValue}.`,
); );
} else if (channel) { } else if (channel) {
message.channel.createMessage( message.channel.send(
`Added ${amount} to **${counterName}** in <#${channel.id}>. The value is now ${newValue}.`, `Added ${amount} to **${counterName}** in <#${channel.id}>. The value is now ${newValue}.`,
); );
} else if (user) { } else if (user) {
message.channel.createMessage( message.channel.send(
`Added ${amount} to **${counterName}** for <@!${user.id}>. The value is now ${newValue}.`, `Added ${amount} to **${counterName}** for <@!${user.id}>. The value is now ${newValue}.`,
); );
} else { } else {
message.channel.createMessage(`Added ${amount} to **${counterName}**. The value is now ${newValue}.`); message.channel.send(`Added ${amount} to **${counterName}**. The value is now ${newValue}.`);
} }
}, },
}); });

View file

@ -41,7 +41,7 @@ export const CountersListCmd = typedGuildCommand<CountersPluginType>()({
hintLines.push(`Use \`${getGuildPrefix(pluginData)}counters reset_all <name>\` to reset a counter entirely`); hintLines.push(`Use \`${getGuildPrefix(pluginData)}counters reset_all <name>\` to reset a counter entirely`);
} }
message.channel.createMessage( message.channel.send(
trimMultilineString(` trimMultilineString(`
${counterLines.join("\n\n")} ${counterLines.join("\n\n")}

View file

@ -2,11 +2,8 @@ import { typedGuildCommand } from "knub";
import { CountersPluginType } from "../types"; import { CountersPluginType } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { resolveChannel, waitForReply } from "knub/dist/helpers";
import { confirm, MINUTES, noop, resolveUser, trimMultilineString, UnknownUser } from "../../../utils"; import { confirm, MINUTES, noop, trimMultilineString } from "../../../utils";
import { changeCounterValue } from "../functions/changeCounterValue";
import { setCounterValue } from "../functions/setCounterValue";
import { resetAllCounterValues } from "../functions/resetAllCounterValues"; import { resetAllCounterValues } from "../functions/resetAllCounterValues";
import { counterIdLock } from "../../../utils/lockNameHelpers"; import { counterIdLock } from "../../../utils/lockNameHelpers";
@ -49,7 +46,7 @@ export const ResetAllCounterValuesCmd = typedGuildCommand<CountersPluginType>()(
} }
const loadingMessage = await message.channel const loadingMessage = await message.channel
.createMessage(`Resetting counter **${counterName}**. This might take a while. Please don't reload the config.`) .send(`Resetting counter **${counterName}**. This might take a while. Please don't reload the config.`)
.catch(() => null); .catch(() => null);
const lock = await pluginData.locks.acquire(counterIdLock(counterId), 10 * MINUTES); const lock = await pluginData.locks.acquire(counterIdLock(counterId), 10 * MINUTES);

View file

@ -2,10 +2,11 @@ import { typedGuildCommand } from "knub";
import { CountersPluginType } from "../types"; import { CountersPluginType } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { resolveChannel, waitForReply } from "knub/dist/helpers"; import { waitForReply } from "knub/dist/helpers";
import { resolveUser, UnknownUser } from "../../../utils"; import { resolveUser, UnknownUser } from "../../../utils";
import { setCounterValue } from "../functions/setCounterValue"; import { setCounterValue } from "../functions/setCounterValue";
import { TextChannel } from "discord.js";
export const ResetCounterCmd = typedGuildCommand<CountersPluginType>()({ export const ResetCounterCmd = typedGuildCommand<CountersPluginType>()({
trigger: ["counters reset", "counter reset", "resetcounter"], trigger: ["counters reset", "counter reset", "resetcounter"],
@ -61,14 +62,14 @@ export const ResetCounterCmd = typedGuildCommand<CountersPluginType>()({
let channel = args.channel; let channel = args.channel;
if (!channel && counter.per_channel) { if (!channel && counter.per_channel) {
message.channel.createMessage(`Which channel's counter value would you like to reset?`); message.channel.send(`Which channel's counter value would you like to reset?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
return; return;
} }
const potentialChannel = resolveChannel(pluginData.guild, reply.content); const potentialChannel = pluginData.guild.channels.resolve(reply.content);
if (!potentialChannel || !(potentialChannel instanceof TextChannel)) { if (!potentialChannel || !(potentialChannel instanceof TextChannel)) {
sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling");
return; return;
@ -79,7 +80,7 @@ export const ResetCounterCmd = typedGuildCommand<CountersPluginType>()({
let user = args.user; let user = args.user;
if (!user && counter.per_user) { if (!user && counter.per_user) {
message.channel.createMessage(`Which user's counter value would you like to reset?`); message.channel.send(`Which user's counter value would you like to reset?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
@ -99,13 +100,13 @@ export const ResetCounterCmd = typedGuildCommand<CountersPluginType>()({
const counterName = counter.name || args.counterName; const counterName = counter.name || args.counterName;
if (channel && user) { if (channel && user) {
message.channel.createMessage(`Reset **${counterName}** for <@!${user.id}> in <#${channel.id}>`); message.channel.send(`Reset **${counterName}** for <@!${user.id}> in <#${channel.id}>`);
} else if (channel) { } else if (channel) {
message.channel.createMessage(`Reset **${counterName}** in <#${channel.id}>`); message.channel.send(`Reset **${counterName}** in <#${channel.id}>`);
} else if (user) { } else if (user) {
message.channel.createMessage(`Reset **${counterName}** for <@!${user.id}>`); message.channel.send(`Reset **${counterName}** for <@!${user.id}>`);
} else { } else {
message.channel.createMessage(`Reset **${counterName}**`); message.channel.send(`Reset **${counterName}**`);
} }
}, },
}); });

View file

@ -2,11 +2,11 @@ import { typedGuildCommand } from "knub";
import { CountersPluginType } from "../types"; import { CountersPluginType } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { resolveChannel, waitForReply } from "knub/dist/helpers"; import { waitForReply } from "knub/dist/helpers";
import { resolveUser, UnknownUser } from "../../../utils"; import { resolveUser, UnknownUser } from "../../../utils";
import { changeCounterValue } from "../functions/changeCounterValue";
import { setCounterValue } from "../functions/setCounterValue"; import { setCounterValue } from "../functions/setCounterValue";
import { TextChannel } from "discord.js";
export const SetCounterCmd = typedGuildCommand<CountersPluginType>()({ export const SetCounterCmd = typedGuildCommand<CountersPluginType>()({
trigger: ["counters set", "counter set", "setcounter"], trigger: ["counters set", "counter set", "setcounter"],
@ -67,14 +67,14 @@ export const SetCounterCmd = typedGuildCommand<CountersPluginType>()({
let channel = args.channel; let channel = args.channel;
if (!channel && counter.per_channel) { if (!channel && counter.per_channel) {
message.channel.createMessage(`Which channel's counter value would you like to change?`); message.channel.send(`Which channel's counter value would you like to change?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
return; return;
} }
const potentialChannel = resolveChannel(pluginData.guild, reply.content); const potentialChannel = pluginData.guild.channels.resolve(reply.content);
if (!potentialChannel || !(potentialChannel instanceof TextChannel)) { if (!potentialChannel || !(potentialChannel instanceof TextChannel)) {
sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling");
return; return;
@ -85,7 +85,7 @@ export const SetCounterCmd = typedGuildCommand<CountersPluginType>()({
let user = args.user; let user = args.user;
if (!user && counter.per_user) { if (!user && counter.per_user) {
message.channel.createMessage(`Which user's counter value would you like to change?`); message.channel.send(`Which user's counter value would you like to change?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
@ -103,7 +103,7 @@ export const SetCounterCmd = typedGuildCommand<CountersPluginType>()({
let value = args.value; let value = args.value;
if (!value) { if (!value) {
message.channel.createMessage("What would you like to set the counter's value to?"); message.channel.send("What would you like to set the counter's value to?");
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
@ -128,13 +128,13 @@ export const SetCounterCmd = typedGuildCommand<CountersPluginType>()({
const counterName = counter.name || args.counterName; const counterName = counter.name || args.counterName;
if (channel && user) { if (channel && user) {
message.channel.createMessage(`Set **${counterName}** for <@!${user.id}> in <#${channel.id}> to ${value}`); message.channel.send(`Set **${counterName}** for <@!${user.id}> in <#${channel.id}> to ${value}`);
} else if (channel) { } else if (channel) {
message.channel.createMessage(`Set **${counterName}** in <#${channel.id}> to ${value}`); message.channel.send(`Set **${counterName}** in <#${channel.id}> to ${value}`);
} else if (user) { } else if (user) {
message.channel.createMessage(`Set **${counterName}** for <@!${user.id}> to ${value}`); message.channel.send(`Set **${counterName}** for <@!${user.id}> to ${value}`);
} else { } else {
message.channel.createMessage(`Set **${counterName}** to ${value}`); message.channel.send(`Set **${counterName}** to ${value}`);
} }
}, },
}); });

View file

@ -2,9 +2,10 @@ import { typedGuildCommand } from "knub";
import { CountersPluginType } from "../types"; import { CountersPluginType } from "../types";
import { commandTypeHelpers as ct } from "../../../commandTypes"; import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { resolveChannel, waitForReply } from "knub/dist/helpers"; import { waitForReply } from "knub/dist/helpers";
import { resolveUser, UnknownUser } from "../../../utils"; import { resolveUser, UnknownUser } from "../../../utils";
import { TextChannel } from "discord.js";
export const ViewCounterCmd = typedGuildCommand<CountersPluginType>()({ export const ViewCounterCmd = typedGuildCommand<CountersPluginType>()({
trigger: ["counters view", "counter view", "viewcounter", "counter"], trigger: ["counters view", "counter view", "viewcounter", "counter"],
@ -60,14 +61,14 @@ export const ViewCounterCmd = typedGuildCommand<CountersPluginType>()({
let channel = args.channel; let channel = args.channel;
if (!channel && counter.per_channel) { if (!channel && counter.per_channel) {
message.channel.createMessage(`Which channel's counter value would you like to view?`); message.channel.send(`Which channel's counter value would you like to view?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
return; return;
} }
const potentialChannel = resolveChannel(pluginData.guild, reply.content); const potentialChannel = pluginData.guild.channels.resolve(reply.content);
if (!potentialChannel || !(potentialChannel instanceof TextChannel)) { if (!potentialChannel || !(potentialChannel instanceof TextChannel)) {
sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling");
return; return;
@ -78,7 +79,7 @@ export const ViewCounterCmd = typedGuildCommand<CountersPluginType>()({
let user = args.user; let user = args.user;
if (!user && counter.per_user) { if (!user && counter.per_user) {
message.channel.createMessage(`Which user's counter value would you like to view?`); message.channel.send(`Which user's counter value would you like to view?`);
const reply = await waitForReply(pluginData.client, message.channel, message.author.id); const reply = await waitForReply(pluginData.client, message.channel, message.author.id);
if (!reply || !reply.content) { if (!reply || !reply.content) {
sendErrorMessage(pluginData, message.channel, "Cancelling"); sendErrorMessage(pluginData, message.channel, "Cancelling");
@ -99,13 +100,13 @@ export const ViewCounterCmd = typedGuildCommand<CountersPluginType>()({
const counterName = counter.name || args.counterName; const counterName = counter.name || args.counterName;
if (channel && user) { if (channel && user) {
message.channel.createMessage(`**${counterName}** for <@!${user.id}> in <#${channel.id}> is ${finalValue}`); message.channel.send(`**${counterName}** for <@!${user.id}> in <#${channel.id}> is ${finalValue}`);
} else if (channel) { } else if (channel) {
message.channel.createMessage(`**${counterName}** in <#${channel.id}> is ${finalValue}`); message.channel.send(`**${counterName}** in <#${channel.id}> is ${finalValue}`);
} else if (user) { } else if (user) {
message.channel.createMessage(`**${counterName}** for <@!${user.id}> is ${finalValue}`); message.channel.send(`**${counterName}** for <@!${user.id}> is ${finalValue}`);
} else { } else {
message.channel.createMessage(`**${counterName}** is ${finalValue}`); message.channel.send(`**${counterName}** is ${finalValue}`);
} }
}, },
}); });

View file

@ -7,7 +7,7 @@ import { fillActiveAlertsList } from "./utils/fillAlertsList";
import { WhereCmd } from "./commands/WhereCmd"; import { WhereCmd } from "./commands/WhereCmd";
import { FollowCmd } from "./commands/FollowCmd"; import { FollowCmd } from "./commands/FollowCmd";
import { DeleteFollowCmd, ListFollowCmd } from "./commands/ListFollowCmd"; import { DeleteFollowCmd, ListFollowCmd } from "./commands/ListFollowCmd";
import { ChannelJoinAlertsEvt, ChannelLeaveAlertsEvt, ChannelSwitchAlertsEvt } from "./events/SendAlertsEvts"; import { VoiceStateUpdateAlertEvt } from "./events/SendAlertsEvts";
import { GuildBanRemoveAlertsEvt } from "./events/BanRemoveAlertsEvt"; import { GuildBanRemoveAlertsEvt } from "./events/BanRemoveAlertsEvt";
import { trimPluginDescription } from "../../utils"; import { trimPluginDescription } from "../../utils";
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
@ -53,9 +53,7 @@ export const LocateUserPlugin = zeppelinGuildPlugin<LocateUserPluginType>()({
// prettier-ignore // prettier-ignore
events: [ events: [
ChannelJoinAlertsEvt, VoiceStateUpdateAlertEvt,
ChannelSwitchAlertsEvt,
ChannelLeaveAlertsEvt,
GuildBanRemoveAlertsEvt GuildBanRemoveAlertsEvt
], ],

View file

@ -46,7 +46,7 @@ export const FollowCmd = locateUserCmd({
sendSuccessMessage( sendSuccessMessage(
pluginData, pluginData,
msg.channel, msg.channel,
`Every time ${args.member.mention} joins or switches VC in the next ${humanizeDuration( `Every time <@${args.member.id}> joins or switches VC in the next ${humanizeDuration(
time, time,
)} i will notify and move you.\nPlease make sure to be in a voice channel, otherwise i cannot move you!`, )} i will notify and move you.\nPlease make sure to be in a voice channel, otherwise i cannot move you!`,
); );
@ -54,7 +54,7 @@ export const FollowCmd = locateUserCmd({
sendSuccessMessage( sendSuccessMessage(
pluginData, pluginData,
msg.channel, msg.channel,
`Every time ${args.member.mention} joins or switches VC in the next ${humanizeDuration( `Every time <@${args.member.id}> joins or switches VC in the next ${humanizeDuration(
time, time,
)} i will notify you`, )} i will notify you`,
); );

View file

@ -14,6 +14,6 @@ export const WhereCmd = locateUserCmd({
}, },
async run({ message: msg, args, pluginData }) { async run({ message: msg, args, pluginData }) {
sendWhere(pluginData, args.member, msg.channel, `${msg.member.mention} | `); sendWhere(pluginData, args.member, msg.channel, `<@${msg.member.id}> | `);
}, },
}); });

View file

@ -4,7 +4,7 @@ export const GuildBanRemoveAlertsEvt = locateUserEvt({
event: "guildBanAdd", event: "guildBanAdd",
async listener(meta) { async listener(meta) {
const alerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.user.id); const alerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.ban.user.id);
alerts.forEach(alert => { alerts.forEach(alert => {
meta.pluginData.state.alerts.delete(alert.id); meta.pluginData.state.alerts.delete(alert.id);
}); });

View file

@ -1,38 +1,27 @@
import { TextChannel } from "discord.js";
import { locateUserEvt } from "../types"; import { locateUserEvt } from "../types";
import { sendAlerts } from "../utils/sendAlerts"; import { sendAlerts } from "../utils/sendAlerts";
export const ChannelJoinAlertsEvt = locateUserEvt({ export const VoiceStateUpdateAlertEvt = locateUserEvt({
event: "voiceChannelJoin", event: "voiceStateUpdate",
async listener(meta) { async listener(meta) {
if (meta.pluginData.state.usersWithAlerts.includes(meta.args.member.id)) { const memberId = meta.args.oldState.member ? meta.args.oldState.member.id : meta.args.newState.member!.id;
sendAlerts(meta.pluginData, meta.args.member.id);
}
},
});
export const ChannelSwitchAlertsEvt = locateUserEvt({ if (meta.args.newState.channel != null) {
event: "voiceChannelSwitch", if (meta.pluginData.state.usersWithAlerts.includes(memberId)) {
sendAlerts(meta.pluginData, memberId);
}
} else {
const triggeredAlerts = await meta.pluginData.state.alerts.getAlertsByUserId(memberId);
const voiceChannel = meta.args.oldState.channel!;
async listener(meta) { triggeredAlerts.forEach(alert => {
if (meta.pluginData.state.usersWithAlerts.includes(meta.args.member.id)) { const txtChannel = meta.pluginData.guild.channels.resolve(alert.channel_id) as TextChannel;
sendAlerts(meta.pluginData, meta.args.member.id); txtChannel.send(
} `🔴 <@!${alert.requestor_id}> the user <@!${alert.user_id}> disconnected out of \`<#!${voiceChannel.id}>\``,
},
});
export const ChannelLeaveAlertsEvt = locateUserEvt({
event: "voiceChannelLeave",
async listener(meta) {
const triggeredAlerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.member.id);
const voiceChannel = meta.args.oldChannel as VoiceChannel;
triggeredAlerts.forEach(alert => {
const txtChannel = meta.pluginData.client.getChannel(alert.channel_id) as TextableChannel;
txtChannel.createMessage(
`🔴 <@!${alert.requestor_id}> the user <@!${alert.user_id}> disconnected out of \`${voiceChannel.name}\``,
); );
}); });
}
}, },
}); });

View file

@ -1,9 +1,11 @@
export async function createOrReuseInvite(vc: VoiceChannel) { import { VoiceChannel } from "discord.js";
const existingInvites = await vc.getInvites();
if (existingInvites.length !== 0) { export async function createOrReuseInvite(vc: VoiceChannel) {
const existingInvites = await vc.fetchInvites();
if (existingInvites.size !== 0) {
return existingInvites[0]; return existingInvites[0];
} else { } else {
return vc.createInvite(undefined); return vc.createInvite();
} }
} }

View file

@ -1,18 +1,19 @@
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { LocateUserPluginType } from "../types"; import { LocateUserPluginType } from "../types";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { GuildMember, TextChannel } from "discord.js";
export async function moveMember( export async function moveMember(
pluginData: GuildPluginData<LocateUserPluginType>, pluginData: GuildPluginData<LocateUserPluginType>,
toMoveID: string, toMoveID: string,
target: Member, target: GuildMember,
errorChannel: TextableChannel, errorChannel: TextChannel,
) { ) {
const modMember: Member = await pluginData.client.getRESTGuildMember(pluginData.guild.id, toMoveID); const modMember: GuildMember = await pluginData.guild.members.fetch(toMoveID);
if (modMember.voiceState.channelID != null) { if (modMember.voice.channelID != null) {
try { try {
await modMember.edit({ await modMember.edit({
channelID: target.voiceState.channelID, channel: target.voice.channelID
}); });
} catch { } catch {
sendErrorMessage(pluginData, errorChannel, "Failed to move you. Are you in a voice channel?"); sendErrorMessage(pluginData, errorChannel, "Failed to move you. Are you in a voice channel?");

View file

@ -4,6 +4,7 @@ import { resolveMember } from "../../../utils";
import { sendWhere } from "./sendWhere"; import { sendWhere } from "./sendWhere";
import { moveMember } from "./moveMember"; import { moveMember } from "./moveMember";
import { TextChannel } from "discord.js";
export async function sendAlerts(pluginData: GuildPluginData<LocateUserPluginType>, userId: string) { export async function sendAlerts(pluginData: GuildPluginData<LocateUserPluginType>, userId: string) {
const triggeredAlerts = await pluginData.state.alerts.getAlertsByUserId(userId); const triggeredAlerts = await pluginData.state.alerts.getAlertsByUserId(userId);
@ -12,7 +13,7 @@ export async function sendAlerts(pluginData: GuildPluginData<LocateUserPluginTyp
triggeredAlerts.forEach(alert => { triggeredAlerts.forEach(alert => {
const prepend = `<@!${alert.requestor_id}>, an alert requested by you has triggered!\nReminder: \`${alert.body}\`\n`; const prepend = `<@!${alert.requestor_id}>, an alert requested by you has triggered!\nReminder: \`${alert.body}\`\n`;
const txtChannel = pluginData.client.getChannel(alert.channel_id) as TextableChannel; const txtChannel = pluginData.guild.channels.resolve(alert.channel_id) as TextChannel;
sendWhere(pluginData, member, txtChannel, prepend); sendWhere(pluginData, member, txtChannel, prepend);
if (alert.active) { if (alert.active) {
moveMember(pluginData, alert.requestor_id, member, txtChannel); moveMember(pluginData, alert.requestor_id, member, txtChannel);

View file

@ -3,19 +3,20 @@ import { createOrReuseInvite } from "./createOrReuseInvite";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { LocateUserPluginType } from "../types"; import { LocateUserPluginType } from "../types";
import { sendErrorMessage } from "../../../pluginUtils"; import { sendErrorMessage } from "../../../pluginUtils";
import { GuildMember, Invite, TextChannel, VoiceChannel } from "discord.js";
export async function sendWhere( export async function sendWhere(
pluginData: GuildPluginData<LocateUserPluginType>, pluginData: GuildPluginData<LocateUserPluginType>,
member: Member, member: GuildMember,
channel: TextableChannel, channel: TextChannel,
prepend: string, prepend: string,
) { ) {
const voice = member.voiceState.channelID const voice = member.voice.channelID
? (pluginData.guild.channels.cache.get(member.voiceState.channelID) as VoiceChannel) ? (pluginData.guild.channels.resolve(member.voice.channelID) as VoiceChannel)
: null; : null;
if (voice == null) { if (voice == null) {
channel.createMessage(prepend + "That user is not in a channel"); channel.send(prepend + "That user is not in a channel");
} else { } else {
let invite: Invite; let invite: Invite;
try { try {
@ -24,9 +25,10 @@ export async function sendWhere(
sendErrorMessage(pluginData, channel, "Cannot create an invite to that channel!"); sendErrorMessage(pluginData, channel, "Cannot create an invite to that channel!");
return; return;
} }
channel.createMessage({ channel.send({
content: prepend + `${member.mention} is in the following channel: \`${voice.name}\` ${getInviteLink(invite)}`, content: prepend + `<@${member.id}> is in the following channel: \`${voice.name}\` ${getInviteLink(invite)}`,
allowedMentions: { users: true }, allowedMentions: { parse: ["users"] },
split: false,
}); });
} }
} }

View file

@ -3,20 +3,21 @@ import { stripObjectToScalars, UnknownUser } from "../../../utils";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { safeFindRelevantAuditLogEntry } from "../../../utils/safeFindRelevantAuditLogEntry"; import { safeFindRelevantAuditLogEntry } from "../../../utils/safeFindRelevantAuditLogEntry";
import { GuildAuditLogs } from "discord.js";
export const LogsGuildBanAddEvt = logsEvt({ export const LogsGuildBanAddEvt = logsEvt({
event: "guildBanAdd", event: "guildBanAdd",
async listener(meta) { async listener(meta) {
const pluginData = meta.pluginData; const pluginData = meta.pluginData;
const user = meta.args.user; const user = meta.args.ban.user;
const relevantAuditLogEntry = await safeFindRelevantAuditLogEntry( const relevantAuditLogEntry = await safeFindRelevantAuditLogEntry(
pluginData, pluginData,
ErisConstants.AuditLogActions.MEMBER_BAN_ADD, GuildAuditLogs.Actions.MEMBER_BAN_ADD as number,
user.id, user.id,
); );
const mod = relevantAuditLogEntry ? relevantAuditLogEntry.user : new UnknownUser(); const mod = relevantAuditLogEntry ? relevantAuditLogEntry.executor : new UnknownUser();
pluginData.state.guildLogs.log( pluginData.state.guildLogs.log(
LogType.MEMBER_BAN, LogType.MEMBER_BAN,
@ -34,14 +35,14 @@ export const LogsGuildBanRemoveEvt = logsEvt({
async listener(meta) { async listener(meta) {
const pluginData = meta.pluginData; const pluginData = meta.pluginData;
const user = meta.args.user; const user = meta.args.ban.user;
const relevantAuditLogEntry = await safeFindRelevantAuditLogEntry( const relevantAuditLogEntry = await safeFindRelevantAuditLogEntry(
pluginData, pluginData,
ErisConstants.AuditLogActions.MEMBER_BAN_REMOVE, GuildAuditLogs.Actions.MEMBER_BAN_REMOVE as number,
user.id, user.id,
); );
const mod = relevantAuditLogEntry ? relevantAuditLogEntry.user : new UnknownUser(); const mod = relevantAuditLogEntry ? relevantAuditLogEntry.executor : new UnknownUser();
pluginData.state.guildLogs.log( pluginData.state.guildLogs.log(
LogType.MEMBER_UNBAN, LogType.MEMBER_UNBAN,

View file

@ -13,14 +13,14 @@ export const LogsGuildMemberAddEvt = logsEvt({
const member = meta.args.member; const member = meta.args.member;
const newThreshold = moment.utc().valueOf() - 1000 * 60 * 60; const newThreshold = moment.utc().valueOf() - 1000 * 60 * 60;
const accountAge = humanizeDuration(moment.utc().valueOf() - member.createdAt, { const accountAge = humanizeDuration(moment.utc().valueOf() - member.user.createdTimestamp, {
largest: 2, largest: 2,
round: true, round: true,
}); });
pluginData.state.guildLogs.log(LogType.MEMBER_JOIN, { pluginData.state.guildLogs.log(LogType.MEMBER_JOIN, {
member: stripObjectToScalars(member, ["user", "roles"]), member: stripObjectToScalars(member, ["user", "roles"]),
new: member.createdAt >= newThreshold ? " :new:" : "", new: member.user.createdTimestamp >= newThreshold ? " :new:" : "",
account_age: accountAge, account_age: accountAge,
}); });

View file

@ -5,6 +5,7 @@ import { LogType } from "../../../data/LogType";
import isEqual from "lodash.isequal"; import isEqual from "lodash.isequal";
import diff from "lodash.difference"; import diff from "lodash.difference";
import { safeFindRelevantAuditLogEntry } from "../../../utils/safeFindRelevantAuditLogEntry"; import { safeFindRelevantAuditLogEntry } from "../../../utils/safeFindRelevantAuditLogEntry";
import { GuildAuditLogs } from "discord.js";
export const LogsGuildMemberUpdateEvt = logsEvt({ export const LogsGuildMemberUpdateEvt = logsEvt({
event: "guildMemberUpdate", event: "guildMemberUpdate",
@ -12,17 +13,17 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
async listener(meta) { async listener(meta) {
const pluginData = meta.pluginData; const pluginData = meta.pluginData;
const oldMember = meta.args.oldMember; const oldMember = meta.args.oldMember;
const member = meta.args.member; const member = meta.args.newMember;
if (!oldMember) return; if (!oldMember) return;
const logMember = stripObjectToScalars(member, ["user", "roles"]); const logMember = stripObjectToScalars(member, ["user", "roles"]);
if (member.nick !== oldMember.nick) { if (member.nickname !== oldMember.nickname) {
pluginData.state.guildLogs.log(LogType.MEMBER_NICK_CHANGE, { pluginData.state.guildLogs.log(LogType.MEMBER_NICK_CHANGE, {
member: logMember, member: logMember,
oldNick: oldMember.nick != null ? oldMember.nick : "<none>", oldNick: oldMember.nickname != null ? oldMember.nickname : "<none>",
newNick: member.nick != null ? member.nick : "<none>", newNick: member.nickname != null ? member.nickname : "<none>",
}); });
} }
@ -49,10 +50,10 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
if (!skip) { if (!skip) {
const relevantAuditLogEntry = await safeFindRelevantAuditLogEntry( const relevantAuditLogEntry = await safeFindRelevantAuditLogEntry(
pluginData, pluginData,
ErisConstants.AuditLogActions.MEMBER_ROLE_UPDATE, GuildAuditLogs.Actions.MEMBER_ROLE_UPDATE as number,
member.id, member.id,
); );
const mod = relevantAuditLogEntry ? relevantAuditLogEntry.user : new UnknownUser(); const mod = relevantAuditLogEntry ? relevantAuditLogEntry.executor : new UnknownUser();
if (addedRoles.length && removedRoles.length) { if (addedRoles.length && removedRoles.length) {
// Roles added *and* removed // Roles added *and* removed

View file

@ -1,46 +1,34 @@
import { logsEvt } from "../types"; import { logsEvt } from "../types";
import { stripObjectToScalars } from "../../../utils"; import { stripObjectToScalars } from "../../../utils";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
/** Merge into single event
export const LogsVoiceJoinEvt = logsEvt({
event: "voiceChannelJoin",
async listener(meta) {
meta.pluginData.state.guildLogs.log(LogType.VOICE_CHANNEL_JOIN, {
member: stripObjectToScalars(meta.args.member, ["user", "roles"]),
channel: stripObjectToScalars(meta.args.newChannel),
});
},
});
export const LogsVoiceLeaveEvt = logsEvt({
event: "voiceChannelLeave",
async listener(meta) {
meta.pluginData.state.guildLogs.log(LogType.VOICE_CHANNEL_LEAVE, {
member: stripObjectToScalars(meta.args.member, ["user", "roles"]),
channel: stripObjectToScalars(meta.args.oldChannel),
});
},
});
export const LogsVoiceSwitchEvt = logsEvt({
event: "voiceChannelSwitch",
async listener(meta) {
meta.pluginData.state.guildLogs.log(LogType.VOICE_CHANNEL_MOVE, {
member: stripObjectToScalars(meta.args.member, ["user", "roles"]),
oldChannel: stripObjectToScalars(meta.args.oldChannel),
newChannel: stripObjectToScalars(meta.args.newChannel),
});
},
});
**/
export const LogsVoiceStateUpdateEvt = logsEvt({ export const LogsVoiceStateUpdateEvt = logsEvt({
event: "voiceStateUpdate", event: "voiceStateUpdate",
async listener(meta) { async listener(meta) {
console.error(`Fixme @LogsVoiceChannelEvts.ts`); const oldChannel = meta.args.oldState.channel;
const newChannel = meta.args.newState.channel;
const member = meta.args.newState.member ?? meta.args.oldState.member!;
if (!newChannel) { // Leave evt
meta.pluginData.state.guildLogs.log(LogType.VOICE_CHANNEL_LEAVE, {
member: stripObjectToScalars(member, ["user", "roles"]),
oldChannel: stripObjectToScalars(oldChannel),
newChannel: stripObjectToScalars(newChannel),
});
} else if (!oldChannel) { // Join Evt
meta.pluginData.state.guildLogs.log(LogType.VOICE_CHANNEL_JOIN, {
member: stripObjectToScalars(member, ["user", "roles"]),
oldChannel: stripObjectToScalars(oldChannel),
newChannel: stripObjectToScalars(newChannel),
});
} else {
meta.pluginData.state.guildLogs.log(LogType.VOICE_CHANNEL_MOVE, {
member: stripObjectToScalars(member, ["user", "roles"]),
oldChannel: stripObjectToScalars(oldChannel),
newChannel: stripObjectToScalars(newChannel),
});
}
}, },
}); });

View file

@ -12,15 +12,15 @@ import {
import { SavedMessage } from "../../../data/entities/SavedMessage"; import { SavedMessage } from "../../../data/entities/SavedMessage";
import { renderTemplate, TemplateParseError } from "../../../templateFormatter"; import { renderTemplate, TemplateParseError } from "../../../templateFormatter";
import { logger } from "../../../logger"; import { logger } from "../../../logger";
import moment from "moment-timezone";
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
import { MessageOptions } from "discord.js";
export async function getLogMessage( export async function getLogMessage(
pluginData: GuildPluginData<LogsPluginType>, pluginData: GuildPluginData<LogsPluginType>,
type: LogType, type: LogType,
data: any, data: any,
opts?: Pick<TLogChannel, "format" | "timestamp_format" | "include_embed_timestamp">, opts?: Pick<TLogChannel, "format" | "timestamp_format" | "include_embed_timestamp">,
): Promise<MessageContent | null> { ): Promise<MessageOptions | null> {
const config = pluginData.config.get(); const config = pluginData.config.get();
const format = opts?.format?.[LogType[type]] || config.format[LogType[type]] || ""; const format = opts?.format?.[LogType[type]] || config.format[LogType[type]] || "";
if (format === "" || format == null) return null; if (format === "" || format == null) return null;

View file

@ -6,6 +6,7 @@ import { createChunkedMessage, get, noop } from "../../../utils";
import { getLogMessage } from "./getLogMessage"; import { getLogMessage } from "./getLogMessage";
import { allowTimeout } from "../../../RegExpRunner"; import { allowTimeout } from "../../../RegExpRunner";
import { SavedMessage } from "../../../data/entities/SavedMessage"; import { SavedMessage } from "../../../data/entities/SavedMessage";
import { MessageMentionTypes, TextChannel } from "discord.js";
const excludedUserProps = ["user", "member", "mod"]; const excludedUserProps = ["user", "member", "mod"];
const excludedRoleProps = ["message.member.roles", "member.roles"]; const excludedRoleProps = ["message.member.roles", "member.roles"];
@ -46,8 +47,8 @@ export async function log(pluginData: GuildPluginData<LogsPluginType>, type: Log
for (const value of Object.values(data || {})) { for (const value of Object.values(data || {})) {
if (value instanceof SavedMessage) { if (value instanceof SavedMessage) {
const member = pluginData.guild.members.cache.get(value.user_id); const member = pluginData.guild.members.cache.get(value.user_id);
for (const role of member?.roles || []) { for (const role of member?.roles.cache || []) {
if (opts.excluded_roles.includes(role)) { if (opts.excluded_roles.includes(role[0])) {
continue logChannelLoop; continue logChannelLoop;
} }
} }
@ -128,7 +129,7 @@ export async function log(pluginData: GuildPluginData<LogsPluginType>, type: Log
if (message) { if (message) {
// For non-string log messages (i.e. embeds) batching or chunking is not possible, so send them immediately // For non-string log messages (i.e. embeds) batching or chunking is not possible, so send them immediately
if (typeof message !== "string") { if (typeof message !== "string") {
await channel.createMessage(message).catch(noop); await channel.send(message).catch(noop);
return; return;
} }
@ -136,6 +137,7 @@ export async function log(pluginData: GuildPluginData<LogsPluginType>, type: Log
const batched = opts.batched ?? true; const batched = opts.batched ?? true;
const batchTime = opts.batch_time ?? 1000; const batchTime = opts.batch_time ?? 1000;
const cfg = pluginData.config.get(); const cfg = pluginData.config.get();
const parse: MessageMentionTypes[] | undefined = cfg.allow_user_mentions ? ["users"] : undefined;
if (batched) { if (batched) {
// If we're batching log messages, gather all log messages within the set batch_time into a single message // If we're batching log messages, gather all log messages within the set batch_time into a single message
@ -144,14 +146,14 @@ export async function log(pluginData: GuildPluginData<LogsPluginType>, type: Log
setTimeout(async () => { setTimeout(async () => {
const batchedMessage = pluginData.state.batches.get(channel.id)!.join("\n"); const batchedMessage = pluginData.state.batches.get(channel.id)!.join("\n");
pluginData.state.batches.delete(channel.id); pluginData.state.batches.delete(channel.id);
createChunkedMessage(channel, batchedMessage, { users: cfg.allow_user_mentions }).catch(noop); createChunkedMessage(channel, batchedMessage, { parse }).catch(noop);
}, batchTime); }, batchTime);
} }
pluginData.state.batches.get(channel.id)!.push(message); pluginData.state.batches.get(channel.id)!.push(message);
} else { } else {
// If we're not batching log messages, just send them immediately // If we're not batching log messages, just send them immediately
await createChunkedMessage(channel, message, { users: cfg.allow_user_mentions }).catch(noop); await createChunkedMessage(channel, message, { parse }).catch(noop);
} }
} }
} }

View file

@ -6,6 +6,7 @@ import moment from "moment-timezone";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { FORMAT_NO_TIMESTAMP, LogsPluginType } from "../types"; import { FORMAT_NO_TIMESTAMP, LogsPluginType } from "../types";
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
import { MessageAttachment } from "discord.js";
export async function onMessageDelete(pluginData: GuildPluginData<LogsPluginType>, savedMessage: SavedMessage) { export async function onMessageDelete(pluginData: GuildPluginData<LogsPluginType>, savedMessage: SavedMessage) {
const user = await resolveUser(pluginData.client, savedMessage.user_id); const user = await resolveUser(pluginData.client, savedMessage.user_id);
@ -14,7 +15,7 @@ export async function onMessageDelete(pluginData: GuildPluginData<LogsPluginType
if (user) { if (user) {
// Replace attachment URLs with media URLs // Replace attachment URLs with media URLs
if (savedMessage.data.attachments) { if (savedMessage.data.attachments) {
for (const attachment of savedMessage.data.attachments as Attachment[]) { for (const attachment of savedMessage.data.attachments as MessageAttachment[]) {
attachment.url = useMediaUrls(attachment.url); attachment.url = useMediaUrls(attachment.url);
} }
} }

View file

@ -5,6 +5,7 @@ import { SavedMessage } from "../../../data/entities/SavedMessage";
import { LogType } from "../../../data/LogType"; import { LogType } from "../../../data/LogType";
import { stripObjectToScalars, resolveUser } from "../../../utils"; import { stripObjectToScalars, resolveUser } from "../../../utils";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
import { MessageEmbed } from "discord.js";
export async function onMessageUpdate( export async function onMessageUpdate(
pluginData: GuildPluginData<LogsPluginType>, pluginData: GuildPluginData<LogsPluginType>,
@ -14,13 +15,13 @@ export async function onMessageUpdate(
// To log a message update, either the message content or a rich embed has to change // To log a message update, either the message content or a rich embed has to change
let logUpdate = false; let logUpdate = false;
const oldEmbedsToCompare = ((oldSavedMessage.data.embeds || []) as Embed[]) const oldEmbedsToCompare = ((oldSavedMessage.data.embeds || []) as MessageEmbed[])
.map(e => cloneDeep(e)) .map(e => cloneDeep(e))
.filter(e => (e as Embed).type === "rich"); .filter(e => (e as MessageEmbed).type === "rich");
const newEmbedsToCompare = ((savedMessage.data.embeds || []) as Embed[]) const newEmbedsToCompare = ((savedMessage.data.embeds || []) as MessageEmbed[])
.map(e => cloneDeep(e)) .map(e => cloneDeep(e))
.filter(e => (e as Embed).type === "rich"); .filter(e => (e as MessageEmbed).type === "rich");
for (const embed of [...oldEmbedsToCompare, ...newEmbedsToCompare]) { for (const embed of [...oldEmbedsToCompare, ...newEmbedsToCompare]) {
if (embed.thumbnail) { if (embed.thumbnail) {

View file

@ -14,7 +14,7 @@ export const SaveMessagesToDBCmd = messageSaverCmd({
}, },
async run({ message: msg, args, pluginData }) { async run({ message: msg, args, pluginData }) {
await msg.channel.createMessage("Saving specified messages..."); await msg.channel.send("Saving specified messages...");
const { savedCount, failed } = await saveMessagesToDB(pluginData, args.channel, args.ids.trim().split(" ")); const { savedCount, failed } = await saveMessagesToDB(pluginData, args.channel, args.ids.trim().split(" "));
if (failed.length) { if (failed.length) {

View file

@ -13,13 +13,13 @@ export const SavePinsToDBCmd = messageSaverCmd({
}, },
async run({ message: msg, args, pluginData }) { async run({ message: msg, args, pluginData }) {
await msg.channel.createMessage(`Saving pins from <#${args.channel.id}>...`); await msg.channel.send(`Saving pins from <#${args.channel.id}>...`);
const pins = await args.channel.getPins(); const pins = await args.channel.messages.fetchPinned();
const { savedCount, failed } = await saveMessagesToDB( const { savedCount, failed } = await saveMessagesToDB(
pluginData, pluginData,
args.channel, args.channel,
pins.map(m => m.id), pins.keyArray(),
); );
if (failed.length) { if (failed.length) {

View file

@ -1,3 +1,4 @@
import { Message } from "discord.js";
import { messageSaverEvt } from "../types"; import { messageSaverEvt } from "../types";
export const MessageCreateEvt = messageSaverEvt({ export const MessageCreateEvt = messageSaverEvt({
@ -7,7 +8,7 @@ export const MessageCreateEvt = messageSaverEvt({
async listener(meta) { async listener(meta) {
// Only save regular chat messages // Only save regular chat messages
if (meta.args.message.type !== 0) { if (meta.args.message.type !== "DEFAULT" && meta.args.message.type !== "REPLY") {
return; return;
} }
@ -21,11 +22,11 @@ export const MessageUpdateEvt = messageSaverEvt({
allowSelf: true, allowSelf: true,
async listener(meta) { async listener(meta) {
if (meta.args.message.type !== 0) { if (meta.args.newMessage.type !== "DEFAULT" && meta.args.newMessage.type !== "REPLY") {
return; return;
} }
await meta.pluginData.state.savedMessages.saveEditFromMsg(meta.args.message); await meta.pluginData.state.savedMessages.saveEditFromMsg(meta.args.newMessage as Message);
}, },
}); });
@ -36,7 +37,7 @@ export const MessageDeleteEvt = messageSaverEvt({
async listener(meta) { async listener(meta) {
const msg = meta.args.message as Message; const msg = meta.args.message as Message;
if (msg.type != null && msg.type !== 0) { if (msg.type != null && meta.args.message.type !== "DEFAULT" && meta.args.message.type !== "REPLY") {
return; return;
} }

View file

@ -1,5 +1,6 @@
import { MessageSaverPluginType } from "./types"; import { MessageSaverPluginType } from "./types";
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { TextChannel, Message } from "discord.js";
export async function saveMessagesToDB( export async function saveMessagesToDB(
pluginData: GuildPluginData<MessageSaverPluginType>, pluginData: GuildPluginData<MessageSaverPluginType>,
@ -14,7 +15,7 @@ export async function saveMessagesToDB(
let thisMsg: Message; let thisMsg: Message;
try { try {
thisMsg = await channel.getMessage(id); thisMsg = await channel.messages.fetch(id);
if (!thisMsg) { if (!thisMsg) {
failed.push(id); failed.push(id);