Files
dc-recorder/src/moderation/messageMetadata.ts
2026-05-14 15:02:23 +07:00

194 lines
5.0 KiB
TypeScript

import type {
Message,
TextChannel,
ThreadChannel,
} from "discord.js-selfbot-v13";
export interface MessageLocation {
channelId: string;
threadId: string | null;
threadName: string | null;
channelName: string | null;
}
export interface RichMessageMetadata {
stickers: Array<{
id: string;
name: string;
url: string;
format: string | null;
}>;
embeds: Array<{
title: string | null;
description: string | null;
url: string | null;
color: number | null;
image: string | null;
thumbnail: string | null;
author: {
name: string | null;
url: string | null;
iconURL: string | null;
} | null;
footer: { text: string | null; iconURL: string | null } | null;
fields: Array<{ name: string; value: string; inline: boolean }>;
}>;
attachments: Array<{
id: string;
name: string;
url: string;
contentType: string | null;
size: number;
}>;
author: {
id: string;
username: string;
tag: string | null;
avatarURL: string | null;
bot: boolean;
};
member: {
displayName: string | null;
roles: Array<{ id: string; name: string }>;
joinedTimestamp: number | null;
} | null;
channel: MessageLocation;
reference: {
messageId: string | null;
channelId: string | null;
guildId: string | null;
} | null;
}
export function getMessageLocation(message: Message): MessageLocation {
const channel = message.channel as TextChannel | ThreadChannel;
if (!channel.isThread?.()) {
return {
channelId: message.channelId,
threadId: null,
threadName: null,
channelName: "name" in channel ? channel.name : null,
};
}
return {
channelId: channel.parentId ?? message.channelId,
threadId: channel.id,
threadName: channel.name,
channelName: channel.parent?.name ?? null,
};
}
export function getStickerMetadata(
message: Message,
): RichMessageMetadata["stickers"] {
return Array.from(message.stickers.values()).map((sticker) => ({
id: sticker.id,
name: sticker.name,
url: sticker.url,
format: sticker.format ?? null,
}));
}
export function getAttachmentMetadata(
message: Message,
): RichMessageMetadata["attachments"] {
return Array.from(message.attachments.values()).map((attachment) => ({
id: attachment.id,
name: attachment.name || "unknown",
url: attachment.url,
contentType: attachment.contentType ?? null,
size: attachment.size,
}));
}
export function getEmbedMetadata(
message: Message,
): RichMessageMetadata["embeds"] {
return message.embeds.map((embed) => ({
title: embed.title ?? null,
description: embed.description ?? null,
url: embed.url ?? null,
color: embed.color ?? null,
image: embed.image?.url ?? null,
thumbnail: embed.thumbnail?.url ?? null,
author: embed.author
? {
name: embed.author.name ?? null,
url: embed.author.url ?? null,
iconURL: embed.author.iconURL ?? null,
}
: null,
footer: embed.footer
? {
text: embed.footer.text ?? null,
iconURL: embed.footer.iconURL ?? null,
}
: null,
fields: embed.fields.map((field) => ({
name: field.name,
value: field.value,
inline: Boolean(field.inline),
})),
}));
}
export function getMessageMetadata(message: Message): RichMessageMetadata {
const member = message.member;
return {
stickers: getStickerMetadata(message),
embeds: getEmbedMetadata(message),
attachments: getAttachmentMetadata(message),
author: {
id: message.author.id,
username: message.author.username,
tag: "tag" in message.author ? message.author.tag : null,
avatarURL: message.author.avatarURL() ?? null,
bot: Boolean(message.author.bot),
},
member: member
? {
displayName: member.displayName ?? null,
roles: member.roles.cache.map((role) => ({
id: role.id,
name: role.name,
})),
joinedTimestamp: member.joinedTimestamp ?? null,
}
: null,
channel: getMessageLocation(message),
reference: message.reference
? {
messageId: message.reference.messageId ?? null,
channelId: message.reference.channelId ?? null,
guildId: message.reference.guildId ?? null,
}
: null,
};
}
export function getDisplayContent(message: Message): string {
if (message.content.trim().length > 0) return message.content;
const stickers = getStickerMetadata(message);
if (stickers.length > 0) {
return stickers.map((sticker) => `[Sticker: ${sticker.name}]`).join(" ");
}
const attachments = getAttachmentMetadata(message);
if (attachments.length > 0) {
return attachments
.map((attachment) => `[Attachment: ${attachment.name}]`)
.join(" ");
}
const embeds = getEmbedMetadata(message);
if (embeds.length > 0) {
return embeds
.map((embed) => embed.title || embed.description || "[Embed]")
.join(" ");
}
return "";
}