This commit is contained in:
Skillz4Killz
2021-10-26 01:29:25 +00:00
committed by GitHub
parent 6a9372c3ff
commit d60b36ff0a
8 changed files with 412 additions and 52 deletions
+6
View File
@@ -311,6 +311,8 @@ import { DiscordenoPresence, transformPresence } from "./transformers/presence.t
import { DiscordReady } from "./types/gateway/ready.ts";
import { urlToBase64 } from "./util/url_to_base64.ts";
import { transformAttachment } from "./transformers/attachment.ts";
import { transformEmbed } from "./transformers/embed.ts";
import { transformComponent } from "./transformers/component.ts";
export function createBot(options: CreateBotOptions) {
return {
@@ -1098,6 +1100,8 @@ export interface Transformers {
activity: typeof transformActivity;
presence: typeof transformPresence;
attachment: typeof transformAttachment;
embed: typeof transformEmbed;
component: typeof transformComponent;
}
export function createTransformers(options: Partial<Transformers>) {
@@ -1106,6 +1110,8 @@ export function createTransformers(options: Partial<Transformers>) {
application: options.application || transformApplication,
attachment: options.attachment || transformAttachment,
channel: options.channel || transformChannel,
component: options.component || transformComponent,
embed: options.embed || transformEmbed,
emoji: options.emoji || transformEmoji,
guild: options.guild || transformGuild,
integration: options.integration || transformIntegration,
+145
View File
@@ -0,0 +1,145 @@
import { Bot } from "../bot.ts";
import { ButtonStyles } from "../types/messages/components/button_styles.ts";
import { DiscordMessageComponentTypes } from "../types/messages/components/message_component_types.ts";
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
export function transformComponent(bot: Bot, payload: SnakeCasedPropertiesDeep<Component>): DiscordenoComponent {
return {
type: payload.type,
customId: payload.custom_id,
disabled: payload.disabled,
style: payload.style,
label: payload.label,
emoji: payload.emoji
? {
id: payload.emoji.id ? bot.transformers.snowflake(payload.emoji.id) : undefined,
name: payload.emoji.name,
animated: payload.emoji.animated,
}
: undefined,
url: payload.url,
options: payload.options?.map((option) => ({
label: option.label,
value: option.value,
description: option.description,
emoji: option.emoji
? {
id: option.emoji.id ? bot.transformers.snowflake(option.emoji.id) : undefined,
name: option.emoji.name,
animated: option.emoji.animated,
}
: undefined,
default: option.default,
})),
placeholder: payload.placeholder,
minValues: payload.min_values,
maxValues: payload.max_values,
components: payload.components?.map((component) => bot.transformers.component(bot, component)),
};
}
export interface Component {
/** component type */
type: DiscordMessageComponentTypes;
/** a developer-defined identifier for the component, max 100 characters */
customId?: string;
/** whether the component is disabled, default false */
disabled?: boolean;
/** For different styles/colors of the buttons */
style?: ButtonStyles;
/** text that appears on the button (max 80 characters) */
label?: string;
/** Emoji object that includes fields of name, id, and animated supporting unicode and custom emojis. */
emoji?: {
/** Emoji id */
id?: string;
/** Emoji name */
name?: string;
/** Whether this emoji is animated */
animated?: boolean;
};
/** optional url for link-style buttons that can navigate a user to the web. Only type 5 Link buttons can have a url */
url?: string;
/** The choices! Maximum of 25 items. */
options?: SelectOption[];
/** A custom placeholder text if nothing is selected. Maximum 100 characters. */
placeholder?: string;
/** The minimum number of items that must be selected. Default 1. Between 1-25. */
minValues?: number;
/** The maximum number of items that can be selected. Default 1. Between 1-25. */
maxValues?: number;
/** a list of child components */
components?: Component[];
}
export interface SelectOption {
/** The user-facing name of the option. Maximum 25 characters. */
label: string;
/** The dev-defined value of the option. Maximum 100 characters. */
value: string;
/** An additional description of the option. Maximum 50 characters. */
description?: string;
/** The id, name, and animated properties of an emoji. */
emoji?: {
/** Emoji id */
id?: string;
/** Emoji name */
name?: string;
/** Whether this emoji is animated */
animated?: boolean;
};
/** Will render this option as already-selected by default. */
default: boolean;
}
export interface DiscordenoComponent {
/** component type */
type: DiscordMessageComponentTypes;
/** a developer-defined identifier for the component, max 100 characters */
customId?: string;
/** whether the component is disabled, default false */
disabled?: boolean;
/** For different styles/colors of the buttons */
style?: ButtonStyles;
/** text that appears on the button (max 80 characters) */
label?: string;
/** Emoji object that includes fields of name, id, and animated supporting unicode and custom emojis. */
emoji?: {
/** Emoji id */
id?: bigint;
/** Emoji name */
name?: string;
/** Whether this emoji is animated */
animated?: boolean;
};
/** optional url for link-style buttons that can navigate a user to the web. Only type 5 Link buttons can have a url */
url?: string;
/** The choices! Maximum of 25 items. */
options?: {
/** The user-facing name of the option. Maximum 25 characters. */
label: string;
/** The dev-defined value of the option. Maximum 100 characters. */
value: string;
/** An additional description of the option. Maximum 50 characters. */
description?: string;
/** The id, name, and animated properties of an emoji. */
emoji?: {
/** Emoji id */
id?: bigint;
/** Emoji name */
name?: string;
/** Whether this emoji is animated */
animated?: boolean;
};
/** Will render this option as already-selected by default. */
default: boolean;
}[];
/** A custom placeholder text if nothing is selected. Maximum 100 characters. */
placeholder?: string;
/** The minimum number of items that must be selected. Default 1. Between 1-25. */
minValues?: number;
/** The maximum number of items that can be selected. Default 1. Between 1-25. */
maxValues?: number;
/** a list of child components */
components?: Component[];
}
+149
View File
@@ -0,0 +1,149 @@
import { Bot } from "../bot.ts";
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
import { DiscordEmbedTypes } from "../types/embeds/embed_types.ts";
import { Embed } from "../types/embeds/embed.ts";
export function transformEmbed(bot: Bot, payload: SnakeCasedPropertiesDeep<Embed>): DiscordenoEmbed {
return {
title: payload.title,
type: payload.type,
description: payload.description,
url: payload.url,
timestamp: payload.timestamp ? Date.parse(payload.timestamp) : undefined,
color: payload.color,
footer: payload.footer
? {
text: payload.footer.text,
iconUrl: payload.footer.icon_url,
proxyIconUrl: payload.footer.proxy_icon_url,
}
: undefined,
image: payload.image
? {
url: payload.image.url,
proxyUrl: payload.image.proxy_url,
height: payload.image.height,
width: payload.image.width,
}
: undefined,
thumbnail: payload.thumbnail
? {
url: payload.thumbnail.url,
proxyUrl: payload.thumbnail.proxy_url,
height: payload.thumbnail.height,
width: payload.thumbnail.width,
}
: undefined,
video: payload.video
? {
url: payload.video.url,
proxyUrl: payload.video.proxy_url,
height: payload.video.height,
width: payload.video.width,
}
: undefined,
provider: payload.provider
? {
name: payload.provider.name,
url: payload.provider.url,
}
: undefined,
author: payload.author
? {
name: payload.author.name,
url: payload.author.url,
iconUrl: payload.author.icon_url,
proxyIconUrl: payload.author.proxy_icon_url,
}
: undefined,
fields: payload.fields?.map((field) => ({
name: field.name,
value: field.value,
inline: field.inline,
})),
};
}
export interface DiscordenoEmbed {
/** Title of embed */
title?: string;
/** Type of embed (always "rich" for webhook embeds) */
type?: DiscordEmbedTypes;
/** Description of embed */
description?: string;
/** Url of embed */
url?: string;
/** Timestamp of embed content */
timestamp?: number;
/** Color code of the embed */
color?: number;
/** Footer information */
footer?: {
/** Footer text */
text: string;
/** Url of footer icon (only supports http(s) and attachments) */
iconUrl?: string;
/** A proxied url of footer icon */
proxyIconUrl?: string;
};
/** Image information */
image?: {
/** Source url of image (only supports http(s) and attachments) */
url?: string;
/** A proxied url of the image */
proxyUrl?: string;
/** Height of image */
height?: number;
/** Width of image */
width?: number;
};
/** Thumbnail information */
thumbnail?: {
/** Source url of thumbnail (only supports http(s) and attachments) */
url?: string;
/** A proxied url of the thumbnail */
proxyUrl?: string;
/** Height of thumbnail */
height?: number;
/** Width of thumbnail */
width?: number;
};
/** Video information */
video?: {
/** Source url of video */
url?: string;
/** A proxied url of the video */
proxyUrl?: string;
/** Height of video */
height?: number;
/** Width of video */
width?: number;
};
/** Provider information */
provider?: {
/** Name of provider */
name?: string;
/** Url of provider */
url?: string;
};
/** Author information */
author?: {
/** Name of author */
name?: string;
/** Url of author */
url?: string;
/** Url of author icon (only supports http(s) and attachments) */
iconUrl?: string;
/** A proxied url of author icon */
proxyIconUrl?: string;
};
/** Fields information */
fields?: {
/** Name of the field */
name: string;
/** Value of the field */
value: string;
/** Whether or not this field should display inline */
inline?: boolean;
}[];
}
+5 -4
View File
@@ -1,5 +1,5 @@
import type { Bot } from "../bot.ts";
import type { GuildMemberWithUser } from "../types/members/guild_member.ts";
import type { GuildMember, GuildMemberWithUser } from "../types/members/guild_member.ts";
import type { DiscordPremiumTypes } from "../types/users/premium_types.ts";
import type { User } from "../types/users/user.ts";
import type { DiscordUserFlags } from "../types/users/user_flags.ts";
@@ -41,11 +41,12 @@ export function transformUser(bot: Bot, payload: SnakeCasedPropertiesDeep<User>)
export function transformMember(
bot: Bot,
payload: SnakeCasedPropertiesDeep<GuildMemberWithUser>,
guildId: bigint
payload: SnakeCasedPropertiesDeep<GuildMember>,
guildId: bigint,
userId: bigint
): DiscordenoMember {
return {
id: bot.transformers.snowflake(payload.user.id),
id: userId,
guildId,
nick: payload.nick ?? undefined,
roles: payload.roles.map((id) => BigInt(id)),
+90 -27
View File
@@ -4,8 +4,20 @@ import { CHANNEL_MENTION_REGEX } from "../util/constants.ts";
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
import { DiscordenoAttachment } from "./attachment.ts";
import { DiscordMessageStickerFormatTypes } from "../types/messages/message_sticker_format_types.ts";
import { DiscordenoMember, DiscordenoUser } from "./member.ts";
import { DiscordenoEmbed } from "./embed.ts";
import { DiscordMessageTypes } from "../types/messages/message_types.ts";
import { DiscordMessageActivityTypes } from "../types/messages/message_activity_types.ts";
import { DiscordInteractionTypes } from "../types/interactions/interaction_types.ts";
import { DiscordMessageComponentTypes } from "../types/messages/components/message_component_types.ts";
import { ButtonStyles } from "../types/messages/components/button_styles.ts";
import { DiscordenoComponent } from "./component.ts";
import { Application } from "../types/applications/application.ts";
export function transformMessage(bot: Bot, data: SnakeCasedPropertiesDeep<Message>): DiscordenoMessage {
const guildId = data.guild_id ? bot.transformers.snowflake(data.guild_id) : undefined;
const userId = bot.transformers.snowflake(data.author.id);
return {
// UNTRANSFORMED STUFF HERE
content: data.content || "",
@@ -15,15 +27,35 @@ export function transformMessage(bot: Bot, data: SnakeCasedPropertiesDeep<Messag
editedTimestamp: data.edited_timestamp ? Date.parse(data.edited_timestamp) : undefined,
bitfield: (data.tts ? 1n : 0n) | (data.mention_everyone ? 2n : 0n) | (data.pinned ? 4n : 0n),
attachments: data.attachments.map((attachment) => bot.transformers.attachment(bot, attachment)),
embeds: data.embeds,
reactions: data.reactions,
embeds: data.embeds.map((embed) => bot.transformers.embed(bot, embed)),
reactions: data.reactions?.map((reaction) => ({
me: reaction.me,
count: reaction.count,
emoji: {
id: reaction.emoji.id ? bot.transformers.snowflake(reaction.emoji.id) : undefined,
name: reaction.emoji.name,
animated: reaction.emoji.animated,
},
})),
type: data.type,
activity: data.activity,
activity: data.activity
? {
type: data.activity.type,
partyId: data.activity.party_id,
}
: undefined,
application: data.application,
flags: data.flags,
interaction: data.interaction,
interaction: data.interaction
? {
id: bot.transformers.snowflake(data.interaction.id),
type: data.interaction.type,
name: data.interaction.name,
user: bot.transformers.user(bot, data.interaction.user),
}
: undefined,
thread: data.thread,
components: data.components,
components: data.components?.map((component) => bot.transformers.component(bot, component)),
stickerItems: data.sticker_items?.map((sticker) => ({
id: bot.transformers.snowflake(sticker.id),
name: sticker.name,
@@ -32,10 +64,10 @@ export function transformMessage(bot: Bot, data: SnakeCasedPropertiesDeep<Messag
// TRANSFORMED STUFF BELOW
id: bot.transformers.snowflake(data.id),
guildId: data.guild_id ? bot.transformers.snowflake(data.guild_id) : undefined,
guildId,
channelId: bot.transformers.snowflake(data.channel_id),
webhookId: data.webhook_id ? bot.transformers.snowflake(data.webhook_id) : undefined,
authorId: bot.transformers.snowflake(data.author.id),
authorId: userId,
applicationId: data.application_id ? bot.transformers.snowflake(data.application_id) : undefined,
messageReference: data.message_reference
? {
@@ -61,29 +93,11 @@ export function transformMessage(bot: Bot, data: SnakeCasedPropertiesDeep<Messag
bot.transformers.snowflake(text.substring(2, text.length - 1))
),
],
member: data.member && guildId ? bot.transformers.member(bot, data.member, guildId, userId) : undefined,
};
}
export interface DiscordenoMessage
extends Omit<
Message,
| "id"
| "webhookId"
| "timestamp"
| "editedTimestamp"
| "guildId"
| "channelId"
| "member"
| "author"
| "applicationId"
| "thread"
| "tts"
| "pinned"
| "mentionEveryone"
| "attachments"
| "messageReference"
| "stickerItems"
> {
export interface DiscordenoMessage {
id: bigint;
/** Whether or not this message was sent by a bot */
isBot: boolean;
@@ -136,4 +150,53 @@ export interface DiscordenoMessage
/** Type of sticker format */
formatType: DiscordMessageStickerFormatTypes;
}[];
/**
* 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?: DiscordenoMember;
/** Any embedded content */
embeds: DiscordenoEmbed[];
/** Reactions to the message */
reactions?: {
me: boolean;
count: number;
emoji: { id?: bigint; name?: string; animated?: boolean };
}[];
/** Used for validating a message was sent */
nonce?: number | string;
/** Type of message */
type: DiscordMessageTypes;
/** Sent with Rich Presence-related chat embeds */
activity?: {
/** Type of message activity */
type: DiscordMessageActivityTypes;
/** `party_id` from a Rich Presence event */
partyId?: string;
};
/** Sent with Rich Presence-related chat embeds */
application?: Partial<SnakeCasedPropertiesDeep<Application>>;
/** Message flags combined as a bitfield */
flags?: number;
/**
* The message associated with the `message_reference`
* Note: This field is only returned for messages with a `type` of `19` (REPLY). If the message is a reply but the `referenced_message` field is not present, the backend did not attempt to fetch the message that was being replied to, so its state is unknown. If the field exists but is null, the referenced message was deleted.
*/
referencedMessage?: Message | null;
/** Sent if the message is a response to an Interaction */
interaction?: {
/** Id of the interaction */
id: bigint;
/** The type of interaction */
type: DiscordInteractionTypes;
/** The name of the ApplicationCommand */
name: string;
/** The user who invoked the interaction */
user: DiscordenoUser;
};
/** The thread that was started from this message, includes thread member object */
thread?: Omit<Channel, "member"> & { member: ThreadMember };
/** The components related to this message */
components?: DiscordenoComponent[];
}
@@ -13,9 +13,7 @@ export interface ButtonComponent {
/** For different styles/colors of the buttons */
style: ButtonStyles;
/** Emoji object that includes fields of name, id, and animated supporting unicode and custom emojis. */
emoji?:
| string
| {
emoji?: {
/** Emoji id */
id?: string;
/** Emoji name */
@@ -7,9 +7,7 @@ export interface SelectOption {
/** An additional description of the option. Maximum 50 characters. */
description?: string;
/** The id, name, and animated properties of an emoji. */
emoji?:
| string
| {
emoji?: {
/** Emoji id */
id?: string;
/** Emoji name */
+1 -1
View File
@@ -32,7 +32,7 @@ export interface Message {
* 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?: Partial<GuildMember>;
member?: GuildMember;
/** Contents of the message */
content?: string;
/** When this message was sent */