mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-04 09:50:07 +00:00
Merge branch 'discordeno:main' into main
This commit is contained in:
21
src/bot.ts
21
src/bot.ts
@@ -85,12 +85,13 @@ import { StatusUpdate } from "./types/gateway/statusUpdate.ts";
|
||||
import { calculateBits, calculatePermissions } from "./util/permissions.ts";
|
||||
import { transformScheduledEvent } from "./transformers/scheduledEvent.ts";
|
||||
import { DiscordenoScheduledEvent } from "./transformers/scheduledEvent.ts";
|
||||
import { transformThreadMember } from "./transformers/threadMember.ts";
|
||||
import { DiscordenoThreadMember, transformThreadMember } from "./transformers/threadMember.ts";
|
||||
import { transformApplicationCommandOption } from "./transformers/applicationCommandOption.ts";
|
||||
import { transformApplicationCommand } from "./transformers/applicationCommand.ts";
|
||||
import { transformWelcomeScreen } from "./transformers/welcomeScreen.ts";
|
||||
import { transformVoiceRegion } from "./transformers/voiceRegion.ts";
|
||||
import { transformWidget } from "./transformers/widget.ts";
|
||||
import { transformStageInstance } from "./transformers/stageInstance.ts";
|
||||
|
||||
export function createBot(options: CreateBotOptions): Bot {
|
||||
const bot = {
|
||||
@@ -141,6 +142,10 @@ export function createEventHandlers(events: Partial<EventHandlers>): EventHandle
|
||||
|
||||
return {
|
||||
debug: events.debug ?? ignore,
|
||||
threadCreate: events.threadCreate ?? ignore,
|
||||
threadDelete: events.threadDelete ?? ignore,
|
||||
threadMembersUpdate: events.threadMembersUpdate ?? ignore,
|
||||
threadUpdate: events.threadUpdate ?? ignore,
|
||||
scheduledEventCreate: events.scheduledEventCreate ?? ignore,
|
||||
scheduledEventUpdate: events.scheduledEventUpdate ?? ignore,
|
||||
scheduledEventDelete: events.scheduledEventDelete ?? ignore,
|
||||
@@ -484,6 +489,7 @@ export interface Transformers {
|
||||
welcomeScreen: typeof transformWelcomeScreen;
|
||||
voiceRegion: typeof transformVoiceRegion;
|
||||
widget: typeof transformWidget;
|
||||
stageInstance: typeof transformStageInstance;
|
||||
}
|
||||
|
||||
export function createTransformers(options: Partial<Transformers>) {
|
||||
@@ -517,6 +523,7 @@ export function createTransformers(options: Partial<Transformers>) {
|
||||
welcomeScreen: options.welcomeScreen || transformWelcomeScreen,
|
||||
voiceRegion: options.voiceRegion || transformVoiceRegion,
|
||||
widget: options.widget || transformWidget,
|
||||
stageInstance: options.stageInstance || transformStageInstance,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -627,6 +634,18 @@ export interface GatewayManager {
|
||||
|
||||
export interface EventHandlers {
|
||||
debug: (text: string, ...args: any[]) => unknown;
|
||||
threadCreate: (bot: Bot, thread: DiscordenoChannel) => unknown;
|
||||
threadDelete: (bot: Bot, thread: DiscordenoChannel) => unknown;
|
||||
threadMembersUpdate: (
|
||||
bot: Bot,
|
||||
payload: {
|
||||
id: bigint;
|
||||
guildId: bigint;
|
||||
addedMembers?: DiscordenoThreadMember[];
|
||||
removedMemberIds?: bigint[];
|
||||
}
|
||||
) => unknown;
|
||||
threadUpdate: (bot: Bot, thread: DiscordenoChannel) => unknown;
|
||||
scheduledEventCreate: (bot: Bot, event: DiscordenoScheduledEvent) => unknown;
|
||||
scheduledEventUpdate: (bot: Bot, event: DiscordenoScheduledEvent) => unknown;
|
||||
scheduledEventDelete: (bot: Bot, event: DiscordenoScheduledEvent) => unknown;
|
||||
|
||||
@@ -6,5 +6,5 @@ import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||
export async function handleThreadCreate(bot: Bot, data: DiscordGatewayPayload) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<Channel>;
|
||||
|
||||
// bot.events.threadCreate(bot, payload);
|
||||
bot.events.threadCreate(bot, bot.transformers.channel(bot, { channel: payload }));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { Bot } from "../../bot.ts";
|
||||
import { Channel } from "../../types/channels/channel.ts";
|
||||
import { DiscordGatewayPayload } from "../../types/gateway/gatewayPayload.ts";
|
||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
||||
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||
|
||||
export async function handleThreadDelete(data: DiscordGatewayPayload) {
|
||||
// const payload = data.d as Channel;
|
||||
// const cachedChannel = await cacheHandlers.get("threads", snowflakeToBigint(payload.id));
|
||||
// if (!cachedChannel) return;
|
||||
// await cacheHandlers.delete("threads", snowflakeToBigint(payload.id));
|
||||
// await cacheHandlers.forEach("DELETE_MESSAGES_FROM_CHANNEL", { channelId: snowflakeToBigint(payload.id) });
|
||||
// eventHandlers.threadDelete?.(cachedChannel);
|
||||
export async function handleThreadDelete(bot: Bot, data: DiscordGatewayPayload) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<Channel>;
|
||||
bot.events.threadDelete(bot, bot.transformers.channel(bot, { channel: payload }));
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import { Bot } from "../../bot.ts";
|
||||
import { ThreadListSync } from "../../types/channels/threads/threadListSync.ts";
|
||||
import { DiscordGatewayPayload } from "../../types/gateway/gatewayPayload.ts";
|
||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
||||
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||
import { Collection } from "../../util/collection.ts";
|
||||
|
||||
export async function handleThreadListSync(data: DiscordGatewayPayload) {
|
||||
// const payload = data.d as ThreadListSync;
|
||||
// const threads = await Promise.all(
|
||||
// payload.threads.map(async (thread) => {
|
||||
// const threadData = channelToThread(thread);
|
||||
// await cacheHandlers.set("threads", threadData.id, threadData);
|
||||
// return threadData;
|
||||
// })
|
||||
// );
|
||||
// eventHandlers.threadListSync?.(
|
||||
// new Collection(threads.map((t) => [t.id, t])),
|
||||
// payload.members.map((member) => threadMemberModified(member)),
|
||||
// snowflakeToBigint(payload.guildId)
|
||||
// );
|
||||
export async function handleThreadListSync(bot: Bot, data: DiscordGatewayPayload) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<ThreadListSync>;
|
||||
|
||||
const guildId = bot.transformers.snowflake(payload.guild_id);
|
||||
return {
|
||||
guildId,
|
||||
channelIds: payload.channel_ids?.map((id) => bot.transformers.snowflake(id)),
|
||||
threads: payload.threads.map((thread) => bot.transformers.channel(bot, { channel: thread, guildId })),
|
||||
members: payload.members.map((member) => ({
|
||||
id: member.id ? bot.transformers.snowflake(member.id) : undefined,
|
||||
userId: member.user_id ? bot.transformers.snowflake(member.user_id) : undefined,
|
||||
joinTimestamp: Date.parse(member.join_timestamp),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { Bot } from "../../bot.ts";
|
||||
import { ThreadMembersUpdate } from "../../types/channels/threads/threadMembersUpdate.ts";
|
||||
import { DiscordGatewayPayload } from "../../types/gateway/gatewayPayload.ts";
|
||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
||||
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||
|
||||
export async function handleThreadMembersUpdate(data: DiscordGatewayPayload) {
|
||||
// const payload = data.d as ThreadMembersUpdate;
|
||||
// const thread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id));
|
||||
// if (!thread) return;
|
||||
// thread.memberCount = payload.memberCount;
|
||||
// await cacheHandlers.set("threads", thread.id, thread);
|
||||
// eventHandlers.threadMembersUpdate?.(threadMembersUpdateModified(payload));
|
||||
export async function handleThreadMembersUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<ThreadMembersUpdate>;
|
||||
bot.events.threadMembersUpdate(bot, {
|
||||
id: bot.transformers.snowflake(payload.id),
|
||||
guildId: bot.transformers.snowflake(payload.guild_id),
|
||||
addedMembers: payload.added_members?.map((member) => bot.transformers.threadMember(bot, member)),
|
||||
removedMemberIds: payload.removed_member_ids?.map((id) => bot.transformers.snowflake(id)),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,19 +1,7 @@
|
||||
import { ThreadMember } from "../../types/channels/threads/threadMember.ts";
|
||||
import { Bot } from "../../bot.ts";
|
||||
import { DiscordGatewayPayload } from "../../types/gateway/gatewayPayload.ts";
|
||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
||||
|
||||
export async function handleThreadMemberUpdate(data: DiscordGatewayPayload) {
|
||||
// const payload = data.d as ThreadMember;
|
||||
// // The id field is omitted from the thread member dispatched within the GUILD_CREATE gateway event.
|
||||
// const thread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id!));
|
||||
// if (!thread) return;
|
||||
// thread.botIsMember = true;
|
||||
// await cacheHandlers.set("threads", thread.id, thread);
|
||||
// const member = {
|
||||
// ...payload,
|
||||
// id: snowflakeToBigint(payload.id!),
|
||||
// userId: snowflakeToBigint(payload.userId!),
|
||||
// joinTimestamp: Date.parse(payload.joinTimestamp),
|
||||
// };
|
||||
// eventHandlers.threadMemberUpdate?.(member, thread);
|
||||
export async function handleThreadMemberUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||
// This event is documented for completeness, but unlikely to be used by most bots
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { Bot } from "../../bot.ts";
|
||||
import { Channel } from "../../types/channels/channel.ts";
|
||||
import { DiscordGatewayPayload } from "../../types/gateway/gatewayPayload.ts";
|
||||
import { snowflakeToBigint } from "../../util/bigint.ts";
|
||||
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||
|
||||
export async function handleThreadUpdate(data: DiscordGatewayPayload) {
|
||||
// const payload = data.d as Channel;
|
||||
// const oldThread = await cacheHandlers.get("threads", snowflakeToBigint(payload.id));
|
||||
// if (!oldThread) return;
|
||||
// const thread = channelToThread(payload);
|
||||
// await cacheHandlers.set("threads", thread.id, thread);
|
||||
// eventHandlers.threadUpdate?.(thread, oldThread);
|
||||
export async function handleThreadUpdate(bot: Bot, data: DiscordGatewayPayload) {
|
||||
const payload = data.d as SnakeCasedPropertiesDeep<Channel>;
|
||||
|
||||
bot.events.threadUpdate(bot, bot.transformers.channel(bot, { channel: payload }));
|
||||
}
|
||||
|
||||
@@ -10,10 +10,5 @@ export async function createStageInstance(bot: Bot, channelId: bigint, topic: st
|
||||
privacy_level: privacyLevel || PrivacyLevel.GuildOnly,
|
||||
});
|
||||
|
||||
return {
|
||||
id: bot.transformers.snowflake(result.id),
|
||||
guildId: bot.transformers.snowflake(result.guild_id),
|
||||
channelId: bot.transformers.snowflake(result.channel_id),
|
||||
topic: result.topic,
|
||||
};
|
||||
return bot.transformers.stageInstance(bot, result);
|
||||
}
|
||||
|
||||
@@ -9,10 +9,5 @@ export async function getStageInstance(bot: Bot, channelId: bigint) {
|
||||
bot.constants.endpoints.STAGE_INSTANCE(channelId)
|
||||
);
|
||||
|
||||
return {
|
||||
id: bot.transformers.snowflake(result.id),
|
||||
guildId: bot.transformers.snowflake(result.guild_id),
|
||||
channelId: bot.transformers.snowflake(result.channel_id),
|
||||
topic: result.topic,
|
||||
};
|
||||
return bot.transformers.stageInstance(bot, result);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,5 @@ export async function updateStageInstance(bot: Bot, channelId: bigint, data: AtL
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
id: bot.transformers.snowflake(result.id),
|
||||
guildId: bot.transformers.snowflake(result.guild_id),
|
||||
channelId: bot.transformers.snowflake(result.channel_id),
|
||||
topic: result.topic,
|
||||
};
|
||||
return bot.transformers.stageInstance(bot, result);
|
||||
}
|
||||
|
||||
@@ -48,5 +48,7 @@ export async function getAuditLogs(bot: Bot, guildId: bigint, options?: GetGuild
|
||||
}
|
||||
: undefined,
|
||||
})),
|
||||
threads: auditlog.threads.map((thread) => bot.transformers.channel(bot, { channel: thread, guildId })),
|
||||
scheduledEvents: auditlog.scheduled_events.map((event) => bot.transformers.scheduledEvent(bot, event)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,20 +6,20 @@ import type { Bot } from "../../bot.ts";
|
||||
export function guildIconURL(
|
||||
bot: Bot,
|
||||
id: bigint,
|
||||
options: {
|
||||
icon?: string | bigint;
|
||||
icon: bigint | undefined,
|
||||
options?: {
|
||||
size?: ImageSize;
|
||||
format?: ImageFormat;
|
||||
}
|
||||
) {
|
||||
return options.icon
|
||||
return icon
|
||||
? bot.utils.formatImageURL(
|
||||
bot.constants.endpoints.GUILD_ICON(
|
||||
id,
|
||||
typeof options.icon === "string" ? options.icon : bot.utils.iconBigintToHash(options.icon)
|
||||
typeof icon === "string" ? icon : bot.utils.iconBigintToHash(icon)
|
||||
),
|
||||
options.size || 128,
|
||||
options.format
|
||||
options?.size || 128,
|
||||
options?.format
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
@@ -6,20 +6,20 @@ import type { Bot } from "../../bot.ts";
|
||||
export function guildSplashURL(
|
||||
bot: Bot,
|
||||
id: bigint,
|
||||
options: {
|
||||
splash?: string | bigint;
|
||||
splash: bigint | undefined,
|
||||
options?: {
|
||||
size?: ImageSize;
|
||||
format?: ImageFormat;
|
||||
}
|
||||
) {
|
||||
return options.splash
|
||||
return splash
|
||||
? bot.utils.formatImageURL(
|
||||
bot.constants.endpoints.GUILD_SPLASH(
|
||||
id,
|
||||
typeof options.splash === "string" ? options.splash : bot.utils.iconBigintToHash(options.splash)
|
||||
typeof splash === "string" ? splash : bot.utils.iconBigintToHash(splash)
|
||||
),
|
||||
options.size || 128,
|
||||
options.format
|
||||
options?.size || 128,
|
||||
options?.format
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,22 @@ export async function editInteractionResponse(bot: Bot, token: string, options:
|
||||
allowed_mentions: options.allowedMentions
|
||||
? {
|
||||
parse: options.allowedMentions.parse,
|
||||
roles: options.allowedMentions.roles,
|
||||
users: options.allowedMentions.users,
|
||||
roles: options.allowedMentions.roles?.map((id) => id.toString()),
|
||||
users: options.allowedMentions.users?.map((id) => id.toString()),
|
||||
replied_user: options.allowedMentions.repliedUser,
|
||||
}
|
||||
: undefined,
|
||||
attachments: options.attachments,
|
||||
attachments: options.attachments?.map((attachment) => ({
|
||||
id: attachment.id.toString(),
|
||||
filename: attachment.filename,
|
||||
content_type: attachment.contentType,
|
||||
size: attachment.size,
|
||||
url: attachment.url,
|
||||
proxy_url: attachment.proxyUrl,
|
||||
height: attachment.height,
|
||||
width: attachment.width,
|
||||
ephemeral: attachment.ephemeral,
|
||||
})),
|
||||
components: options.components?.map((component) => ({
|
||||
type: component.type,
|
||||
components: component.components.map((subcomponent) => {
|
||||
@@ -79,7 +89,7 @@ export async function editInteractionResponse(bot: Bot, token: string, options:
|
||||
};
|
||||
}),
|
||||
})),
|
||||
message_id: options.messageId,
|
||||
message_id: options.messageId?.toString(),
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -22,12 +22,22 @@ export async function editFollowupMessage(
|
||||
allowed_mentions: options.allowedMentions
|
||||
? {
|
||||
parse: options.allowedMentions.parse,
|
||||
roles: options.allowedMentions.roles,
|
||||
users: options.allowedMentions.users,
|
||||
roles: options.allowedMentions.roles?.map((id) => id.toString()),
|
||||
users: options.allowedMentions.users?.map((id) => id.toString()),
|
||||
replied_user: options.allowedMentions.repliedUser,
|
||||
}
|
||||
: undefined,
|
||||
attachments: options.attachments,
|
||||
attachments: options.attachments?.map((attachment) => ({
|
||||
id: attachment.id.toString(),
|
||||
filename: attachment.filename,
|
||||
content_type: attachment.contentType,
|
||||
size: attachment.size,
|
||||
url: attachment.url,
|
||||
proxy_url: attachment.proxyUrl,
|
||||
height: attachment.height,
|
||||
width: attachment.width,
|
||||
ephemeral: attachment.ephemeral,
|
||||
})),
|
||||
components: options.components?.map((component) => ({
|
||||
type: component.type,
|
||||
components: component.components.map((subcomponent) => {
|
||||
|
||||
@@ -7,20 +7,20 @@ export function avatarURL(
|
||||
bot: Bot,
|
||||
userId: bigint,
|
||||
discriminator: number,
|
||||
options: {
|
||||
avatar?: string | bigint;
|
||||
options?: {
|
||||
avatar: bigint | undefined;
|
||||
size?: ImageSize;
|
||||
format?: ImageFormat;
|
||||
}
|
||||
) {
|
||||
return options.avatar
|
||||
return options?.avatar
|
||||
? bot.utils.formatImageURL(
|
||||
bot.constants.endpoints.USER_AVATAR(
|
||||
userId,
|
||||
typeof options.avatar === "string" ? options.avatar : bot.utils.iconBigintToHash(options.avatar)
|
||||
typeof options?.avatar === "string" ? options.avatar : bot.utils.iconBigintToHash(options?.avatar)
|
||||
),
|
||||
options.size || 128,
|
||||
options.format
|
||||
options?.size || 128,
|
||||
options?.format
|
||||
)
|
||||
: bot.constants.endpoints.USER_DEFAULT_AVATAR(Number(discriminator) % 5);
|
||||
}
|
||||
|
||||
@@ -4,16 +4,8 @@ import type { Bot } from "../../bot.ts";
|
||||
import { MessageComponentTypes } from "../../types/messages/components/messageComponentTypes.ts";
|
||||
|
||||
/** Edit the message. */
|
||||
export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint, content: string | EditMessage) {
|
||||
if (typeof content === "string") content = { content };
|
||||
|
||||
content.embeds?.splice(10);
|
||||
|
||||
if (content.content && content.content.length > 2000) {
|
||||
throw new Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
|
||||
}
|
||||
|
||||
const result = await bot.rest.runMethod<Message>(
|
||||
export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint, content: EditMessage) {
|
||||
const result = await bot.rest.runMethod<Message>(
|
||||
bot.rest,
|
||||
"patch",
|
||||
bot.constants.endpoints.CHANNEL_MESSAGE(channelId, messageId),
|
||||
|
||||
@@ -5,36 +5,7 @@ import type { Bot } from "../../bot.ts";
|
||||
import { MessageComponentTypes } from "../../types/messages/components/messageComponentTypes.ts";
|
||||
|
||||
/** Send a message to the channel. Requires SEND_MESSAGES permission. */
|
||||
export async function sendMessage(bot: Bot, channelId: bigint, content: string | CreateMessage) {
|
||||
if (typeof content === "string") content = { content };
|
||||
|
||||
// Use ... for content length due to unicode characters and js .length handling
|
||||
if (content.content && !bot.utils.validateLength(content.content, { max: 2000 })) {
|
||||
throw new Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
|
||||
}
|
||||
|
||||
if (content.allowedMentions) {
|
||||
if (content.allowedMentions.users?.length) {
|
||||
if (content.allowedMentions.parse?.includes(AllowedMentionsTypes.UserMentions)) {
|
||||
content.allowedMentions.parse = content.allowedMentions.parse.filter((p) => p !== "users");
|
||||
}
|
||||
|
||||
if (content.allowedMentions.users.length > 100) {
|
||||
content.allowedMentions.users = content.allowedMentions.users.slice(0, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (content.allowedMentions.roles?.length) {
|
||||
if (content.allowedMentions.parse?.includes(AllowedMentionsTypes.RoleMentions)) {
|
||||
content.allowedMentions.parse = content.allowedMentions.parse.filter((p) => p !== "roles");
|
||||
}
|
||||
|
||||
if (content.allowedMentions.roles.length > 100) {
|
||||
content.allowedMentions.roles = content.allowedMentions.roles.slice(0, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendMessage(bot: Bot, channelId: bigint, content: CreateMessage) {
|
||||
const result = await bot.rest.runMethod<Message>(
|
||||
bot.rest,
|
||||
"post",
|
||||
@@ -170,3 +141,4 @@ export async function sendMessage(bot: Bot, channelId: bigint, content: string |
|
||||
|
||||
return bot.transformers.message(bot, result);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,24 +6,6 @@ import type { Bot } from "../../bot.ts";
|
||||
* NOTE: username: if changed may cause the bot's discriminator to be randomized.
|
||||
*/
|
||||
export async function editBotProfile(bot: Bot, options: { username?: string; botAvatarURL?: string | null }) {
|
||||
// Nothing was edited
|
||||
if (!options.username && options.botAvatarURL === undefined) return;
|
||||
// Check username requirements if username was provided
|
||||
if (options.username) {
|
||||
if (options.username.length > 32) {
|
||||
throw new Error(Errors.USERNAME_MAX_LENGTH);
|
||||
}
|
||||
if (options.username.length < 2) {
|
||||
throw new Error(Errors.USERNAME_MIN_LENGTH);
|
||||
}
|
||||
if (["@", "#", ":", "```"].some((char) => options.username!.includes(char))) {
|
||||
throw new Error(Errors.USERNAME_INVALID_CHARACTER);
|
||||
}
|
||||
if (["discordtag", "everyone", "here"].includes(options.username)) {
|
||||
throw new Error(Errors.USERNAME_INVALID_USERNAME);
|
||||
}
|
||||
}
|
||||
|
||||
const avatar = options?.botAvatarURL ? await bot.utils.urlToBase64(options?.botAvatarURL) : options?.botAvatarURL;
|
||||
|
||||
const result = await bot.rest.runMethod<User>(bot.rest, "patch", bot.constants.endpoints.USER_BOT, {
|
||||
|
||||
@@ -7,7 +7,7 @@ export function editBotStatus(bot: Bot, data: Omit<StatusUpdate, "afk" | "since"
|
||||
bot.events.debug(`Running forEach loop in editBotStatus function.`);
|
||||
|
||||
bot.gateway.sendShardMessage(bot.gateway, shard, {
|
||||
op: GatewayOpcodes.StatusUpdate,
|
||||
op: GatewayOpcodes.PresenceUpdate,
|
||||
d: {
|
||||
since: null,
|
||||
afk: false,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Application } from "../../types/applications/application.ts";
|
||||
import type { Bot } from "../../bot.ts";
|
||||
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||
|
||||
/** Get the applications info */
|
||||
export async function getApplicationInfo(bot: Bot) {
|
||||
|
||||
@@ -8,18 +8,15 @@ import type { Webhook } from "../../types/webhooks/webhook.ts";
|
||||
* Webhook names cannot be: 'clyde'
|
||||
*/
|
||||
export async function createWebhook(bot: Bot, channelId: bigint, options: CreateWebhook) {
|
||||
if (
|
||||
// Specific usernames that discord does not allow
|
||||
options.name === "clyde" ||
|
||||
!bot.utils.validateLength(options.name, { min: 2, max: 32 })
|
||||
) {
|
||||
throw new Error(bot.constants.Errors.INVALID_WEBHOOK_NAME);
|
||||
}
|
||||
|
||||
const result = await bot.rest.runMethod<Webhook>(bot.rest, "post", bot.constants.endpoints.CHANNEL_WEBHOOKS(channelId), {
|
||||
...options,
|
||||
avatar: options.avatar ? await bot.utils.urlToBase64(options.avatar) : undefined,
|
||||
});
|
||||
const result = await bot.rest.runMethod<Webhook>(
|
||||
bot.rest,
|
||||
"post",
|
||||
bot.constants.endpoints.CHANNEL_WEBHOOKS(channelId),
|
||||
{
|
||||
...options,
|
||||
avatar: options.avatar ? await bot.utils.urlToBase64(options.avatar) : undefined,
|
||||
}
|
||||
);
|
||||
|
||||
return bot.transformers.webhook(bot, result);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
import type { Bot } from "../../bot.ts";
|
||||
|
||||
export async function deleteWebhookMessage(bot: Bot, webhookId: bigint, webhookToken: string, messageId: bigint) {
|
||||
await bot.rest.runMethod<undefined>(
|
||||
bot.rest,
|
||||
"delete",
|
||||
bot.constants.endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, messageId)
|
||||
);
|
||||
export interface DeleteWebhookMessageOptions {
|
||||
/** id of the thread the message is in */
|
||||
threadId: bigint;
|
||||
}
|
||||
|
||||
export async function deleteWebhookMessage(
|
||||
bot: Bot,
|
||||
webhookId: bigint,
|
||||
webhookToken: string,
|
||||
messageId: bigint,
|
||||
options?: DeleteWebhookMessageOptions
|
||||
) {
|
||||
let url = bot.constants.endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, messageId);
|
||||
|
||||
// QUERY PARAMS
|
||||
if (options?.threadId) {
|
||||
url += `?threadId=${options.threadId}`;
|
||||
}
|
||||
await bot.rest.runMethod<undefined>(bot.rest, "delete", url);
|
||||
}
|
||||
|
||||
@@ -1,124 +1,103 @@
|
||||
import type { Message } from "../../types/messages/message.ts";
|
||||
import type { EditWebhookMessage } from "../../types/webhooks/editWebhookMessage.ts";
|
||||
import type { Bot } from "../../bot.ts";
|
||||
import { AllowedMentionsTypes } from "../../types/messages/allowedMentionsTypes.ts";
|
||||
import { MessageComponentTypes } from "../../types/messages/components/messageComponentTypes.ts";
|
||||
import { hasProperty } from "../../util/utils.ts";
|
||||
import { ButtonComponent } from "../../types/messages/components/buttonComponent.ts";
|
||||
|
||||
export async function editWebhookMessage(
|
||||
bot: Bot,
|
||||
webhookId: bigint,
|
||||
webhookToken: string,
|
||||
options: EditWebhookMessage & { messageId?: bigint }
|
||||
options: EditWebhookMessage & { messageId?: bigint; threadId?: bigint }
|
||||
) {
|
||||
if (options.content && options.content.length > 2000) {
|
||||
throw Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
|
||||
let url = options.messageId
|
||||
? bot.constants.endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, options.messageId)
|
||||
: bot.constants.endpoints.WEBHOOK_MESSAGE_ORIGINAL(webhookId, webhookToken);
|
||||
|
||||
// QUERY PARAMS
|
||||
if (options.threadId) {
|
||||
url += `?thread_id=${options.threadId}`;
|
||||
}
|
||||
|
||||
if (options.embeds && options.embeds.length > 10) {
|
||||
options.embeds.splice(10);
|
||||
}
|
||||
|
||||
if (options.allowedMentions) {
|
||||
if (options.allowedMentions.users?.length) {
|
||||
if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.UserMentions)) {
|
||||
options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "users");
|
||||
}
|
||||
|
||||
if (options.allowedMentions.users.length > 100) {
|
||||
options.allowedMentions.users = options.allowedMentions.users.slice(0, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.allowedMentions.roles?.length) {
|
||||
if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.RoleMentions)) {
|
||||
options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "roles");
|
||||
}
|
||||
|
||||
if (options.allowedMentions.roles.length > 100) {
|
||||
options.allowedMentions.roles = options.allowedMentions.roles.slice(0, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = await bot.rest.runMethod<Message>(
|
||||
bot.rest,
|
||||
"patch",
|
||||
options.messageId
|
||||
? bot.constants.endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, options.messageId)
|
||||
: bot.constants.endpoints.WEBHOOK_MESSAGE_ORIGINAL(webhookId, webhookToken),
|
||||
{
|
||||
content: options.content,
|
||||
embeds: options.embeds,
|
||||
file: options.file,
|
||||
allowed_mentions: options.allowedMentions
|
||||
? {
|
||||
parse: options.allowedMentions.parse,
|
||||
roles: options.allowedMentions.roles,
|
||||
users: options.allowedMentions.users,
|
||||
replied_user: options.allowedMentions.repliedUser,
|
||||
}
|
||||
: undefined,
|
||||
attachments: options.attachments,
|
||||
components: options.components?.map((component) => ({
|
||||
type: component.type,
|
||||
components: component.components.map((subcomponent) => {
|
||||
if (subcomponent.type === MessageComponentTypes.InputText) {
|
||||
return {
|
||||
type: subcomponent.type,
|
||||
style: subcomponent.style,
|
||||
custom_id: subcomponent.customId,
|
||||
label: subcomponent.label,
|
||||
placeholder: subcomponent.placeholder,
|
||||
min_length: subcomponent.minLength ?? subcomponent.required === false ? 0 : subcomponent.minLength,
|
||||
max_length: subcomponent.maxLength,
|
||||
};
|
||||
}
|
||||
|
||||
if (subcomponent.type === MessageComponentTypes.SelectMenu)
|
||||
return {
|
||||
type: subcomponent.type,
|
||||
custom_id: subcomponent.customId,
|
||||
placeholder: subcomponent.placeholder,
|
||||
min_values: subcomponent.minValues,
|
||||
max_values: subcomponent.maxValues,
|
||||
options: subcomponent.options.map((option) => ({
|
||||
label: option.label,
|
||||
value: option.value,
|
||||
description: option.description,
|
||||
emoji: option.emoji
|
||||
? {
|
||||
id: option.emoji.id?.toString(),
|
||||
name: option.emoji.name,
|
||||
animated: option.emoji.animated,
|
||||
}
|
||||
: undefined,
|
||||
default: option.default,
|
||||
})),
|
||||
};
|
||||
const result = await bot.rest.runMethod<Message>(bot.rest, "patch", url, {
|
||||
content: options.content,
|
||||
embeds: options.embeds,
|
||||
file: options.file,
|
||||
allowed_mentions: options.allowedMentions
|
||||
? {
|
||||
parse: options.allowedMentions.parse,
|
||||
roles: options.allowedMentions.roles?.map((id) => id.toString()),
|
||||
users: options.allowedMentions.users?.map((id) => id.toString()),
|
||||
replied_user: options.allowedMentions.repliedUser,
|
||||
}
|
||||
: undefined,
|
||||
attachments: options.attachments?.map((attachment) => ({
|
||||
id: attachment.id.toString(),
|
||||
filename: attachment.filename,
|
||||
content_type: attachment.contentType,
|
||||
size: attachment.size,
|
||||
url: attachment.url,
|
||||
proxy_url: attachment.proxyUrl,
|
||||
height: attachment.height,
|
||||
width: attachment.width,
|
||||
ephemeral: attachment.ephemeral,
|
||||
})),
|
||||
components: options.components?.map((component) => ({
|
||||
type: component.type,
|
||||
components: component.components.map((subcomponent) => {
|
||||
if (subcomponent.type === MessageComponentTypes.InputText) {
|
||||
return {
|
||||
type: subcomponent.type,
|
||||
style: subcomponent.style,
|
||||
custom_id: subcomponent.customId,
|
||||
label: subcomponent.label,
|
||||
placeholder: subcomponent.placeholder,
|
||||
min_length: subcomponent.minLength ?? subcomponent.required === false ? 0 : subcomponent.minLength,
|
||||
max_length: subcomponent.maxLength,
|
||||
};
|
||||
}
|
||||
|
||||
if (subcomponent.type === MessageComponentTypes.SelectMenu)
|
||||
return {
|
||||
type: subcomponent.type,
|
||||
custom_id: subcomponent.customId,
|
||||
label: subcomponent.label,
|
||||
style: subcomponent.style,
|
||||
emoji:
|
||||
"emoji" in subcomponent && subcomponent.emoji
|
||||
placeholder: subcomponent.placeholder,
|
||||
min_values: subcomponent.minValues,
|
||||
max_values: subcomponent.maxValues,
|
||||
options: subcomponent.options.map((option) => ({
|
||||
label: option.label,
|
||||
value: option.value,
|
||||
description: option.description,
|
||||
emoji: option.emoji
|
||||
? {
|
||||
id: subcomponent.emoji.id?.toString(),
|
||||
name: subcomponent.emoji.name,
|
||||
animated: subcomponent.emoji.animated,
|
||||
id: option.emoji.id?.toString(),
|
||||
name: option.emoji.name,
|
||||
animated: option.emoji.animated,
|
||||
}
|
||||
: undefined,
|
||||
url: "url" in subcomponent ? subcomponent.url : undefined,
|
||||
disabled: "disabled" in subcomponent ? subcomponent.disabled : undefined,
|
||||
default: option.default,
|
||||
})),
|
||||
};
|
||||
}),
|
||||
})),
|
||||
message_id: options.messageId?.toString(),
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
type: subcomponent.type,
|
||||
custom_id: subcomponent.customId,
|
||||
label: subcomponent.label,
|
||||
style: subcomponent.style,
|
||||
emoji:
|
||||
"emoji" in subcomponent && subcomponent.emoji
|
||||
? {
|
||||
id: subcomponent.emoji.id?.toString(),
|
||||
name: subcomponent.emoji.name,
|
||||
animated: subcomponent.emoji.animated,
|
||||
}
|
||||
: undefined,
|
||||
url: "url" in subcomponent ? subcomponent.url : undefined,
|
||||
disabled: "disabled" in subcomponent ? subcomponent.disabled : undefined,
|
||||
};
|
||||
}),
|
||||
})),
|
||||
message_id: options.messageId?.toString(),
|
||||
});
|
||||
|
||||
return bot.transformers.message(bot, result);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
import type { Message } from "../../types/messages/message.ts";
|
||||
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
|
||||
import type { Bot } from "../../bot.ts";
|
||||
|
||||
export interface GetWebhookMessageOptions {
|
||||
threadId: bigint;
|
||||
}
|
||||
|
||||
/** Returns a previously-sent webhook message from the same token. Returns a message object on success. */
|
||||
export async function getWebhookMessage(bot: Bot, webhookId: bigint, webhookToken: string, messageId: bigint) {
|
||||
const result = await bot.rest.runMethod<Message>(
|
||||
bot.rest,
|
||||
"get",
|
||||
bot.constants.endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, messageId)
|
||||
);
|
||||
export async function getWebhookMessage(
|
||||
bot: Bot,
|
||||
webhookId: bigint,
|
||||
webhookToken: string,
|
||||
messageId: bigint,
|
||||
options?: GetWebhookMessageOptions
|
||||
) {
|
||||
let url = bot.constants.endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, messageId);
|
||||
|
||||
// QUERY PARAMS
|
||||
if (options?.threadId) {
|
||||
url += `?thread_id=${options.threadId}`;
|
||||
}
|
||||
|
||||
const result = await bot.rest.runMethod<Message>(bot.rest, "get", url);
|
||||
|
||||
return bot.transformers.message(bot, result);
|
||||
}
|
||||
|
||||
@@ -5,41 +5,6 @@ import type { ExecuteWebhook } from "../../types/webhooks/executeWebhook.ts";
|
||||
|
||||
/** Send a webhook with webhook Id and webhook token */
|
||||
export async function sendWebhook(bot: Bot, webhookId: bigint, webhookToken: string, options: ExecuteWebhook) {
|
||||
// DEFAULT TO TRUE
|
||||
options.wait = options.wait ?? true;
|
||||
|
||||
if (!options.content && !options.file && !options.embeds) {
|
||||
throw new Error(bot.constants.Errors.INVALID_WEBHOOK_OPTIONS);
|
||||
}
|
||||
|
||||
if (options.content && options.content.length > 2000) {
|
||||
throw Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
|
||||
}
|
||||
|
||||
options.embeds?.splice(10);
|
||||
|
||||
if (options.allowedMentions) {
|
||||
if (options.allowedMentions.users?.length) {
|
||||
if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.UserMentions)) {
|
||||
options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "users");
|
||||
}
|
||||
|
||||
if (options.allowedMentions.users.length > 100) {
|
||||
options.allowedMentions.users = options.allowedMentions.users.slice(0, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.allowedMentions.roles?.length) {
|
||||
if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.RoleMentions)) {
|
||||
options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "roles");
|
||||
}
|
||||
|
||||
if (options.allowedMentions.roles.length > 100) {
|
||||
options.allowedMentions.roles = options.allowedMentions.roles.slice(0, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const allowedMentions = options.allowedMentions
|
||||
? {
|
||||
parse: options.allowedMentions.parse,
|
||||
@@ -65,6 +30,7 @@ export async function sendWebhook(bot: Bot, webhookId: bigint, webhookToken: str
|
||||
file: options.file,
|
||||
embeds: options.embeds,
|
||||
allowed_mentions: allowedMentions,
|
||||
component: options.components,
|
||||
}
|
||||
);
|
||||
if (!options.wait) return;
|
||||
|
||||
27
src/transformers/stageInstance.ts
Normal file
27
src/transformers/stageInstance.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Bot } from "../bot.ts";
|
||||
import { StageInstance } from "../types/channels/stageInstance.ts";
|
||||
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
|
||||
import { PrivacyLevel } from "../types/channels/privacyLevel.ts";
|
||||
|
||||
export function transformStageInstance(
|
||||
bot: Bot,
|
||||
payload: SnakeCasedPropertiesDeep<StageInstance>
|
||||
): DiscordenoStageInstance {
|
||||
return {
|
||||
id: bot.transformers.snowflake(payload.id),
|
||||
guildId: bot.transformers.snowflake(payload.guild_id),
|
||||
channelId: bot.transformers.snowflake(payload.channel_id),
|
||||
topic: payload.topic,
|
||||
};
|
||||
}
|
||||
|
||||
export interface DiscordenoStageInstance {
|
||||
/** The id of this Stage instance */
|
||||
id: bigint;
|
||||
/** The guild id of the associated Stage channel */
|
||||
guildId: bigint;
|
||||
/** The id of the associated Stage channel */
|
||||
channelId: bigint;
|
||||
/** The topic of the Stage instance (1-120 characters) */
|
||||
topic: string;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { Integration } from "../integrations/integration.ts";
|
||||
import { User } from "../users/user.ts";
|
||||
import { Webhook } from "../webhooks/webhook.ts";
|
||||
import { AuditLogEntry } from "./auditLogEntry.ts";
|
||||
import { ScheduledEvent } from "../guilds/scheduledEvents.ts";
|
||||
|
||||
/** https://discord.com/developers/docs/resources/audit-log#audit-log-object */
|
||||
export interface AuditLog {
|
||||
@@ -16,4 +17,6 @@ export interface AuditLog {
|
||||
integrations: Partial<Integration>[];
|
||||
/** List of threads found in the audit log. */
|
||||
threads: Channel[];
|
||||
/** List of guild scheduled events found in the audit log */
|
||||
scheduledEvents: ScheduledEvent[];
|
||||
}
|
||||
|
||||
@@ -10,4 +10,6 @@ export interface ModifyGuildMember {
|
||||
deaf?: boolean | null;
|
||||
/** Id of channel to move user to (if they are connected to voice). Requires the `MOVE_MEMBERS` permission */
|
||||
channelId?: bigint | null;
|
||||
/** when the user's timeout will expire and the user will be able to communicate in the guild again (up to 28 days in the future), set to null to remove timeout. Requires the `MODERATE_MEMBERS` permission */
|
||||
communicationDisabledUntil?: number;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ export interface GuildMember {
|
||||
user?: User;
|
||||
/** This users guild nickname */
|
||||
nick?: string | null;
|
||||
/** The members custom avatar for this server. */
|
||||
avatar?: string;
|
||||
/** Array of role object ids */
|
||||
roles: string[];
|
||||
/** When the user joined the guild */
|
||||
@@ -18,10 +20,10 @@ export interface GuildMember {
|
||||
mute?: boolean;
|
||||
/** Whether the user has not yet passed the guild's Membership Screening requirements */
|
||||
pending?: boolean;
|
||||
/** The members custom avatar for this server. */
|
||||
avatar?: string;
|
||||
/** The permissions this member has in the guild. Only present on interaction events. */
|
||||
permissions?: string;
|
||||
/** when the user's [timeout](https://support.discord.com/hc/en-us/articles/4413305239191-Time-Out-FAQ) will expire and the user will be able to communicate in the guild again, null or a time in the past if the user is not timed out */
|
||||
communicationDisabledUntil?: number;
|
||||
}
|
||||
|
||||
// We use these types much since user always exists unless its a `CREATE_MESSAGE` or `MESSAGE_UPDATE` event
|
||||
|
||||
@@ -10,14 +10,18 @@ export interface GuildMemberUpdate {
|
||||
user: User;
|
||||
/** Nickname of the user in the guild */
|
||||
nick?: string | null;
|
||||
/** the member's [guild avatar hash](https://discord.com/developers/docs/reference#image-formatting) */
|
||||
avatar: string;
|
||||
/** When the user joined the guild */
|
||||
joinedAt: string;
|
||||
/** When the user starting boosting the guild */
|
||||
premiumSince?: string | null;
|
||||
/** Whether the user has not yet passed the guild's Membership Screening requirements */
|
||||
pending?: boolean;
|
||||
/** whether the user is deafened in voice channels */
|
||||
deaf?: boolean;
|
||||
/** whether the user is muted in voice channels */
|
||||
mute?: boolean;
|
||||
/** Whether the user has not yet passed the guild's Membership Screening requirements */
|
||||
pending?: boolean;
|
||||
/** when the user's [timeout](https://support.discord.com/hc/en-us/articles/4413305239191-Time-Out-FAQ) will expire and the user will be able to communicate in the guild again, null or a time in the past if the user is not timed out */
|
||||
communicationDisabledUntil?: number;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export interface Message {
|
||||
activity?: MessageActivity;
|
||||
/** Sent with Rich Presence-related chat embeds */
|
||||
application?: Partial<Application>;
|
||||
/** If the message is a response to an Interaction, this is the id of the interaction's application */
|
||||
/** if the message is an Interaction or application-owned webhook, this is the id of the application */
|
||||
applicationId?: string;
|
||||
/** Data showing the source of a crossposted channel follow add, pin or reply message */
|
||||
messageReference?: Omit<MessageReference, "failIfNotExists">;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { MessageStickerFormatTypes } from "./messageStickerFormatTypes.ts";
|
||||
import type { User } from "../users/user.ts";
|
||||
|
||||
/** https://discord.com/developers/docs/resources/channel#message-object-message-sticker-structure */
|
||||
export interface MessageSticker {
|
||||
/** Id of the sticker */
|
||||
id: string;
|
||||
/** Id of the pack the sticker is from */
|
||||
packId?: string;
|
||||
/** Name of the sticker */
|
||||
name: string;
|
||||
/** Description of the sticker */
|
||||
description: string;
|
||||
/** a unicode emoji representing the sticker's expression */
|
||||
tags: string;
|
||||
/** Type of sticker format */
|
||||
formatType: MessageStickerFormatTypes;
|
||||
/** Whether or not the sticker is available */
|
||||
available?: boolean;
|
||||
/** Id of the guild that owns this sticker */
|
||||
guildId?: string;
|
||||
/** The user that uploaded the sticker */
|
||||
user?: User;
|
||||
/** A sticker's sort order within a pack */
|
||||
sortValue?: number;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/** https://discord.com/developers/docs/resources/channel#message-object-message-sticker-format-types */
|
||||
export enum MessageStickerFormatTypes {
|
||||
Png = 1,
|
||||
Apng,
|
||||
Lottie,
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { MessageStickerFormatTypes } from "./messageStickerFormatTypes.ts";
|
||||
|
||||
export interface MessageStickerItem {
|
||||
/** Id of the sticker */
|
||||
id: string;
|
||||
/** Name of the sticker */
|
||||
name: string;
|
||||
/** Type of sticker format */
|
||||
formatType: MessageStickerFormatTypes;
|
||||
}
|
||||
@@ -1,83 +1,85 @@
|
||||
/** https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags */
|
||||
export enum BitwisePermissionFlags {
|
||||
/** Allows creation of instant invites */
|
||||
CREATE_INSTANT_INVITE = 0x00000001,
|
||||
CREATE_INSTANT_INVITE = 0x0000000000000001,
|
||||
/** Allows kicking members */
|
||||
KICK_MEMBERS = 0x00000002,
|
||||
KICK_MEMBERS = 0x0000000000000002,
|
||||
/** Allows banning members */
|
||||
BAN_MEMBERS = 0x00000004,
|
||||
BAN_MEMBERS = 0x0000000000000004,
|
||||
/** Allows all permissions and bypasses channel permission overwrites */
|
||||
ADMINISTRATOR = 0x00000008,
|
||||
ADMINISTRATOR = 0x0000000000000008,
|
||||
/** Allows management and editing of channels */
|
||||
MANAGE_CHANNELS = 0x00000010,
|
||||
MANAGE_CHANNELS = 0x0000000000000010,
|
||||
/** Allows management and editing of the guild */
|
||||
MANAGE_GUILD = 0x00000020,
|
||||
MANAGE_GUILD = 0x0000000000000020,
|
||||
/** Allows for the addition of reactions to messages */
|
||||
ADD_REACTIONS = 0x00000040,
|
||||
ADD_REACTIONS = 0x0000000000000040,
|
||||
/** Allows for viewing of audit logs */
|
||||
VIEW_AUDIT_LOG = 0x00000080,
|
||||
VIEW_AUDIT_LOG = 0x0000000000000080,
|
||||
/** Allows for using priority speaker in a voice channel */
|
||||
PRIORITY_SPEAKER = 0x00000100,
|
||||
PRIORITY_SPEAKER = 0x0000000000000100,
|
||||
/** Allows the user to go live */
|
||||
STREAM = 0x00000200,
|
||||
STREAM = 0x0000000000000200,
|
||||
/** Allows guild members to view a channel, which includes reading messages in text channels */
|
||||
VIEW_CHANNEL = 0x00000400,
|
||||
VIEW_CHANNEL = 0x0000000000000400,
|
||||
/** Allows for sending messages in a channel. (does not allow sending messages in threads) */
|
||||
SEND_MESSAGES = 0x00000800,
|
||||
SEND_MESSAGES = 0x0000000000000800,
|
||||
/** Allows for sending of /tts messages */
|
||||
SEND_TTS_MESSAGES = 0x00001000,
|
||||
SEND_TTS_MESSAGES = 0x0000000000001000,
|
||||
/** Allows for deletion of other users messages */
|
||||
MANAGE_MESSAGES = 0x00002000,
|
||||
MANAGE_MESSAGES = 0x0000000000002000,
|
||||
/** Links sent by users with this permission will be auto-embedded */
|
||||
EMBED_LINKS = 0x00004000,
|
||||
EMBED_LINKS = 0x0000000000004000,
|
||||
/** Allows for uploading images and files */
|
||||
ATTACH_FILES = 0x00008000,
|
||||
ATTACH_FILES = 0x0000000000008000,
|
||||
/** Allows for reading of message history */
|
||||
READ_MESSAGE_HISTORY = 0x00010000,
|
||||
READ_MESSAGE_HISTORY = 0x0000000000010000,
|
||||
/** Allows for using the @everyone tag to notify all users in a channel, and the @here tag to notify all online users in a channel */
|
||||
MENTION_EVERYONE = 0x00020000,
|
||||
MENTION_EVERYONE = 0x0000000000020000,
|
||||
/** Allows the usage of custom emojis from other servers */
|
||||
USE_EXTERNAL_EMOJIS = 0x00040000,
|
||||
USE_EXTERNAL_EMOJIS = 0x0000000000040000,
|
||||
/** Allows for viewing guild insights */
|
||||
VIEW_GUILD_INSIGHTS = 0x00080000,
|
||||
VIEW_GUILD_INSIGHTS = 0x0000000000080000,
|
||||
/** Allows for joining of a voice channel */
|
||||
CONNECT = 0x00100000,
|
||||
CONNECT = 0x0000000000100000,
|
||||
/** Allows for speaking in a voice channel */
|
||||
SPEAK = 0x00200000,
|
||||
SPEAK = 0x0000000000200000,
|
||||
/** Allows for muting members in a voice channel */
|
||||
MUTE_MEMBERS = 0x00400000,
|
||||
MUTE_MEMBERS = 0x0000000000400000,
|
||||
/** Allows for deafening of members in a voice channel */
|
||||
DEAFEN_MEMBERS = 0x00800000,
|
||||
DEAFEN_MEMBERS = 0x0000000000800000,
|
||||
/** Allows for moving of members between voice channels */
|
||||
MOVE_MEMBERS = 0x01000000,
|
||||
MOVE_MEMBERS = 0x0000000001000000,
|
||||
/** Allows for using voice-activity-detection in a voice channel */
|
||||
USE_VAD = 0x02000000,
|
||||
USE_VAD = 0x0000000002000000,
|
||||
/** Allows for modification of own nickname */
|
||||
CHANGE_NICKNAME = 0x04000000,
|
||||
CHANGE_NICKNAME = 0x0000000004000000,
|
||||
/** Allows for modification of other users nicknames */
|
||||
MANAGE_NICKNAMES = 0x08000000,
|
||||
MANAGE_NICKNAMES = 0x0000000008000000,
|
||||
/** Allows management and editing of roles */
|
||||
MANAGE_ROLES = 0x10000000,
|
||||
MANAGE_ROLES = 0x0000000010000000,
|
||||
/** Allows management and editing of webhooks */
|
||||
MANAGE_WEBHOOKS = 0x20000000,
|
||||
MANAGE_WEBHOOKS = 0x0000000020000000,
|
||||
/** Allows management and editing of emojis */
|
||||
MANAGE_EMOJIS = 0x40000000,
|
||||
MANAGE_EMOJIS = 0x0000000040000000,
|
||||
/** Allows members to use application commands in text channels */
|
||||
USE_SLASH_COMMANDS = 0x80000000,
|
||||
USE_SLASH_COMMANDS = 0x0000000080000000,
|
||||
/** Allows for requesting to speak in stage channels. */
|
||||
REQUEST_TO_SPEAK = 0x0100000000,
|
||||
REQUEST_TO_SPEAK = 0x0000000100000000,
|
||||
/** Allows for creating, editing, and deleting scheduled events */
|
||||
MANAGE_EVENTS = 0x0200000000,
|
||||
MANAGE_EVENTS = 0x0000000200000000,
|
||||
/** Allows for deleting and archiving threads, and viewing all private threads */
|
||||
MANAGE_THREADS = 0x0400000000,
|
||||
MANAGE_THREADS = 0x0000000400000000,
|
||||
/** Allows for creating threads */
|
||||
CREATE_PUBLIC_THREADS = 0x0800000000,
|
||||
CREATE_PUBLIC_THREADS = 0x0000000800000000,
|
||||
/** Allows for creating private threads */
|
||||
CREATE_PRIVATE_THREADS = 0x1000000000,
|
||||
CREATE_PRIVATE_THREADS = 0x0000001000000000,
|
||||
/** Allows the usage of custom stickers from other servers */
|
||||
USE_EXTERNAL_STICKERS = 0x2000000000,
|
||||
USE_EXTERNAL_STICKERS = 0x0000002000000000,
|
||||
/** Allows for sending messages in threads */
|
||||
SEND_MESSAGES_IN_THREADS = 0x4000000000,
|
||||
SEND_MESSAGES_IN_THREADS = 0x0000004000000000,
|
||||
/** Allows for launching activities (applications with the `EMBEDDED` flag) in a voice channel. */
|
||||
START_EMBEDDED_ACTIVITIES = 0x8000000000,
|
||||
START_EMBEDDED_ACTIVITIES = 0x0000008000000000,
|
||||
/** Allows for timing out users to prevent them from sending or reacting to messages in chat and threads, and from speaking in voice and stage channels */
|
||||
MODERATE_MEMBERS = 0x0000010000000000,
|
||||
}
|
||||
|
||||
29
src/types/stickers/sticker.ts
Normal file
29
src/types/stickers/sticker.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { StickerFormatTypes } from "./stickerFormatTypes.ts";
|
||||
import type { StickerTypes } from "./stickerTypes.ts";
|
||||
import type { User } from "../users/user.ts";
|
||||
|
||||
/** https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-structure */
|
||||
export interface Sticker {
|
||||
/** [Id of the sticker](https://discord.com/developers/docs/reference#image-formatting) */
|
||||
id: string;
|
||||
/** Id of the pack the sticker is from */
|
||||
packId?: string;
|
||||
/** Name of the sticker */
|
||||
name: string;
|
||||
/** Description of the sticker */
|
||||
description: string;
|
||||
/** a unicode emoji representing the sticker's expression */
|
||||
tags: string;
|
||||
/** [type of sticker](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-types) */
|
||||
type: StickerTypes;
|
||||
/** [Type of sticker format](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types) */
|
||||
formatType: StickerFormatTypes;
|
||||
/** Whether or not the sticker is available */
|
||||
available?: boolean;
|
||||
/** Id of the guild that owns this sticker */
|
||||
guildId?: string;
|
||||
/** The user that uploaded the sticker */
|
||||
user?: User;
|
||||
/** A sticker's sort order within a pack */
|
||||
sortValue?: number;
|
||||
}
|
||||
6
src/types/stickers/stickerFormatTypes.ts
Normal file
6
src/types/stickers/stickerFormatTypes.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/** https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types */
|
||||
export enum StickerFormatTypes {
|
||||
Png = 1,
|
||||
Apng,
|
||||
Lottie,
|
||||
}
|
||||
11
src/types/stickers/stickerItem.ts
Normal file
11
src/types/stickers/stickerItem.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { StickerFormatTypes } from "./stickerFormatTypes.ts";
|
||||
|
||||
/** https://discord.com/developers/docs/resources/sticker#sticker-item-object-sticker-item-structure */
|
||||
export interface StickerItem {
|
||||
/** Id of the sticker */
|
||||
id: string;
|
||||
/** Name of the sticker */
|
||||
name: string;
|
||||
/** [Type of sticker format](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types) */
|
||||
formatType: StickerFormatTypes;
|
||||
}
|
||||
19
src/types/stickers/stickerPack.ts
Normal file
19
src/types/stickers/stickerPack.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Sticker } from "./sticker.ts";
|
||||
|
||||
/** https://discord.com/developers/docs/resources/sticker#sticker-pack-object-sticker-pack-structure */
|
||||
export interface StickerPack {
|
||||
/** id of the sticker pack */
|
||||
id: string;
|
||||
/** the stickers in the pack */
|
||||
stickers: Sticker[];
|
||||
/** name of the sticker pack */
|
||||
name: string;
|
||||
/** id of the pack's SKU */
|
||||
sku_id: string;
|
||||
/** id of a sticker in the pack which is shown as the pack's icon */
|
||||
cover_sticker_id?: string;
|
||||
/** description of the sticker pack */
|
||||
description: string;
|
||||
/** id of the sticker pack's [banner image](https://discord.com/developers/docs/reference#image-formatting) */
|
||||
banner_asset_id?: string;
|
||||
}
|
||||
7
src/types/stickers/stickerTypes.ts
Normal file
7
src/types/stickers/stickerTypes.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/** https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-types */
|
||||
export enum StickerTypes {
|
||||
/** an official sticker in a pack, part of Nitro or in a removed purchasable pack */
|
||||
Standard = 1,
|
||||
/** a sticker uploaded to a Boosted guild for the guild's members */
|
||||
Guild,
|
||||
}
|
||||
@@ -13,9 +13,14 @@ export interface EditWebhookMessage {
|
||||
/** The contents of the file being sent/edited */
|
||||
file?: FileContent | FileContent[] | null;
|
||||
/** Allowed mentions for the message */
|
||||
allowedMentions?: AllowedMentions | null;
|
||||
allowedMentions?: Omit<AllowedMentions, "users" | "roles"> & {
|
||||
/** Array of role_ids to mention (Max size of 100) */
|
||||
roles?: bigint[];
|
||||
/** Array of user_ids to mention (Max size of 100) */
|
||||
users?: bigint[];
|
||||
};
|
||||
/** Attached files to keep */
|
||||
attachments?: Attachment | null;
|
||||
attachments?: (Omit<Attachment, "id"> & { id: bigint })[] | null;
|
||||
/** The components you would like to have sent in this message */
|
||||
components?: MessageComponents;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Embed } from "../embeds/embed.ts";
|
||||
import { AllowedMentions } from "../messages/allowedMentions.ts";
|
||||
import { FileContent } from "../discordeno/fileContent.ts";
|
||||
import { SnakeCasedPropertiesDeep } from "../util.ts";
|
||||
import { MessageComponents } from "../messages/components/messageComponents.ts";
|
||||
|
||||
/** https://discord.com/developers/docs/resources/webhook#execute-webhook */
|
||||
export interface ExecuteWebhook {
|
||||
@@ -28,6 +29,8 @@ export interface ExecuteWebhook {
|
||||
/** Array of user_ids to mention (Max size of 100) */
|
||||
users?: bigint[];
|
||||
};
|
||||
/** the components to include with the message */
|
||||
components: MessageComponents;
|
||||
}
|
||||
|
||||
export type DiscordExecuteWebhook = SnakeCasedPropertiesDeep<Omit<ExecuteWebhook, "wait">>;
|
||||
|
||||
35
tests/interactions/slash/createApplicationCommand.ts
Normal file
35
tests/interactions/slash/createApplicationCommand.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { assertExists, assertEquals } from "../../deps.ts";
|
||||
import { bot } from "../../mod.ts";
|
||||
import { CACHED_COMMUNITY_GUILD_ID } from "../../constants.ts";
|
||||
|
||||
Deno.test({
|
||||
name: "[slash] Create a guild slash command",
|
||||
fn: async (t) => {
|
||||
let commands = new Map();
|
||||
await t.step({
|
||||
name: "[slash] Gets a bot's slash commands in a guild",
|
||||
fn: async (t) => {
|
||||
commands = await bot.helpers.getApplicationCommands(CACHED_COMMUNITY_GUILD_ID);
|
||||
},
|
||||
});
|
||||
|
||||
if (commands.has("test")) {
|
||||
await t.step({
|
||||
name: "[slash] Delete a guild slash command",
|
||||
fn: async (t) => {
|
||||
await bot.helpers.deleteApplicationCommand(commands.get("test").id, CACHED_COMMUNITY_GUILD_ID);
|
||||
commands.delete("test");
|
||||
assertEquals(commands.has("test"), false);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await bot.helpers.createApplicationCommand(
|
||||
{
|
||||
name: "test",
|
||||
description: "Test slash command from the ddeno unit tests",
|
||||
},
|
||||
CACHED_COMMUNITY_GUILD_ID
|
||||
);
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user