2026-05-14 15:02:23 +07:00
|
|
|
import type {
|
|
|
|
|
Message,
|
|
|
|
|
TextChannel,
|
|
|
|
|
ThreadChannel,
|
|
|
|
|
} from "discord.js-selfbot-v13";
|
2026-05-13 21:04:45 +07:00
|
|
|
|
|
|
|
|
export interface MessageLocation {
|
|
|
|
|
channelId: string;
|
|
|
|
|
threadId: string | null;
|
|
|
|
|
threadName: string | null;
|
|
|
|
|
channelName: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface RichMessageMetadata {
|
2026-05-14 15:02:23 +07:00
|
|
|
stickers: Array<{
|
|
|
|
|
id: string;
|
|
|
|
|
name: string;
|
|
|
|
|
url: string;
|
|
|
|
|
format: string | null;
|
|
|
|
|
}>;
|
2026-05-13 21:04:45 +07:00
|
|
|
embeds: Array<{
|
|
|
|
|
title: string | null;
|
|
|
|
|
description: string | null;
|
|
|
|
|
url: string | null;
|
|
|
|
|
color: number | null;
|
|
|
|
|
image: string | null;
|
|
|
|
|
thumbnail: string | null;
|
2026-05-14 15:02:23 +07:00
|
|
|
author: {
|
|
|
|
|
name: string | null;
|
|
|
|
|
url: string | null;
|
|
|
|
|
iconURL: string | null;
|
|
|
|
|
} | null;
|
2026-05-13 21:04:45 +07:00
|
|
|
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,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-14 15:02:23 +07:00
|
|
|
export function getStickerMetadata(
|
|
|
|
|
message: Message,
|
|
|
|
|
): RichMessageMetadata["stickers"] {
|
2026-05-13 21:04:45 +07:00
|
|
|
return Array.from(message.stickers.values()).map((sticker) => ({
|
|
|
|
|
id: sticker.id,
|
|
|
|
|
name: sticker.name,
|
|
|
|
|
url: sticker.url,
|
|
|
|
|
format: sticker.format ?? null,
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-14 15:02:23 +07:00
|
|
|
export function getAttachmentMetadata(
|
|
|
|
|
message: Message,
|
|
|
|
|
): RichMessageMetadata["attachments"] {
|
2026-05-13 21:04:45 +07:00
|
|
|
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,
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-14 15:02:23 +07:00
|
|
|
export function getEmbedMetadata(
|
|
|
|
|
message: Message,
|
|
|
|
|
): RichMessageMetadata["embeds"] {
|
2026-05-13 21:04:45 +07:00
|
|
|
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,
|
2026-05-14 15:02:23 +07:00
|
|
|
roles: member.roles.cache.map((role) => ({
|
|
|
|
|
id: role.id,
|
|
|
|
|
name: role.name,
|
|
|
|
|
})),
|
2026-05-13 21:04:45 +07:00
|
|
|
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) {
|
2026-05-14 15:02:23 +07:00
|
|
|
return attachments
|
|
|
|
|
.map((attachment) => `[Attachment: ${attachment.name}]`)
|
|
|
|
|
.join(" ");
|
2026-05-13 21:04:45 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const embeds = getEmbedMetadata(message);
|
|
|
|
|
if (embeds.length > 0) {
|
2026-05-14 15:02:23 +07:00
|
|
|
return embeds
|
|
|
|
|
.map((embed) => embed.title || embed.description || "[Embed]")
|
|
|
|
|
.join(" ");
|
2026-05-13 21:04:45 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
}
|