Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/src/data/DefaultLogMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"MESSAGE_DELETE_BULK": "{timestamp} 🗑 **{count}** messages by {authorIds} deleted in {channelMention(channel)} ({archiveUrl})",
"MESSAGE_DELETE_BARE": "{timestamp} 🗑 Message (`{messageId}`) deleted in {channelMention(channel)} (no more info available)",
"MESSAGE_DELETE_AUTO": "{timestamp} 🗑 Auto-deleted message (`{message.id}`) from {userMention(user)} in {channelMention(channel)} (originally posted at **{messageDate}**):{messageSummary(message)}",
"MESSAGE_PIN": "{timestamp} 📌 {userMention(mod)} pinned a message by {userMention(user)} in {channelMention(channel)}:{messageSummary(message)}",
"MESSAGE_UNPIN": "{timestamp} 📌 {userMention(mod)} unpinned a message by {userMention(user)} in {channelMention(channel)}:{messageSummary(message)}",

"VOICE_CHANNEL_JOIN": "{timestamp} 🎙 🔵 {userMention(member)} joined {channelMention(channel)}",
"VOICE_CHANNEL_MOVE": "{timestamp} 🎙 ↔ {userMention(member)} moved from {channelMention(oldChannel)} to {channelMention(newChannel)}",
Expand Down
2 changes: 2 additions & 0 deletions backend/src/data/GuildSavedMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
}));
}

data.pinned = msg.pinned;

return data;
}

Expand Down
2 changes: 2 additions & 0 deletions backend/src/data/LogType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const LogType = {
MESSAGE_DELETE: "MESSAGE_DELETE",
MESSAGE_DELETE_BULK: "MESSAGE_DELETE_BULK",
MESSAGE_DELETE_BARE: "MESSAGE_DELETE_BARE",
MESSAGE_PIN: "MESSAGE_PIN",
MESSAGE_UNPIN: "MESSAGE_UNPIN",
VOICE_CHANNEL_JOIN: "VOICE_CHANNEL_JOIN",
VOICE_CHANNEL_LEAVE: "VOICE_CHANNEL_LEAVE",
VOICE_CHANNEL_MOVE: "VOICE_CHANNEL_MOVE",
Expand Down
1 change: 1 addition & 0 deletions backend/src/data/entities/SavedMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface ISavedMessageData {
discriminator: string;
};
content: string;
pinned?: boolean;
embeds?: ISavedMessageEmbedData[];
stickers?: ISavedMessageStickerData[];
timestamp: number;
Expand Down
4 changes: 4 additions & 0 deletions backend/src/plugins/Logs/LogsPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ import { logMessageDelete } from "./logFunctions/logMessageDelete.js";
import { logMessageDeleteAuto } from "./logFunctions/logMessageDeleteAuto.js";
import { logMessageDeleteBare } from "./logFunctions/logMessageDeleteBare.js";
import { logMessageDeleteBulk } from "./logFunctions/logMessageDeleteBulk.js";
import { logMessagePin } from "./logFunctions/logMessagePin.js";
import { logMessageUnpin } from "./logFunctions/logMessageUnpin.js";
import { logMessageEdit } from "./logFunctions/logMessageEdit.js";
import { logMessageSpamDetected } from "./logFunctions/logMessageSpamDetected.js";
import { logOtherSpamDetected } from "./logFunctions/logOtherSpamDetected.js";
Expand Down Expand Up @@ -200,6 +202,8 @@ export const LogsPlugin = guildPlugin<LogsPluginType>()({
logMessageDeleteAuto: makePublicFn(pluginData, logMessageDeleteAuto),
logMessageDeleteBare: makePublicFn(pluginData, logMessageDeleteBare),
logMessageDeleteBulk: makePublicFn(pluginData, logMessageDeleteBulk),
logMessagePin: makePublicFn(pluginData, logMessagePin),
logMessageUnpin: makePublicFn(pluginData, logMessageUnpin),
logMessageEdit: makePublicFn(pluginData, logMessageEdit),
logMessageSpamDetected: makePublicFn(pluginData, logMessageSpamDetected),
logOtherSpamDetected: makePublicFn(pluginData, logOtherSpamDetected),
Expand Down
46 changes: 46 additions & 0 deletions backend/src/plugins/Logs/logFunctions/logMessagePin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { GuildTextBasedChannel, User } from "discord.js";
import { GuildPluginData } from "knub";
import { LogType } from "../../../data/LogType.js";
import { ISavedMessageAttachmentData, SavedMessage } from "../../../data/entities/SavedMessage.js";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter.js";
import { UnknownUser, useMediaUrls } from "../../../utils.js";
import { resolveChannelIds } from "../../../utils/resolveChannelIds.js";
import {
channelToTemplateSafeChannel,
savedMessageToTemplateSafeSavedMessage,
userToTemplateSafeUser,
} from "../../../utils/templateSafeObjects.js";
import { LogsPluginType } from "../types.js";
import { log } from "../util/log.js";

export interface LogMessagePinData {
mod: User | UnknownUser | null;
user: User | UnknownUser;
channel: GuildTextBasedChannel;
message: SavedMessage;
}

export function logMessagePin(pluginData: GuildPluginData<LogsPluginType>, data: LogMessagePinData) {
if (data.message.data.attachments) {
for (const attachment of data.message.data.attachments as ISavedMessageAttachmentData[]) {
attachment.url = useMediaUrls(attachment.url);
}
}

return log(
pluginData,
LogType.MESSAGE_PIN,
createTypedTemplateSafeValueContainer({
mod: data.mod ? userToTemplateSafeUser(data.mod) : null,
user: userToTemplateSafeUser(data.user),
channel: channelToTemplateSafeChannel(data.channel),
message: savedMessageToTemplateSafeSavedMessage(data.message),
}),
{
userId: data.user.id,
messageTextContent: data.message.data.content,
bot: data.user instanceof User ? data.user.bot : false,
...resolveChannelIds(data.channel),
},
);
}
46 changes: 46 additions & 0 deletions backend/src/plugins/Logs/logFunctions/logMessageUnpin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { GuildTextBasedChannel, User } from "discord.js";
import { GuildPluginData } from "knub";
import { LogType } from "../../../data/LogType.js";
import { ISavedMessageAttachmentData, SavedMessage } from "../../../data/entities/SavedMessage.js";
import { createTypedTemplateSafeValueContainer } from "../../../templateFormatter.js";
import { UnknownUser, useMediaUrls } from "../../../utils.js";
import { resolveChannelIds } from "../../../utils/resolveChannelIds.js";
import {
channelToTemplateSafeChannel,
savedMessageToTemplateSafeSavedMessage,
userToTemplateSafeUser,
} from "../../../utils/templateSafeObjects.js";
import { LogsPluginType } from "../types.js";
import { log } from "../util/log.js";

export interface LogMessageUnpinData {
mod: User | UnknownUser | null;
user: User | UnknownUser;
channel: GuildTextBasedChannel;
message: SavedMessage;
}

export function logMessageUnpin(pluginData: GuildPluginData<LogsPluginType>, data: LogMessageUnpinData) {
if (data.message.data.attachments) {
for (const attachment of data.message.data.attachments as ISavedMessageAttachmentData[]) {
attachment.url = useMediaUrls(attachment.url);
}
}

return log(
pluginData,
LogType.MESSAGE_UNPIN,
createTypedTemplateSafeValueContainer({
mod: data.mod ? userToTemplateSafeUser(data.mod) : null,
user: userToTemplateSafeUser(data.user),
channel: channelToTemplateSafeChannel(data.channel),
message: savedMessageToTemplateSafeSavedMessage(data.message),
}),
{
userId: data.user.id,
messageTextContent: data.message.data.content,
bot: data.user instanceof User ? data.user.bot : false,
...resolveChannelIds(data.channel),
},
);
}
14 changes: 14 additions & 0 deletions backend/src/plugins/Logs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,20 @@ export const LogTypeData = z.object({
channel: z.instanceof(TemplateSafeChannel),
}),

[LogType.MESSAGE_PIN]: z.object({
mod: z.instanceof(TemplateSafeUser).or(z.null()),
user: z.instanceof(TemplateSafeUser),
channel: z.instanceof(TemplateSafeChannel),
message: z.instanceof(TemplateSafeSavedMessage),
}),

[LogType.MESSAGE_UNPIN]: z.object({
mod: z.instanceof(TemplateSafeUser).or(z.null()),
user: z.instanceof(TemplateSafeUser),
channel: z.instanceof(TemplateSafeChannel),
message: z.instanceof(TemplateSafeSavedMessage),
}),

[LogType.VOICE_CHANNEL_JOIN]: z.object({
member: z.instanceof(TemplateSafeMember),
channel: z.instanceof(TemplateSafeChannel),
Expand Down
74 changes: 63 additions & 11 deletions backend/src/plugins/Logs/util/onMessageUpdate.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { EmbedData, GuildTextBasedChannel, Snowflake } from "discord.js";
import { AuditLogEvent, EmbedData, GuildTextBasedChannel, Snowflake, User } from "discord.js";
import { GuildPluginData } from "vety";
import { LogType } from "../../../data/LogType.js";
import { SavedMessage } from "../../../data/entities/SavedMessage.js";
import { resolveUser } from "../../../utils.js";
import { findMatchingAuditLogEntry } from "../../../utils/findMatchingAuditLogEntry.js";
import { resolveUser, UnknownUser } from "../../../utils.js";
import { logMessageEdit } from "../logFunctions/logMessageEdit.js";
import { logMessagePin } from "../logFunctions/logMessagePin.js";
import { logMessageUnpin } from "../logFunctions/logMessageUnpin.js";
import { LogsPluginType } from "../types.js";
import { isLogIgnored } from "./isLogIgnored.js";

export async function onMessageUpdate(
pluginData: GuildPluginData<LogsPluginType>,
Expand Down Expand Up @@ -41,17 +46,64 @@ export async function onMessageUpdate(
logUpdate = true;
}

if (!logUpdate) {
const wasPinned = oldSavedMessage.data.pinned ?? false;
const isPinned = savedMessage.data.pinned ?? false;
const pinStateChanged = wasPinned !== isPinned;

if (!logUpdate && !pinStateChanged) {
return;
}

const user = await resolveUser(pluginData.client, savedMessage.user_id);
const resolvedChannel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake);
if (!resolvedChannel || !resolvedChannel.isTextBased()) {
return;
}
const channel = resolvedChannel as GuildTextBasedChannel;

if (logUpdate) {
logMessageEdit(pluginData, {
user,
channel,
before: oldSavedMessage,
after: savedMessage,
});
}

const user = await resolveUser(pluginData.client, savedMessage.user_id, "Logs:onMessageUpdate");
const channel = pluginData.guild.channels.resolve(savedMessage.channel_id as Snowflake)! as GuildTextBasedChannel;
if (pinStateChanged) {
const logType = isPinned ? LogType.MESSAGE_PIN : LogType.MESSAGE_UNPIN;
if (!isLogIgnored(pluginData, logType, savedMessage.id)) {
const auditLogAction = isPinned ? AuditLogEvent.MessagePin : AuditLogEvent.MessageUnpin;
const relevantAuditLogEntry = await findMatchingAuditLogEntry(
pluginData.guild,
auditLogAction,
savedMessage.user_id,
);

logMessageEdit(pluginData, {
user,
channel,
before: oldSavedMessage,
after: savedMessage,
});
let mod: User | UnknownUser | null = null;
let skipMod = false;

if (relevantAuditLogEntry?.extra) {
const extra: any = relevantAuditLogEntry.extra;
if (
(extra?.channel?.id && extra.channel.id !== savedMessage.channel_id) ||
(extra?.messageId && extra.messageId !== savedMessage.id)
) {
skipMod = true;
}
}

if (!skipMod && relevantAuditLogEntry?.executor?.id) {
mod = await resolveUser(pluginData.client, relevantAuditLogEntry.executor.id);
}

const logFn = isPinned ? logMessagePin : logMessageUnpin;
logFn(pluginData, {
mod,
user,
channel,
message: savedMessage,
});
}
}
}
2 changes: 2 additions & 0 deletions backend/src/utils/templateSafeObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export class TemplateSafeSavedMessageData extends TemplateSafeValueContainer {
discriminator: string;
}>;
content: string;
pinned?: boolean;
embeds?: Array<TypedTemplateSafeValueContainer<ISavedMessageEmbedData>>;
stickers?: Array<TypedTemplateSafeValueContainer<ISavedMessageStickerData>>;
timestamp: number;
Expand Down Expand Up @@ -445,6 +446,7 @@ export function savedMessageToTemplateSafeSavedMessage(savedMessage: SavedMessag
),

timestamp: savedMessage.data.timestamp,
pinned: savedMessage.data.pinned ?? false,
}),
});
}
Expand Down