mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 08:47:22 +00:00
fix(transformers): message transformer using different style (#2916)
* fix(transformers): message transformer using different style * fix: more bench tests * fix(bench): token can not be empty * more desired props * fix: bug on message.id props * fix: transfomrer errors on bench --------- Co-authored-by: Jonathan Ho <heiheiho000@gmail.com>
This commit is contained in:
co-authored by
Jonathan Ho
parent
782a778a1d
commit
dea9d1d152
@@ -0,0 +1,753 @@
|
||||
import {
|
||||
ApplicationFlags,
|
||||
ButtonStyles,
|
||||
iconHashToBigInt,
|
||||
InteractionTypes,
|
||||
MessageActivityTypes,
|
||||
MessageComponentTypes,
|
||||
MessageTypes,
|
||||
PremiumTypes,
|
||||
StickerFormatTypes,
|
||||
TeamMembershipStates,
|
||||
TextStyles,
|
||||
UserFlags,
|
||||
type Bot,
|
||||
type DiscordMessage,
|
||||
} from '@discordeno/bot'
|
||||
import { MemberToggles } from '@discordeno/bot/dist/transformers/index.js'
|
||||
import { createBot } from '../../../bot/dist/index.js'
|
||||
import { memoryBenchmark } from '../utils/memoryBenchmark.js'
|
||||
|
||||
export const CHANNEL_MENTION_REGEX = /<#[0-9]+>/g
|
||||
|
||||
const MESSAGE_SIZE = 20000
|
||||
|
||||
const bot = createBot({
|
||||
token: process.env.DISCORD_TOKEN ?? " ",
|
||||
events: {},
|
||||
})
|
||||
|
||||
bot.transformers.desiredProperties.message.activity = true
|
||||
bot.transformers.desiredProperties.message.application = true
|
||||
bot.transformers.desiredProperties.message.applicationId = true
|
||||
bot.transformers.desiredProperties.message.attachments = true
|
||||
bot.transformers.desiredProperties.message.author = true
|
||||
bot.transformers.desiredProperties.message.channelId = true
|
||||
bot.transformers.desiredProperties.message.components = true
|
||||
bot.transformers.desiredProperties.message.content = true
|
||||
bot.transformers.desiredProperties.message.editedTimestamp = true
|
||||
bot.transformers.desiredProperties.message.embeds = true
|
||||
bot.transformers.desiredProperties.message.guildId = true
|
||||
bot.transformers.desiredProperties.message.id = true
|
||||
bot.transformers.desiredProperties.message.interaction.id = true
|
||||
bot.transformers.desiredProperties.message.interaction.member = true
|
||||
bot.transformers.desiredProperties.message.interaction.name = true
|
||||
bot.transformers.desiredProperties.message.interaction.user = true
|
||||
bot.transformers.desiredProperties.message.interaction.type = true
|
||||
bot.transformers.desiredProperties.message.member = true
|
||||
bot.transformers.desiredProperties.message.mentionedChannelIds = true
|
||||
bot.transformers.desiredProperties.message.mentionedRoleIds = true
|
||||
bot.transformers.desiredProperties.message.mentions = true
|
||||
bot.transformers.desiredProperties.message.messageReference.messageId = true
|
||||
bot.transformers.desiredProperties.message.messageReference.channelId = true
|
||||
bot.transformers.desiredProperties.message.messageReference.guildId = true
|
||||
bot.transformers.desiredProperties.message.nonce = true
|
||||
bot.transformers.desiredProperties.message.reactions = true
|
||||
bot.transformers.desiredProperties.message.stickerItems = true
|
||||
bot.transformers.desiredProperties.message.thread = true
|
||||
bot.transformers.desiredProperties.message.type = true
|
||||
bot.transformers.desiredProperties.message.webhookId = true
|
||||
|
||||
const URL = 'https://discordeno.js.org/'
|
||||
const IMAGE_HASH = '5fff867ae5f666fcd0626bd84f5e69c0'
|
||||
const GUILD_ID = '785384884197392384'
|
||||
const USER = {
|
||||
accent_color: 0,
|
||||
avatar: IMAGE_HASH,
|
||||
banner: IMAGE_HASH,
|
||||
bot: true,
|
||||
discriminator: '1234',
|
||||
email: 'discordeno@discordeno.com',
|
||||
flags: UserFlags.BotHttpInteractions,
|
||||
id: GUILD_ID,
|
||||
locale: 'en',
|
||||
mfa_enabled: true,
|
||||
premium_type: PremiumTypes.Nitro,
|
||||
public_flags: UserFlags.BotHttpInteractions,
|
||||
system: true,
|
||||
username: 'skillz',
|
||||
verified: true,
|
||||
}
|
||||
const MEMBER = {
|
||||
nick: 'John',
|
||||
roles: ['111111111111111111', '222222222222222222', '333333333333333333'],
|
||||
joined_at: '2022-01-01T00:00:00.000Z',
|
||||
premium_since: '2022-02-01T00:00:00.000Z',
|
||||
deaf: false,
|
||||
mute: true,
|
||||
pending: false,
|
||||
permissions: '2147483647',
|
||||
}
|
||||
|
||||
console.log('before the bench')
|
||||
await memoryBenchmark(
|
||||
'[transformer] message cache check',
|
||||
() => ({
|
||||
cache: [] as any[],
|
||||
}), // function reutrn a new instance of object wanted to test with
|
||||
(object, event: DiscordMessage) => object.cache.push(bot.transformers.message(bot, event)),
|
||||
// function specify how to add event to the object/ run the object
|
||||
[...new Array(MESSAGE_SIZE)].map(
|
||||
(i) =>
|
||||
({
|
||||
activity: {
|
||||
party_id: 'party_id',
|
||||
type: MessageActivityTypes.Join,
|
||||
},
|
||||
application: {
|
||||
bot_public: true,
|
||||
bot_require_code_grant: true,
|
||||
cover_image: IMAGE_HASH,
|
||||
custom_install_url: 'https://google.com',
|
||||
description: 'discordeno is the best lib ever',
|
||||
flags: ApplicationFlags.GatewayGuildMembers,
|
||||
guild_id: GUILD_ID,
|
||||
icon: IMAGE_HASH,
|
||||
id: GUILD_ID,
|
||||
install_params: {
|
||||
permissions: '8',
|
||||
scopes: ['identify'],
|
||||
},
|
||||
name: 'skillz',
|
||||
owner: USER,
|
||||
primary_sku_id: GUILD_ID,
|
||||
privacy_policy_url: 'https://discordeno.js.org',
|
||||
role_connections_verification_url: 'https://discordeno.js.org',
|
||||
rpc_origins: [],
|
||||
slug: 'discordeno',
|
||||
tags: ['discordeno', 'discordeno', 'discordeno', 'discordeno', 'discordeno'],
|
||||
team: {
|
||||
icon: IMAGE_HASH,
|
||||
id: GUILD_ID,
|
||||
members: [
|
||||
{
|
||||
membership_state: TeamMembershipStates.Accepted,
|
||||
permissions: ['*'],
|
||||
team_id: GUILD_ID,
|
||||
user: USER,
|
||||
},
|
||||
{
|
||||
membership_state: TeamMembershipStates.Accepted,
|
||||
permissions: ['*'],
|
||||
team_id: GUILD_ID,
|
||||
user: USER,
|
||||
},
|
||||
],
|
||||
name: 'discordeno',
|
||||
owner_user_id: GUILD_ID,
|
||||
},
|
||||
terms_of_service_url: 'https://discordeno.js.org',
|
||||
verify_key: IMAGE_HASH,
|
||||
},
|
||||
application_id: GUILD_ID,
|
||||
attachments: [
|
||||
{
|
||||
content_type: 'application/json',
|
||||
description: 'discordeno discordeno discordeno',
|
||||
ephemeral: true,
|
||||
filename: 'discordeno',
|
||||
height: 100,
|
||||
id: GUILD_ID,
|
||||
proxy_url: 'https://discordeno.js.org',
|
||||
size: 100,
|
||||
url: 'https://discordeno.js.org',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
content_type: 'application/json',
|
||||
description: 'discordeno discordeno discordeno',
|
||||
ephemeral: true,
|
||||
filename: 'discordeno',
|
||||
height: 100,
|
||||
id: GUILD_ID,
|
||||
proxy_url: 'https://discordeno.js.org',
|
||||
size: 100,
|
||||
url: 'https://discordeno.js.org',
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
author: USER,
|
||||
channel_id: GUILD_ID,
|
||||
components: [
|
||||
{
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
custom_id: GUILD_ID,
|
||||
disabled: true,
|
||||
emoji: {
|
||||
animated: true,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
label: 'discordeno',
|
||||
style: ButtonStyles.Danger,
|
||||
type: MessageComponentTypes.Button,
|
||||
url: 'https://discordeno.js.org',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
type: MessageComponentTypes.InputText,
|
||||
custom_id: 'discordeno',
|
||||
label: 'discordeno',
|
||||
max_length: 100,
|
||||
min_length: 100,
|
||||
placeholder: 'discordeno',
|
||||
required: true,
|
||||
style: TextStyles.Paragraph,
|
||||
value: 'discordeno',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
type: MessageComponentTypes.SelectMenu,
|
||||
custom_id: 'discordeno',
|
||||
max_values: 100,
|
||||
min_values: 100,
|
||||
options: [
|
||||
{
|
||||
default: true,
|
||||
description: 'idk idk idk',
|
||||
emoji: {
|
||||
animated: true,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
label: 'discordeno',
|
||||
value: 'discordeno',
|
||||
},
|
||||
],
|
||||
placeholder: 'discordeno',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
content: 'discordeno',
|
||||
edited_timestamp: new Date().toISOString(),
|
||||
embeds: [
|
||||
{
|
||||
author: {
|
||||
icon_url: URL,
|
||||
name: 'discordeno',
|
||||
proxy_icon_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
color: 0,
|
||||
description: 'discordeno',
|
||||
fields: [
|
||||
{
|
||||
name: 'discordeno',
|
||||
value: 'discordeno',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'discordeno',
|
||||
value: 'discordeno',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
footer: {
|
||||
icon_url: URL,
|
||||
proxy_icon_url: URL,
|
||||
text: 'discordeno',
|
||||
},
|
||||
image: {
|
||||
height: 100,
|
||||
width: 100,
|
||||
proxy_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
provider: {
|
||||
name: 'discordeno',
|
||||
url: URL,
|
||||
},
|
||||
thumbnail: {
|
||||
height: 100,
|
||||
width: 100,
|
||||
proxy_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
title: 'discordeno',
|
||||
type: 'rich',
|
||||
url: URL,
|
||||
video: {
|
||||
height: 100,
|
||||
width: 100,
|
||||
proxy_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
},
|
||||
],
|
||||
flags: 64,
|
||||
guild_id: GUILD_ID,
|
||||
id: GUILD_ID,
|
||||
interaction: {
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
type: InteractionTypes.ApplicationCommand,
|
||||
user: USER,
|
||||
member: MEMBER,
|
||||
},
|
||||
member: MEMBER,
|
||||
mention_channels: [
|
||||
{
|
||||
guild_id: GUILD_ID,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
type: 0,
|
||||
},
|
||||
],
|
||||
mention_roles: ['111111111111111111', '222222222222222222'],
|
||||
mention_everyone: false,
|
||||
mentions: [USER, USER, USER],
|
||||
message_reference: {
|
||||
message_id: GUILD_ID,
|
||||
channel_id: GUILD_ID,
|
||||
guild_id: GUILD_ID,
|
||||
fail_if_not_exists: true,
|
||||
},
|
||||
nonce: 'discordeno',
|
||||
pinned: true,
|
||||
position: 100,
|
||||
reactions: [
|
||||
{
|
||||
count: 100,
|
||||
emoji: {
|
||||
animated: true,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
me: true,
|
||||
},
|
||||
],
|
||||
sticker_items: [
|
||||
{
|
||||
format_type: StickerFormatTypes.APng,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
],
|
||||
thread: {
|
||||
id: '987654321098765432',
|
||||
name: 'My Thread',
|
||||
type: 11,
|
||||
guild_id: '123456789012345678',
|
||||
parent_id: '876543210987654321',
|
||||
owner_id: '111111111111111111',
|
||||
message_count: 10,
|
||||
member_count: 5,
|
||||
created_timestamp: 1651388000,
|
||||
last_message_id: '876543210987654321',
|
||||
applied_tags: ['discordeno'],
|
||||
default_thread_rate_limit_per_user: 100,
|
||||
member: {
|
||||
flags: 100,
|
||||
id: GUILD_ID,
|
||||
join_timestamp: new Date().toISOString(),
|
||||
user_id: GUILD_ID,
|
||||
},
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
tts: true,
|
||||
type: MessageTypes.Default,
|
||||
webhook_id: GUILD_ID,
|
||||
} as DiscordMessage),
|
||||
), // array of event to test with
|
||||
{ times: 1, log: false, table: false },
|
||||
)
|
||||
console.log('after the bench')
|
||||
|
||||
function oldtransformMessage(bot: Bot, payload: DiscordMessage): any {
|
||||
const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined
|
||||
const userId = bot.transformers.snowflake(payload.author.id)
|
||||
|
||||
const message = {
|
||||
// UNTRANSFORMED STUFF HERE
|
||||
content: payload.content ?? '',
|
||||
isFromBot: payload.author.bot ?? false,
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
tag: `${payload.author.username}#${payload.author.discriminator}`,
|
||||
timestamp: Date.parse(payload.timestamp),
|
||||
editedTimestamp: payload.edited_timestamp ? Date.parse(payload.edited_timestamp) : undefined,
|
||||
bitfield: (payload.tts ? 1n : 0n) | (payload.mention_everyone ? 2n : 0n) | (payload.pinned ? 4n : 0n),
|
||||
attachments: payload.attachments?.map((attachment) => bot.transformers.attachment(bot, attachment)),
|
||||
embeds: payload.embeds?.map((embed) => bot.transformers.embed(bot, embed)),
|
||||
reactions: payload.reactions?.map((reaction) => ({
|
||||
me: reaction.me,
|
||||
count: reaction.count,
|
||||
emoji: bot.transformers.emoji(bot, reaction.emoji),
|
||||
})),
|
||||
type: payload.type,
|
||||
activity: payload.activity
|
||||
? {
|
||||
type: payload.activity.type,
|
||||
partyId: payload.activity.party_id,
|
||||
}
|
||||
: undefined,
|
||||
application: payload.application,
|
||||
flags: payload.flags,
|
||||
interaction: payload.interaction
|
||||
? {
|
||||
id: bot.transformers.snowflake(payload.interaction.id),
|
||||
type: payload.interaction.type,
|
||||
name: payload.interaction.name,
|
||||
user: bot.transformers.user(bot, payload.interaction.user),
|
||||
member: payload.interaction.member
|
||||
? {
|
||||
id: userId,
|
||||
guildId,
|
||||
nick: payload.interaction.member.nick ?? undefined,
|
||||
roles: payload.interaction.member.roles?.map((id) => bot.transformers.snowflake(id)),
|
||||
joinedAt: payload.interaction.member.joined_at ? Date.parse(payload.interaction.member.joined_at) : undefined,
|
||||
premiumSince: payload.interaction.member.premium_since ? Date.parse(payload.interaction.member.premium_since) : undefined,
|
||||
toggles: new MemberToggles(payload.interaction.member),
|
||||
avatar: payload.interaction.member.avatar ? iconHashToBigInt(payload.interaction.member.avatar) : undefined,
|
||||
permissions: payload.interaction.member.permissions ? bot.transformers.snowflake(payload.interaction.member.permissions) : undefined,
|
||||
communicationDisabledUntil: payload.interaction.member.communication_disabled_until
|
||||
? Date.parse(payload.interaction.member.communication_disabled_until)
|
||||
: undefined,
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
: undefined,
|
||||
thread: payload.thread ? bot.transformers.channel(bot, { channel: payload.thread, guildId }) : undefined,
|
||||
components: payload.components?.map((component) => bot.transformers.component(bot, component)),
|
||||
stickerItems: payload.sticker_items?.map((sticker) => ({
|
||||
id: bot.transformers.snowflake(sticker.id),
|
||||
name: sticker.name,
|
||||
formatType: sticker.format_type,
|
||||
})),
|
||||
|
||||
// TRANSFORMED STUFF BELOW
|
||||
id: bot.transformers.snowflake(payload.id),
|
||||
guildId,
|
||||
channelId: bot.transformers.snowflake(payload.channel_id),
|
||||
webhookId: payload.webhook_id ? bot.transformers.snowflake(payload.webhook_id) : undefined,
|
||||
authorId: userId,
|
||||
applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined,
|
||||
messageReference: payload.message_reference
|
||||
? {
|
||||
messageId: payload.message_reference.message_id ? bot.transformers.snowflake(payload.message_reference.message_id) : undefined,
|
||||
channelId: payload.message_reference.channel_id ? bot.transformers.snowflake(payload.message_reference.channel_id) : undefined,
|
||||
guildId: payload.message_reference.guild_id ? bot.transformers.snowflake(payload.message_reference.guild_id) : undefined,
|
||||
}
|
||||
: undefined,
|
||||
mentionedUserIds: payload.mentions ? payload.mentions.map((m) => bot.transformers.snowflake(m.id)) : [],
|
||||
mentionedRoleIds: payload.mention_roles ? payload.mention_roles.map((id) => bot.transformers.snowflake(id)) : [],
|
||||
mentionedChannelIds: [
|
||||
// Keep any ids tht discord sends
|
||||
...(payload.mention_channels ?? []).map((m) => bot.transformers.snowflake(m.id)),
|
||||
// Add any other ids that can be validated in a channel mention format
|
||||
...(payload.content?.match(CHANNEL_MENTION_REGEX) ?? []).map((text) =>
|
||||
// converts the <#123> into 123
|
||||
bot.transformers.snowflake(text.substring(2, text.length - 1)),
|
||||
),
|
||||
],
|
||||
member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined,
|
||||
nonce: payload.nonce,
|
||||
}
|
||||
|
||||
return message
|
||||
}
|
||||
|
||||
await memoryBenchmark(
|
||||
'[transformer] old message cache check',
|
||||
() => ({
|
||||
cache: [] as any[],
|
||||
}), // function reutrn a new instance of object wanted to test with
|
||||
(object, event: DiscordMessage) => object.cache.push(oldtransformMessage(bot as any, event)),
|
||||
// function specify how to add event to the object/ run the object
|
||||
[...new Array(MESSAGE_SIZE)].map(
|
||||
(i) =>
|
||||
({
|
||||
activity: {
|
||||
party_id: 'party_id',
|
||||
type: MessageActivityTypes.Join,
|
||||
},
|
||||
application: {
|
||||
bot_public: true,
|
||||
bot_require_code_grant: true,
|
||||
cover_image: IMAGE_HASH,
|
||||
custom_install_url: 'https://google.com',
|
||||
description: 'discordeno is the best lib ever',
|
||||
flags: ApplicationFlags.GatewayGuildMembers,
|
||||
guild_id: GUILD_ID,
|
||||
icon: IMAGE_HASH,
|
||||
id: GUILD_ID,
|
||||
install_params: {
|
||||
permissions: '8',
|
||||
scopes: ['identify'],
|
||||
},
|
||||
name: 'skillz',
|
||||
owner: USER,
|
||||
primary_sku_id: GUILD_ID,
|
||||
privacy_policy_url: 'https://discordeno.js.org',
|
||||
role_connections_verification_url: 'https://discordeno.js.org',
|
||||
rpc_origins: [],
|
||||
slug: 'discordeno',
|
||||
tags: ['discordeno', 'discordeno', 'discordeno', 'discordeno', 'discordeno'],
|
||||
team: {
|
||||
icon: IMAGE_HASH,
|
||||
id: GUILD_ID,
|
||||
members: [
|
||||
{
|
||||
membership_state: TeamMembershipStates.Accepted,
|
||||
permissions: ['*'],
|
||||
team_id: GUILD_ID,
|
||||
user: USER,
|
||||
},
|
||||
{
|
||||
membership_state: TeamMembershipStates.Accepted,
|
||||
permissions: ['*'],
|
||||
team_id: GUILD_ID,
|
||||
user: USER,
|
||||
},
|
||||
],
|
||||
name: 'discordeno',
|
||||
owner_user_id: GUILD_ID,
|
||||
},
|
||||
terms_of_service_url: 'https://discordeno.js.org',
|
||||
verify_key: IMAGE_HASH,
|
||||
},
|
||||
application_id: GUILD_ID,
|
||||
attachments: [
|
||||
{
|
||||
content_type: 'application/json',
|
||||
description: 'discordeno discordeno discordeno',
|
||||
ephemeral: true,
|
||||
filename: 'discordeno',
|
||||
height: 100,
|
||||
id: GUILD_ID,
|
||||
proxy_url: 'https://discordeno.js.org',
|
||||
size: 100,
|
||||
url: 'https://discordeno.js.org',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
content_type: 'application/json',
|
||||
description: 'discordeno discordeno discordeno',
|
||||
ephemeral: true,
|
||||
filename: 'discordeno',
|
||||
height: 100,
|
||||
id: GUILD_ID,
|
||||
proxy_url: 'https://discordeno.js.org',
|
||||
size: 100,
|
||||
url: 'https://discordeno.js.org',
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
author: USER,
|
||||
channel_id: GUILD_ID,
|
||||
components: [
|
||||
{
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
custom_id: GUILD_ID,
|
||||
disabled: true,
|
||||
emoji: {
|
||||
animated: true,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
label: 'discordeno',
|
||||
style: ButtonStyles.Danger,
|
||||
type: MessageComponentTypes.Button,
|
||||
url: 'https://discordeno.js.org',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
type: MessageComponentTypes.InputText,
|
||||
custom_id: 'discordeno',
|
||||
label: 'discordeno',
|
||||
max_length: 100,
|
||||
min_length: 100,
|
||||
placeholder: 'discordeno',
|
||||
required: true,
|
||||
style: TextStyles.Paragraph,
|
||||
value: 'discordeno',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 1,
|
||||
components: [
|
||||
{
|
||||
type: MessageComponentTypes.SelectMenu,
|
||||
custom_id: 'discordeno',
|
||||
max_values: 100,
|
||||
min_values: 100,
|
||||
options: [
|
||||
{
|
||||
default: true,
|
||||
description: 'idk idk idk',
|
||||
emoji: {
|
||||
animated: true,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
label: 'discordeno',
|
||||
value: 'discordeno',
|
||||
},
|
||||
],
|
||||
placeholder: 'discordeno',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
content: 'discordeno',
|
||||
edited_timestamp: new Date().toISOString(),
|
||||
embeds: [
|
||||
{
|
||||
author: {
|
||||
icon_url: URL,
|
||||
name: 'discordeno',
|
||||
proxy_icon_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
color: 0,
|
||||
description: 'discordeno',
|
||||
fields: [
|
||||
{
|
||||
name: 'discordeno',
|
||||
value: 'discordeno',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'discordeno',
|
||||
value: 'discordeno',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
footer: {
|
||||
icon_url: URL,
|
||||
proxy_icon_url: URL,
|
||||
text: 'discordeno',
|
||||
},
|
||||
image: {
|
||||
height: 100,
|
||||
width: 100,
|
||||
proxy_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
provider: {
|
||||
name: 'discordeno',
|
||||
url: URL,
|
||||
},
|
||||
thumbnail: {
|
||||
height: 100,
|
||||
width: 100,
|
||||
proxy_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
title: 'discordeno',
|
||||
type: 'rich',
|
||||
url: URL,
|
||||
video: {
|
||||
height: 100,
|
||||
width: 100,
|
||||
proxy_url: URL,
|
||||
url: URL,
|
||||
},
|
||||
},
|
||||
],
|
||||
flags: 64,
|
||||
guild_id: GUILD_ID,
|
||||
id: GUILD_ID,
|
||||
interaction: {
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
type: InteractionTypes.ApplicationCommand,
|
||||
user: USER,
|
||||
member: MEMBER,
|
||||
},
|
||||
member: MEMBER,
|
||||
mention_channels: [
|
||||
{
|
||||
guild_id: GUILD_ID,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
type: 0,
|
||||
},
|
||||
],
|
||||
mention_roles: ['111111111111111111', '222222222222222222'],
|
||||
mention_everyone: false,
|
||||
mentions: [USER, USER, USER],
|
||||
message_reference: {
|
||||
message_id: GUILD_ID,
|
||||
channel_id: GUILD_ID,
|
||||
guild_id: GUILD_ID,
|
||||
fail_if_not_exists: true,
|
||||
},
|
||||
nonce: 'discordeno',
|
||||
pinned: true,
|
||||
position: 100,
|
||||
reactions: [
|
||||
{
|
||||
count: 100,
|
||||
emoji: {
|
||||
animated: true,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
me: true,
|
||||
},
|
||||
],
|
||||
sticker_items: [
|
||||
{
|
||||
format_type: StickerFormatTypes.APng,
|
||||
id: GUILD_ID,
|
||||
name: 'discordeno',
|
||||
},
|
||||
],
|
||||
thread: {
|
||||
id: '987654321098765432',
|
||||
name: 'My Thread',
|
||||
type: 11,
|
||||
guild_id: '123456789012345678',
|
||||
parent_id: '876543210987654321',
|
||||
owner_id: '111111111111111111',
|
||||
message_count: 10,
|
||||
member_count: 5,
|
||||
created_timestamp: 1651388000,
|
||||
last_message_id: '876543210987654321',
|
||||
applied_tags: ['discordeno'],
|
||||
default_thread_rate_limit_per_user: 100,
|
||||
member: {
|
||||
flags: 100,
|
||||
id: GUILD_ID,
|
||||
join_timestamp: new Date().toISOString(),
|
||||
user_id: GUILD_ID,
|
||||
},
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
tts: true,
|
||||
type: MessageTypes.Default,
|
||||
webhook_id: GUILD_ID,
|
||||
} as DiscordMessage),
|
||||
), // array of event to test with
|
||||
{ times: 1, log: false, table: false },
|
||||
)
|
||||
@@ -35,9 +35,13 @@ export async function memoryBenchmark<O, E>(
|
||||
// Set the memory stats for when files are loaded in.
|
||||
results.loaded = process.memoryUsage()
|
||||
|
||||
events.forEach((event) => {
|
||||
// events.forEach((event, i) => {
|
||||
// console.log('logging event', i)
|
||||
// objectFeeder(object, event)
|
||||
// })
|
||||
for (const event of events) {
|
||||
objectFeeder(object, event)
|
||||
})
|
||||
}
|
||||
|
||||
if (options.log) {
|
||||
console.log(`[INFO] Processed ${events.length} events.`)
|
||||
|
||||
@@ -61,11 +61,6 @@ import { transformEmbed, type Embed } from './transformers/embed.js'
|
||||
import { transformEmoji, type Emoji } from './transformers/emoji.js'
|
||||
import { transformGatewayBot, type GetGatewayBot } from './transformers/gatewayBot.js'
|
||||
import { transformGuild, type Guild } from './transformers/guild.js'
|
||||
import { transformIntegration, type Integration } from './transformers/integration.js'
|
||||
import { transformInteraction, transformInteractionDataOption, type Interaction, type InteractionDataOption } from './transformers/interaction.js'
|
||||
import { transformInvite, type Invite } from './transformers/invite.js'
|
||||
import { transformMember, transformUser, type Member, type User } from './transformers/member.js'
|
||||
import { transformMessage, type Message } from './transformers/message.js'
|
||||
import {
|
||||
transformActivityToDiscordActivity,
|
||||
transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice,
|
||||
@@ -79,6 +74,11 @@ import {
|
||||
transformTeamToDiscordTeam,
|
||||
transformUserToDiscordUser,
|
||||
} from './transformers/index.js'
|
||||
import { transformIntegration, type Integration } from './transformers/integration.js'
|
||||
import { transformInteraction, transformInteractionDataOption, type Interaction, type InteractionDataOption } from './transformers/interaction.js'
|
||||
import { transformInvite, type Invite } from './transformers/invite.js'
|
||||
import { transformMember, transformUser, type Member, type User } from './transformers/member.js'
|
||||
import { transformMessage, type Message } from './transformers/message.js'
|
||||
import { transformPresence, type PresenceUpdate } from './transformers/presence.js'
|
||||
import { transformAllowedMentionsToDiscordAllowedMentions } from './transformers/reverse/allowedMentions.js'
|
||||
import { transformCreateApplicationCommandToDiscordCreateApplicationCommand } from './transformers/reverse/createApplicationCommand.js'
|
||||
@@ -99,6 +99,227 @@ import { transformWidgetSettings, type GuildWidgetSettings } from './transformer
|
||||
import type { BotInteractionResponse, DiscordComponent, DiscordInteractionResponse } from './typings.js'
|
||||
|
||||
export interface Transformers {
|
||||
customizers: {
|
||||
message: (bot: Bot, payload: DiscordMessage, message: Message) => any
|
||||
}
|
||||
desiredProperties: {
|
||||
attachment: {
|
||||
id: boolean
|
||||
filename: boolean
|
||||
contentType: boolean
|
||||
size: boolean
|
||||
url: boolean
|
||||
proxyUrl: boolean
|
||||
height: boolean
|
||||
width: boolean
|
||||
ephemeral: boolean
|
||||
description: boolean
|
||||
}
|
||||
channel: {
|
||||
type: boolean
|
||||
position: boolean
|
||||
name: boolean
|
||||
topic: boolean
|
||||
nsfw: boolean
|
||||
bitrate: boolean
|
||||
userLimit: boolean
|
||||
rateLimitPerUser: boolean
|
||||
rtcRegion: boolean
|
||||
videoQualityMode: boolean
|
||||
guildId: boolean
|
||||
lastPinTimestamp: boolean
|
||||
permissionOverwrites: boolean
|
||||
id: boolean
|
||||
permissions: boolean
|
||||
lastMessageId: boolean
|
||||
ownerId: boolean
|
||||
applicationId: boolean
|
||||
managed: boolean
|
||||
parentId: boolean
|
||||
memberCount: boolean
|
||||
messageCount: boolean
|
||||
archiveTimestamp: boolean
|
||||
autoArchiveDuration: boolean
|
||||
botIsMember: boolean
|
||||
archived: boolean
|
||||
locked: boolean
|
||||
invitable: boolean
|
||||
createTimestamp: boolean
|
||||
newlyCreated: boolean
|
||||
flags: boolean
|
||||
}
|
||||
emoji: {
|
||||
id: boolean
|
||||
name: boolean
|
||||
roles: boolean
|
||||
user: boolean
|
||||
}
|
||||
guild: {
|
||||
afkTimeout: boolean
|
||||
approximateMemberCount: boolean
|
||||
approximatePresenceCount: boolean
|
||||
defaultMessageNotifications: boolean
|
||||
description: boolean
|
||||
explicitContentFilter: boolean
|
||||
maxMembers: boolean
|
||||
maxPresences: boolean
|
||||
maxVideoChannelUsers: boolean
|
||||
mfaLevel: boolean
|
||||
name: boolean
|
||||
nsfwLevel: boolean
|
||||
preferredLocale: boolean
|
||||
premiumSubscriptionCount: boolean
|
||||
premiumTier: boolean
|
||||
stageInstances: boolean
|
||||
systemChannelFlags: boolean
|
||||
vanityUrlCode: boolean
|
||||
verificationLevel: boolean
|
||||
welcomeScreen: boolean
|
||||
discoverySplash: boolean
|
||||
joinedAt: boolean
|
||||
memberCount: boolean
|
||||
shardId: boolean
|
||||
icon: boolean
|
||||
banner: boolean
|
||||
splash: boolean
|
||||
id: boolean
|
||||
ownerId: boolean
|
||||
permissions: boolean
|
||||
afkChannelId: boolean
|
||||
widgetChannelId: boolean
|
||||
applicationId: boolean
|
||||
systemChannelId: boolean
|
||||
rulesChannelId: boolean
|
||||
publicUpdatesChannelId: boolean
|
||||
premiumProgressBarEnabled: boolean
|
||||
}
|
||||
invite: {
|
||||
channelId: boolean
|
||||
code: boolean
|
||||
createdAt: boolean
|
||||
guildId: boolean
|
||||
inviter: boolean
|
||||
maxAge: boolean
|
||||
maxUses: boolean
|
||||
targetType: boolean
|
||||
targetUser: boolean
|
||||
targetApplication: boolean
|
||||
temporary: boolean
|
||||
uses: boolean
|
||||
}
|
||||
member: {
|
||||
id: boolean
|
||||
guildId: boolean
|
||||
user: boolean
|
||||
nick: boolean
|
||||
roles: boolean
|
||||
joinedAt: boolean
|
||||
premiumSince: boolean
|
||||
avatar: boolean
|
||||
permissions: boolean
|
||||
communicationDisabledUntil: boolean
|
||||
}
|
||||
message: {
|
||||
activity: boolean
|
||||
application: boolean
|
||||
applicationId: boolean
|
||||
attachments: boolean
|
||||
author: boolean
|
||||
channelId: boolean
|
||||
components: boolean
|
||||
content: boolean
|
||||
editedTimestamp: boolean
|
||||
embeds: boolean
|
||||
guildId: boolean
|
||||
id: boolean
|
||||
interaction: {
|
||||
id: boolean
|
||||
member: boolean
|
||||
name: boolean
|
||||
user: boolean
|
||||
type: boolean
|
||||
}
|
||||
member: boolean
|
||||
mentionedChannelIds: boolean
|
||||
mentionedRoleIds: boolean
|
||||
mentions: boolean
|
||||
messageReference: {
|
||||
messageId: boolean
|
||||
channelId: boolean
|
||||
guildId: boolean
|
||||
}
|
||||
nonce: boolean
|
||||
reactions: boolean
|
||||
stickerItems: boolean
|
||||
thread: boolean
|
||||
type: boolean
|
||||
webhookId: boolean
|
||||
}
|
||||
role: {
|
||||
name: boolean;
|
||||
guildId: boolean;
|
||||
position: boolean;
|
||||
color: boolean;
|
||||
id: boolean;
|
||||
botId: boolean;
|
||||
integrationId: boolean;
|
||||
permissions: boolean;
|
||||
icon: boolean;
|
||||
unicodeEmoji: boolean;
|
||||
}
|
||||
scheduledEvent: {
|
||||
id: boolean;
|
||||
guildId: boolean;
|
||||
channelId: boolean
|
||||
creatorId: boolean
|
||||
scheduledStartTime: boolean
|
||||
scheduledEndTime: boolean
|
||||
entityId: boolean
|
||||
creator: boolean
|
||||
name: boolean
|
||||
description: boolean
|
||||
privacyLevel: boolean
|
||||
status: boolean
|
||||
entityType: boolean
|
||||
userCount: boolean
|
||||
location: boolean
|
||||
image: boolean
|
||||
}
|
||||
stageInstance: {
|
||||
id: boolean
|
||||
guildId: boolean
|
||||
channelId: boolean
|
||||
topic: boolean
|
||||
guildScheduledEventId: boolean
|
||||
}
|
||||
sticker: {
|
||||
id: boolean
|
||||
packId: boolean
|
||||
name: boolean
|
||||
description: boolean
|
||||
tags: boolean
|
||||
type: boolean
|
||||
formatType: boolean
|
||||
available: boolean
|
||||
guildId: boolean
|
||||
user: boolean
|
||||
sortValue: boolean
|
||||
}
|
||||
webhook: {
|
||||
id: boolean;
|
||||
type: boolean
|
||||
guildId: boolean
|
||||
channelId: boolean
|
||||
user: boolean
|
||||
name: boolean
|
||||
avatar: boolean
|
||||
token: boolean
|
||||
applicationId: boolean
|
||||
sourceGuild: boolean
|
||||
sourceChannel: boolean
|
||||
url: boolean
|
||||
}
|
||||
}
|
||||
reverse: {
|
||||
allowedMentions: (bot: Bot, payload: AllowedMentions) => DiscordAllowedMentions
|
||||
embed: (bot: Bot, payload: Embed) => DiscordEmbed
|
||||
@@ -159,6 +380,229 @@ export interface Transformers {
|
||||
|
||||
export function createTransformers(options: Partial<Transformers>): Transformers {
|
||||
return {
|
||||
customizers: {
|
||||
message(bot, payload, message) {
|
||||
return message
|
||||
},
|
||||
},
|
||||
desiredProperties: {
|
||||
attachment: {
|
||||
id: false,
|
||||
filename: false,
|
||||
contentType: false,
|
||||
size: false,
|
||||
url: false,
|
||||
proxyUrl: false,
|
||||
height: false,
|
||||
width: false,
|
||||
ephemeral: false,
|
||||
description: false,
|
||||
},
|
||||
channel: {
|
||||
type: false,
|
||||
position: false,
|
||||
name: false,
|
||||
topic: false,
|
||||
nsfw: false,
|
||||
bitrate: false,
|
||||
userLimit: false,
|
||||
rateLimitPerUser: false,
|
||||
rtcRegion: false,
|
||||
videoQualityMode: false,
|
||||
guildId: false,
|
||||
lastPinTimestamp: false,
|
||||
permissionOverwrites: false,
|
||||
id: false,
|
||||
permissions: false,
|
||||
lastMessageId: false,
|
||||
ownerId: false,
|
||||
applicationId: false,
|
||||
managed: false,
|
||||
parentId: false,
|
||||
memberCount: false,
|
||||
messageCount: false,
|
||||
archiveTimestamp: false,
|
||||
autoArchiveDuration: false,
|
||||
botIsMember: false,
|
||||
archived: false,
|
||||
locked: false,
|
||||
invitable: false,
|
||||
createTimestamp: false,
|
||||
newlyCreated: false,
|
||||
flags: false,
|
||||
},
|
||||
emoji: {
|
||||
id: false,
|
||||
name: false,
|
||||
roles: false,
|
||||
user: false,
|
||||
},
|
||||
guild: {
|
||||
afkTimeout: false,
|
||||
approximateMemberCount: false,
|
||||
approximatePresenceCount: false,
|
||||
defaultMessageNotifications: false,
|
||||
description: false,
|
||||
explicitContentFilter: false,
|
||||
maxMembers: false,
|
||||
maxPresences: false,
|
||||
maxVideoChannelUsers: false,
|
||||
mfaLevel: false,
|
||||
name: false,
|
||||
nsfwLevel: false,
|
||||
preferredLocale: false,
|
||||
premiumSubscriptionCount: false,
|
||||
premiumTier: false,
|
||||
stageInstances: false,
|
||||
systemChannelFlags: false,
|
||||
vanityUrlCode: false,
|
||||
verificationLevel: false,
|
||||
welcomeScreen: false,
|
||||
discoverySplash: false,
|
||||
joinedAt: false,
|
||||
memberCount: false,
|
||||
shardId: false,
|
||||
icon: false,
|
||||
banner: false,
|
||||
splash: false,
|
||||
id: false,
|
||||
ownerId: false,
|
||||
permissions: false,
|
||||
afkChannelId: false,
|
||||
widgetChannelId: false,
|
||||
applicationId: false,
|
||||
systemChannelId: false,
|
||||
rulesChannelId: false,
|
||||
publicUpdatesChannelId: false,
|
||||
premiumProgressBarEnabled: false,
|
||||
},
|
||||
invite: {
|
||||
channelId: false,
|
||||
code: false,
|
||||
createdAt: false,
|
||||
guildId: false,
|
||||
inviter: false,
|
||||
maxAge: false,
|
||||
maxUses: false,
|
||||
targetType: false,
|
||||
targetUser: false,
|
||||
targetApplication: false,
|
||||
temporary: false,
|
||||
uses: false,
|
||||
},
|
||||
member: {
|
||||
id: false,
|
||||
guildId: false,
|
||||
user: false,
|
||||
nick: false,
|
||||
roles: false,
|
||||
joinedAt: false,
|
||||
premiumSince: false,
|
||||
avatar: false,
|
||||
permissions: false,
|
||||
communicationDisabledUntil: false,
|
||||
},
|
||||
message: {
|
||||
activity: false,
|
||||
application: false,
|
||||
applicationId: false,
|
||||
attachments: false,
|
||||
author: false,
|
||||
channelId: false,
|
||||
components: false,
|
||||
content: false,
|
||||
editedTimestamp: false,
|
||||
embeds: false,
|
||||
guildId: false,
|
||||
id: false,
|
||||
interaction: {
|
||||
id: false,
|
||||
member: false,
|
||||
name: false,
|
||||
type: false,
|
||||
user: false,
|
||||
},
|
||||
member: false,
|
||||
mentionedChannelIds: false,
|
||||
mentionedRoleIds: false,
|
||||
mentions: false,
|
||||
messageReference: {
|
||||
messageId: false,
|
||||
channelId: false,
|
||||
guildId: false,
|
||||
},
|
||||
nonce: false,
|
||||
reactions: false,
|
||||
stickerItems: false,
|
||||
thread: false,
|
||||
type: false,
|
||||
webhookId: false,
|
||||
},
|
||||
role: {
|
||||
name: false,
|
||||
guildId: false,
|
||||
position: false,
|
||||
color: false,
|
||||
id: false,
|
||||
botId: false,
|
||||
integrationId: false,
|
||||
permissions: false,
|
||||
icon: false,
|
||||
unicodeEmoji: false,
|
||||
},
|
||||
scheduledEvent: {
|
||||
id: false,
|
||||
guildId: false,
|
||||
channelId: false,
|
||||
creatorId: false,
|
||||
scheduledStartTime: false,
|
||||
scheduledEndTime: false,
|
||||
entityId: false,
|
||||
creator: false,
|
||||
name: false,
|
||||
description: false,
|
||||
privacyLevel: false,
|
||||
status: false,
|
||||
entityType: false,
|
||||
userCount: false,
|
||||
location: false,
|
||||
image: false,
|
||||
},
|
||||
stageInstance: {
|
||||
id: false,
|
||||
guildId: false,
|
||||
channelId: false,
|
||||
topic: false,
|
||||
guildScheduledEventId: false,
|
||||
},
|
||||
sticker: {
|
||||
id: false,
|
||||
packId: false,
|
||||
name: false,
|
||||
description: false,
|
||||
tags: false,
|
||||
type: false,
|
||||
formatType: false,
|
||||
available: false,
|
||||
guildId: false,
|
||||
user: false,
|
||||
sortValue: false,
|
||||
},
|
||||
webhook: {
|
||||
id: false,
|
||||
type: false,
|
||||
guildId: false,
|
||||
channelId: false,
|
||||
user: false,
|
||||
name: false,
|
||||
avatar: false,
|
||||
token: false,
|
||||
applicationId: false,
|
||||
sourceGuild: false,
|
||||
sourceChannel: false,
|
||||
url: false,
|
||||
}
|
||||
},
|
||||
reverse: {
|
||||
allowedMentions: options.reverse?.allowedMentions ?? transformAllowedMentionsToDiscordAllowedMentions,
|
||||
embed: options.reverse?.embed ?? transformEmbedToDiscordEmbed,
|
||||
|
||||
@@ -1,87 +1,307 @@
|
||||
import type { DiscordMessage } from '@discordeno/types'
|
||||
import type { DiscordMessage, InteractionTypes, MessageActivityTypes, MessageTypes, StickerFormatTypes } from '@discordeno/types'
|
||||
import { CHANNEL_MENTION_REGEX } from '../constants.js'
|
||||
import { iconHashToBigInt, type Bot } from '../index.js'
|
||||
import type { Optionalize } from '../optionalize.js'
|
||||
import { MemberToggles } from './toggles/member.js'
|
||||
import { snowflakeToTimestamp, type Bot } from '../index.js'
|
||||
import { MessageFlags } from '../typings.js'
|
||||
import type { Attachment } from './attachment.js'
|
||||
import type { Channel } from './channel.js'
|
||||
import type { Component } from './component.js'
|
||||
import type { Embed } from './embed.js'
|
||||
import type { Emoji } from './emoji.js'
|
||||
import type { Member, User } from './member.js'
|
||||
import { ToggleBitfield } from './toggles/ToggleBitfield.js'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function transformMessage(bot: Bot, payload: DiscordMessage) {
|
||||
const baseMessage: Partial<Message> & MessageBase = {
|
||||
get crossposted() {
|
||||
return this.flags?.contains(MessageFlags.Crossposted) ?? false
|
||||
},
|
||||
set crossposted(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.Crossposted)
|
||||
else this.flags.remove(MessageFlags.Crossposted)
|
||||
},
|
||||
get ephemeral() {
|
||||
return this.flags?.contains(MessageFlags.Ephemeral) ?? false
|
||||
},
|
||||
set ephemeral(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.Ephemeral)
|
||||
else this.flags.remove(MessageFlags.Ephemeral)
|
||||
},
|
||||
get failedToMentionSomeRolesInThread() {
|
||||
return this.flags?.contains(MessageFlags.FailedToMentionSomeRolesInThread) ?? false
|
||||
},
|
||||
set failedToMentionSomeRolesInThread(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.FailedToMentionSomeRolesInThread)
|
||||
else this.flags.remove(MessageFlags.FailedToMentionSomeRolesInThread)
|
||||
},
|
||||
get hasThread() {
|
||||
return this.flags?.contains(MessageFlags.HasThread) ?? false
|
||||
},
|
||||
set hasThread(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.HasThread)
|
||||
else this.flags.remove(MessageFlags.HasThread)
|
||||
},
|
||||
get isCrosspost() {
|
||||
return this.flags?.contains(MessageFlags.IsCrosspost) ?? false
|
||||
},
|
||||
set isCrosspost(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.IsCrosspost)
|
||||
else this.flags.remove(MessageFlags.IsCrosspost)
|
||||
},
|
||||
get loading() {
|
||||
return this.flags?.contains(MessageFlags.Loading) ?? false
|
||||
},
|
||||
set loading(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.Loading)
|
||||
else this.flags.remove(MessageFlags.Loading)
|
||||
},
|
||||
get mentionedUserIds() {
|
||||
return this.mentions?.map((user) => user.id) ?? []
|
||||
},
|
||||
get mentionEveryone() {
|
||||
return this.bitfield?.contains(2) ?? false
|
||||
},
|
||||
set mentionEveryone(value: boolean) {
|
||||
if (!this.bitfield) return
|
||||
if (value) this.bitfield.add(2)
|
||||
else this.bitfield.remove(2)
|
||||
},
|
||||
get pinned() {
|
||||
return this.bitfield?.contains(3) ?? false
|
||||
},
|
||||
set pinned(value: boolean) {
|
||||
if (!this.bitfield) return
|
||||
if (value) this.bitfield.add(3)
|
||||
else this.bitfield.remove(3)
|
||||
},
|
||||
get sourceMessageDeleted() {
|
||||
return this.flags?.contains(MessageFlags.SourceMessageDeleted) ?? false
|
||||
},
|
||||
set sourceMessageDeleted(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.SourceMessageDeleted)
|
||||
else this.flags.remove(MessageFlags.SourceMessageDeleted)
|
||||
},
|
||||
get suppressEmbeds() {
|
||||
return this.flags?.contains(MessageFlags.SuppressEmbeds) ?? false
|
||||
},
|
||||
set suppressEmbeds(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.SuppressEmbeds)
|
||||
else this.flags.remove(MessageFlags.SuppressEmbeds)
|
||||
},
|
||||
get suppressNotifications() {
|
||||
return this.flags?.contains(MessageFlags.SuppressNotifications) ?? false
|
||||
},
|
||||
set suppressNotifications(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.SuppressNotifications)
|
||||
else this.flags.remove(MessageFlags.SuppressNotifications)
|
||||
},
|
||||
get timestamp() {
|
||||
return this.id ? snowflakeToTimestamp(this.id) : 0
|
||||
},
|
||||
get tts() {
|
||||
return this.bitfield?.contains(1) ?? false
|
||||
},
|
||||
set tts(value: boolean) {
|
||||
if (!this.bitfield) return
|
||||
if (value) this.bitfield.add(1)
|
||||
else this.bitfield.remove(1)
|
||||
},
|
||||
get urgent() {
|
||||
return this.flags?.contains(MessageFlags.Urgent) ?? false
|
||||
},
|
||||
set urgent(value: boolean) {
|
||||
if (!this.flags) return
|
||||
if (value) this.flags.add(MessageFlags.Urgent)
|
||||
else this.flags.remove(MessageFlags.Urgent)
|
||||
},
|
||||
}
|
||||
|
||||
export interface MessageBase {
|
||||
/** Holds all the boolean values on this message. */
|
||||
bitfield?: ToggleBitfield
|
||||
/** Whether this message has been published to subscribed channels (via Channel Following) */
|
||||
crossposted: boolean
|
||||
/** Whether this message is only visible to the user who invoked the Interaction */
|
||||
ephemeral: boolean
|
||||
/** Whether this message failed to mention some roles and add their members to the thread */
|
||||
failedToMentionSomeRolesInThread: boolean
|
||||
/** Message flags combined as a bitfield */
|
||||
flags?: ToggleBitfield
|
||||
/** Whether this message has an associated thread, with the same id as the message */
|
||||
hasThread: boolean
|
||||
/** Whether this message originated from a message in another channel (via Channel Following) */
|
||||
isCrosspost: boolean
|
||||
/** Whether this message is an Interaction Response and the bot is "thinking" */
|
||||
loading: boolean
|
||||
/** The ids of the users who were mentioned in this message. */
|
||||
mentionedUserIds: bigint[]
|
||||
/** Whether this message mentions everyone */
|
||||
mentionEveryone: boolean
|
||||
/** Whether this message is pinned */
|
||||
pinned: boolean
|
||||
/** Whether the source message for this crosspost has been deleted (via Channel Following) */
|
||||
sourceMessageDeleted: boolean
|
||||
/** Whether do not include any embeds when serializing this message */
|
||||
suppressEmbeds: boolean
|
||||
/** Whether this message will not trigger push and desktop notifications */
|
||||
suppressNotifications: boolean
|
||||
/** The timestamp in milliseconds when this message was created */
|
||||
timestamp: number
|
||||
/** Whether this was a TTS message. */
|
||||
tts: boolean
|
||||
/** Whether this message came from the urgent message system */
|
||||
urgent: boolean
|
||||
}
|
||||
|
||||
export interface Message extends MessageBase {
|
||||
/** Sent with Rich Presence-related chat embeds */
|
||||
activity?: {
|
||||
/** Type of message activity */
|
||||
type: MessageActivityTypes
|
||||
/** party_id from a Rich Presence event */
|
||||
partyId?: string
|
||||
}
|
||||
/** if the message is an Interaction or application-owned webhook, this is the id of the application */
|
||||
applicationId?: bigint
|
||||
/** Any attached files on this message. */
|
||||
attachments?: Attachment[]
|
||||
/** The author of this message (not guaranteed to be a valid user) Note: The author object follows the structure of the user object, but is only a valid user in the case where the message is generated by a user or bot user. If the message is generated by a webhook, the author object corresponds to the webhook's id, username, and avatar. You can tell if a message is generated by a webhook by checking for the webhook_id on the message object. */
|
||||
author: User
|
||||
/** id of the channel the message was sent in */
|
||||
channelId: bigint
|
||||
/** The components related to this message */
|
||||
components: Component[]
|
||||
/** Contents of the message */
|
||||
content: string
|
||||
/** The timestamp in milliseconds when this message was edited last. */
|
||||
editedTimestamp?: number
|
||||
/** Any embedded content */
|
||||
embeds?: Embed[]
|
||||
/** id of the guild the message was sent in Note: For MESSAGE_CREATE and MESSAGE_UPDATE events, the message object may not contain a guild_id or member field since the events are sent directly to the receiving user and the bot who sent the message, rather than being sent through the guild like non-ephemeral messages. */
|
||||
guildId?: bigint
|
||||
/** id of the message */
|
||||
id: bigint
|
||||
/** Sent if the message is a response to an Interaction */
|
||||
interaction?: {
|
||||
/** Id of the interaction */
|
||||
id: bigint
|
||||
/** The member who invoked the interaction in the guild */
|
||||
member?: Member
|
||||
/** The name of the ApplicationCommand including the name of the subcommand/subcommand group */
|
||||
name: string
|
||||
/** The type of interaction */
|
||||
type: InteractionTypes
|
||||
/** The user who invoked the interaction */
|
||||
user: User
|
||||
}
|
||||
/** Member properties for this message's author Note: The member object exists in MESSAGE_CREATE and MESSAGE_UPDATE events from text-based guild channels. This allows bots to obtain real-time member data without requiring bots to store member state in memory. */
|
||||
member?: Member
|
||||
/** Users specifically mentioned in the message Note: The user objects in the mentions array will only have the partial member field present in MESSAGE_CREATE and MESSAGE_UPDATE events from text-based guild channels. */
|
||||
mentions?: User[]
|
||||
/** Channels specifically mentioned in this message Note: Not all channel mentions in a message will appear in mention_channels. Only textual channels that are visible to everyone in a lurkable guild will ever be included. Only crossposted messages (via Channel Following) currently include mention_channels at all. If no mentions in the message meet these requirements, this field will not be sent. */
|
||||
mentionedChannelIds?: bigint[]
|
||||
/** Roles specifically mentioned in this message */
|
||||
mentionedRoleIds?: bigint[]
|
||||
/** Data showing the source of a crossposted channel follow add, pin or reply message */
|
||||
messageReference?: {
|
||||
/** id of the originating message's channel Note: channel_id is optional when creating a reply, but will always be present when receiving an event/response that includes this data model. */
|
||||
channelId?: bigint
|
||||
/** id of the originating message's guild */
|
||||
guildId?: bigint
|
||||
/** id of the originating message */
|
||||
messageId?: bigint
|
||||
}
|
||||
/** Used for validating a message was sent */
|
||||
nonce?: string | number
|
||||
/** Reactions on this message. */
|
||||
reactions?: Array<{
|
||||
/** Whether the current user reacted using this emoji */
|
||||
me: boolean
|
||||
/** Times this emoji has been used to react */
|
||||
count: number
|
||||
/** Emoji information */
|
||||
emoji: Emoji
|
||||
}>
|
||||
/** Sent if the message contains stickers */
|
||||
stickerItems?: Array<{
|
||||
/** The id of this sticker. */
|
||||
id: bigint
|
||||
/** The name of this sticker. */
|
||||
name: string
|
||||
/** The type of this stickers format. */
|
||||
formatType: StickerFormatTypes
|
||||
}>
|
||||
/** Type of message */
|
||||
type: MessageTypes
|
||||
/** The thread that was started from this message, includes thread member object */
|
||||
thread?: Channel
|
||||
/** If the message is generated by a webhook, this is the webhook's id */
|
||||
webhookId?: bigint
|
||||
}
|
||||
|
||||
const EMPTY_STRING = ''
|
||||
|
||||
export function transformMessage(bot: Bot, payload: DiscordMessage): Message {
|
||||
const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined
|
||||
const userId = bot.transformers.snowflake(payload.author.id)
|
||||
|
||||
const message = {
|
||||
// UNTRANSFORMED STUFF HERE
|
||||
content: payload.content ?? '',
|
||||
isFromBot: payload.author.bot ?? false,
|
||||
tag: `${payload.author.username}#${payload.author.discriminator}`,
|
||||
timestamp: Date.parse(payload.timestamp),
|
||||
editedTimestamp: payload.edited_timestamp ? Date.parse(payload.edited_timestamp) : undefined,
|
||||
bitfield: (payload.tts ? 1n : 0n) | (payload.mention_everyone ? 2n : 0n) | (payload.pinned ? 4n : 0n),
|
||||
attachments: payload.attachments?.map((attachment) => bot.transformers.attachment(bot, attachment)),
|
||||
embeds: payload.embeds?.map((embed) => bot.transformers.embed(bot, embed)),
|
||||
reactions: payload.reactions?.map((reaction) => ({
|
||||
me: reaction.me,
|
||||
count: reaction.count,
|
||||
emoji: bot.transformers.emoji(bot, reaction.emoji),
|
||||
})),
|
||||
type: payload.type,
|
||||
activity: payload.activity
|
||||
? {
|
||||
type: payload.activity.type,
|
||||
partyId: payload.activity.party_id,
|
||||
}
|
||||
: undefined,
|
||||
application: payload.application,
|
||||
flags: payload.flags,
|
||||
interaction: payload.interaction
|
||||
? {
|
||||
id: bot.transformers.snowflake(payload.interaction.id),
|
||||
type: payload.interaction.type,
|
||||
name: payload.interaction.name,
|
||||
user: bot.transformers.user(bot, payload.interaction.user),
|
||||
member: payload.interaction.member
|
||||
? {
|
||||
id: userId,
|
||||
guildId,
|
||||
nick: payload.interaction.member.nick ?? undefined,
|
||||
roles: payload.interaction.member.roles?.map((id) => bot.transformers.snowflake(id)),
|
||||
joinedAt: payload.interaction.member.joined_at ? Date.parse(payload.interaction.member.joined_at) : undefined,
|
||||
premiumSince: payload.interaction.member.premium_since ? Date.parse(payload.interaction.member.premium_since) : undefined,
|
||||
toggles: new MemberToggles(payload.interaction.member),
|
||||
avatar: payload.interaction.member.avatar ? iconHashToBigInt(payload.interaction.member.avatar) : undefined,
|
||||
permissions: payload.interaction.member.permissions ? bot.transformers.snowflake(payload.interaction.member.permissions) : undefined,
|
||||
communicationDisabledUntil: payload.interaction.member.communication_disabled_until
|
||||
? Date.parse(payload.interaction.member.communication_disabled_until)
|
||||
: undefined,
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
: undefined,
|
||||
thread: payload.thread ? bot.transformers.channel(bot, { channel: payload.thread, guildId }) : undefined,
|
||||
components: payload.components?.map((component) => bot.transformers.component(bot, component)),
|
||||
stickerItems: payload.sticker_items?.map((sticker) => ({
|
||||
id: bot.transformers.snowflake(sticker.id),
|
||||
name: sticker.name,
|
||||
formatType: sticker.format_type,
|
||||
})),
|
||||
const message: Message = Object.create(baseMessage)
|
||||
message.bitfield = new ToggleBitfield()
|
||||
message.flags = new ToggleBitfield(payload.flags)
|
||||
|
||||
// TRANSFORMED STUFF BELOW
|
||||
id: bot.transformers.snowflake(payload.id),
|
||||
guildId,
|
||||
channelId: bot.transformers.snowflake(payload.channel_id),
|
||||
webhookId: payload.webhook_id ? bot.transformers.snowflake(payload.webhook_id) : undefined,
|
||||
authorId: userId,
|
||||
applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined,
|
||||
messageReference: payload.message_reference
|
||||
? {
|
||||
messageId: payload.message_reference.message_id ? bot.transformers.snowflake(payload.message_reference.message_id) : undefined,
|
||||
channelId: payload.message_reference.channel_id ? bot.transformers.snowflake(payload.message_reference.channel_id) : undefined,
|
||||
guildId: payload.message_reference.guild_id ? bot.transformers.snowflake(payload.message_reference.guild_id) : undefined,
|
||||
}
|
||||
: undefined,
|
||||
mentionedUserIds: payload.mentions ? payload.mentions.map((m) => bot.transformers.snowflake(m.id)) : [],
|
||||
mentionedRoleIds: payload.mention_roles ? payload.mention_roles.map((id) => bot.transformers.snowflake(id)) : [],
|
||||
mentionedChannelIds: [
|
||||
const props = bot.transformers.desiredProperties.message
|
||||
|
||||
if (props.author && props.author) message.author = bot.transformers.user(bot, payload.author)
|
||||
if (payload.application_id && props.applicationId) message.applicationId = bot.transformers.snowflake(payload.application_id)
|
||||
if (payload.attachments?.length && props.attachments) {
|
||||
message.attachments = payload.attachments.map((attachment) => bot.transformers.attachment(bot, attachment))
|
||||
}
|
||||
if (props.channelId && props.channelId) message.channelId = bot.transformers.snowflake(payload.channel_id)
|
||||
if (props.components && payload.components?.length) message.components = payload.components.map((comp) => bot.transformers.component(bot, comp))
|
||||
if (props.content && props.content) message.content = payload.content ?? EMPTY_STRING
|
||||
if (payload.edited_timestamp && props.editedTimestamp) message.editedTimestamp = Date.parse(payload.edited_timestamp)
|
||||
if (payload.embeds?.length && props.embeds) message.embeds = payload.embeds.map((embed) => bot.transformers.embed(bot, embed))
|
||||
if (guildId && props.guildId) message.guildId = guildId
|
||||
if (props.id && payload.id) message.id = bot.transformers.snowflake(payload.id)
|
||||
if (payload.interaction) {
|
||||
const interaction = {} as NonNullable<Message['interaction']>
|
||||
let edited = false
|
||||
if (props.interaction.id) {
|
||||
interaction.id = bot.transformers.snowflake(payload.interaction.id)
|
||||
edited = true
|
||||
}
|
||||
if (props.interaction.member && payload.interaction.member) {
|
||||
// @ts-expect-error TODO: partial - check why this is partial and handle as needed
|
||||
interaction.member = bot.transformers.member(bot, payload.interaction.member, guildId, payload.interaction.user.id)
|
||||
edited = true
|
||||
}
|
||||
if (props.interaction.name) {
|
||||
interaction.name = payload.interaction.name
|
||||
edited = true
|
||||
}
|
||||
if (props.interaction.type) {
|
||||
interaction.type = payload.interaction.type
|
||||
edited = true
|
||||
}
|
||||
if (props.interaction.user) {
|
||||
interaction.user = bot.transformers.user(bot, payload.interaction.user)
|
||||
edited = true
|
||||
}
|
||||
|
||||
if (edited) message.interaction = interaction
|
||||
}
|
||||
if (props.member && payload.member && guildId) message.member = bot.transformers.member(bot, payload.member, guildId, userId)
|
||||
if (payload.mention_everyone) message.mentionEveryone = true
|
||||
if (props.mentionedChannelIds && payload.mention_channels?.length) {
|
||||
message.mentionedChannelIds = [
|
||||
// Keep any ids tht discord sends
|
||||
...(payload.mention_channels ?? []).map((m) => bot.transformers.snowflake(m.id)),
|
||||
// Add any other ids that can be validated in a channel mention format
|
||||
@@ -89,12 +309,52 @@ export function transformMessage(bot: Bot, payload: DiscordMessage) {
|
||||
// converts the <#123> into 123
|
||||
bot.transformers.snowflake(text.substring(2, text.length - 1)),
|
||||
),
|
||||
],
|
||||
member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined,
|
||||
nonce: payload.nonce,
|
||||
]
|
||||
}
|
||||
if (props.mentionedRoleIds && payload.mention_roles?.length) {
|
||||
message.mentionedRoleIds = payload.mention_roles.map((id) => bot.transformers.snowflake(id))
|
||||
}
|
||||
if (props.mentions && payload.mentions?.length) {
|
||||
message.mentions = payload.mentions.map((user) => bot.transformers.user(bot, user))
|
||||
}
|
||||
if (payload.message_reference) {
|
||||
const reference = {} as NonNullable<Message['messageReference']>
|
||||
let edited = false
|
||||
|
||||
return message as Optionalize<typeof message>
|
||||
if (props.messageReference.channelId && payload.message_reference.channel_id) {
|
||||
reference.channelId = bot.transformers.snowflake(payload.message_reference.channel_id)
|
||||
edited = true
|
||||
}
|
||||
if (props.messageReference.guildId && payload.message_reference.guild_id) {
|
||||
reference.guildId = bot.transformers.snowflake(payload.message_reference.guild_id)
|
||||
edited = true
|
||||
}
|
||||
if (props.messageReference.messageId && payload.message_reference.message_id) {
|
||||
reference.messageId = bot.transformers.snowflake(payload.message_reference.message_id)
|
||||
edited = true
|
||||
}
|
||||
|
||||
if (edited) message.messageReference = reference
|
||||
}
|
||||
if (payload.nonce && props.nonce) message.nonce = payload.nonce
|
||||
if (payload.pinned) message.pinned = true
|
||||
if (payload.reactions?.length && props.reactions) {
|
||||
message.reactions = payload.reactions.map((reaction) => ({
|
||||
me: reaction.me,
|
||||
count: reaction.count,
|
||||
emoji: bot.transformers.emoji(bot, reaction.emoji),
|
||||
}))
|
||||
}
|
||||
if (props.stickerItems && payload.sticker_items?.length)
|
||||
message.stickerItems = payload.sticker_items.map((item) => ({
|
||||
id: bot.transformers.snowflake(item.id),
|
||||
name: item.name,
|
||||
formatType: item.format_type,
|
||||
}))
|
||||
if (payload.tts) message.tts = true
|
||||
if (props.thread && payload.thread) message.thread = bot.transformers.channel(bot, { channel: payload.thread, guildId })
|
||||
if (props.type && props.type) message.type = payload.type
|
||||
if (payload.webhook_id && props.webhookId) message.webhookId = bot.transformers.snowflake(payload.webhook_id)
|
||||
|
||||
return bot.transformers.customizers.message(bot, payload, message)
|
||||
}
|
||||
|
||||
export interface Message extends ReturnType<typeof transformMessage> {}
|
||||
|
||||
@@ -21,6 +21,10 @@ export class ToggleBitfield {
|
||||
this.bitfield &= ~bits
|
||||
return this
|
||||
}
|
||||
|
||||
toJSON(): number {
|
||||
return this.bitfield;
|
||||
}
|
||||
}
|
||||
|
||||
export class ToggleBitfieldBigint {
|
||||
|
||||
@@ -202,3 +202,26 @@ export interface BotGatewayHandlerOptions {
|
||||
INTEGRATION_UPDATE: typeof handlers.handleIntegrationUpdate
|
||||
INTEGRATION_DELETE: typeof handlers.handleIntegrationDelete
|
||||
}
|
||||
|
||||
export enum MessageFlags {
|
||||
/** Whether this message has been published to subscribed channels (via Channel Following) */
|
||||
Crossposted = 1 << 0,
|
||||
/** Whether this message originated from a message in another channel (via Channel Following) */
|
||||
IsCrosspost = 1 << 1,
|
||||
/** Whether do not include any embeds when serializing this message */
|
||||
SuppressEmbeds = 1 << 2,
|
||||
/** Whether the source message for this crosspost has been deleted (via Channel Following) */
|
||||
SourceMessageDeleted = 1 << 3,
|
||||
/** Whether this message came from the urgent message system */
|
||||
Urgent = 1 << 4,
|
||||
/** Whether this message has an associated thread, with the same id as the message */
|
||||
HasThread = 1 << 5,
|
||||
/** Whether this message is only visible to the user who invoked the Interaction */
|
||||
Ephemeral = 1 << 6,
|
||||
/** Whether this message is an Interaction Response and the bot is "thinking" */
|
||||
Loading = 1 << 7,
|
||||
/** Whether this message failed to mention some roles and add their members to the thread */
|
||||
FailedToMentionSomeRolesInThread = 1 << 8,
|
||||
/** Whether this message will not trigger push and desktop notifications */
|
||||
SuppressNotifications = 1 << 12,
|
||||
}
|
||||
|
||||
@@ -7,3 +7,7 @@ export function snowflakeToBigint(snowflake: BigString): bigint {
|
||||
export function bigintToSnowflake(snowflake: BigString): string {
|
||||
return snowflake === 0n ? '' : snowflake.toString()
|
||||
}
|
||||
|
||||
export function snowflakeToTimestamp(id: bigint): number {
|
||||
return Number(id / 4194304n + 1420070400000n)
|
||||
}
|
||||
Reference in New Issue
Block a user