mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-16 11:28:15 +00:00
Merge branch 'main' of https://github.com/discordeno/discordeno into fix-rest-issues
This commit is contained in:
+62
-40
@@ -1,29 +1,32 @@
|
|||||||
// deno-lint-ignore-file require-await no-explicit-any prefer-const
|
// deno-lint-ignore-file require-await no-explicit-any prefer-const
|
||||||
|
import { ChannelStruct } from "./structures/channel.ts";
|
||||||
import { Channel, Guild, Member, Message } from "./structures/mod.ts";
|
import { GuildStruct } from "./structures/guild.ts";
|
||||||
|
import { MemberStruct } from "./structures/member.ts";
|
||||||
|
import { MessageStruct } from "./structures/message.ts";
|
||||||
import { Emoji } from "./types/emojis/emoji.ts";
|
import { Emoji } from "./types/emojis/emoji.ts";
|
||||||
|
import { PresenceUpdate } from "./types/misc/presence_update.ts";
|
||||||
import { Collection } from "./util/collection.ts";
|
import { Collection } from "./util/collection.ts";
|
||||||
|
|
||||||
export const cache = {
|
export const cache = {
|
||||||
isReady: false,
|
isReady: false,
|
||||||
/** All of the guild objects the bot has access to, mapped by their Ids */
|
/** All of the guild objects the bot has access to, mapped by their Ids */
|
||||||
guilds: new Collection<string, Guild>(),
|
guilds: new Collection<string, GuildStruct>(),
|
||||||
/** All of the channel objects the bot has access to, mapped by their Ids */
|
/** All of the channel objects the bot has access to, mapped by their Ids */
|
||||||
channels: new Collection<string, Channel>(),
|
channels: new Collection<string, ChannelStruct>(),
|
||||||
/** All of the message objects the bot has cached since the bot acquired `READY` state, mapped by their Ids */
|
/** All of the message objects the bot has cached since the bot acquired `READY` state, mapped by their Ids */
|
||||||
messages: new Collection<string, Message>(),
|
messages: new Collection<string, MessageStruct>(),
|
||||||
/** All of the member objects that have been cached since the bot acquired `READY` state, mapped by their Ids */
|
/** All of the member objects that have been cached since the bot acquired `READY` state, mapped by their Ids */
|
||||||
members: new Collection<string, Member>(),
|
members: new Collection<string, MemberStruct>(),
|
||||||
/** All of the unavailable guilds, mapped by their Ids (id, timestamp) */
|
/** All of the unavailable guilds, mapped by their Ids (id, timestamp) */
|
||||||
unavailableGuilds: new Collection<string, number>(),
|
unavailableGuilds: new Collection<string, number>(),
|
||||||
/** All of the presence update objects received in PRESENCE_UPDATE gateway event, mapped by their user Id */
|
/** All of the presence update objects received in PRESENCE_UPDATE gateway event, mapped by their user Id */
|
||||||
presences: new Collection<string, Presence>(),
|
presences: new Collection<string, PresenceUpdate>(),
|
||||||
fetchAllMembersProcessingRequests: new Collection<
|
fetchAllMembersProcessingRequests: new Collection<
|
||||||
string,
|
string,
|
||||||
(
|
(
|
||||||
value:
|
value:
|
||||||
| Collection<string, Member>
|
| Collection<string, MemberStruct>
|
||||||
| PromiseLike<Collection<string, Member>>,
|
| PromiseLike<Collection<string, MemberStruct>>,
|
||||||
) => void
|
) => void
|
||||||
>(),
|
>(),
|
||||||
executedSlashCommands: new Collection<string, string>(),
|
executedSlashCommands: new Collection<string, string>(),
|
||||||
@@ -78,28 +81,28 @@ export type TableName =
|
|||||||
function set(
|
function set(
|
||||||
table: "guilds",
|
table: "guilds",
|
||||||
key: string,
|
key: string,
|
||||||
value: Guild,
|
value: GuildStruct,
|
||||||
): Promise<Collection<string, Guild>>;
|
): Promise<Collection<string, GuildStruct>>;
|
||||||
function set(
|
function set(
|
||||||
table: "channels",
|
table: "channels",
|
||||||
key: string,
|
key: string,
|
||||||
value: Channel,
|
value: ChannelStruct,
|
||||||
): Promise<Collection<string, Channel>>;
|
): Promise<Collection<string, ChannelStruct>>;
|
||||||
function set(
|
function set(
|
||||||
table: "messages",
|
table: "messages",
|
||||||
key: string,
|
key: string,
|
||||||
value: Message,
|
value: MessageStruct,
|
||||||
): Promise<Collection<string, Message>>;
|
): Promise<Collection<string, MessageStruct>>;
|
||||||
function set(
|
function set(
|
||||||
table: "members",
|
table: "members",
|
||||||
key: string,
|
key: string,
|
||||||
value: Member,
|
value: MemberStruct,
|
||||||
): Promise<Collection<string, Member>>;
|
): Promise<Collection<string, MemberStruct>>;
|
||||||
function set(
|
function set(
|
||||||
table: "presences",
|
table: "presences",
|
||||||
key: string,
|
key: string,
|
||||||
value: PresenceUpdatePayload,
|
value: PresenceUpdate,
|
||||||
): Promise<Collection<string, PresenceUpdatePayload>>;
|
): Promise<Collection<string, PresenceUpdate>>;
|
||||||
function set(
|
function set(
|
||||||
table: "unavailableGuilds",
|
table: "unavailableGuilds",
|
||||||
key: string,
|
key: string,
|
||||||
@@ -109,41 +112,60 @@ async function set(table: TableName, key: string, value: any) {
|
|||||||
return cache[table].set(key, value);
|
return cache[table].set(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get(table: "guilds", key: string): Promise<Guild | undefined>;
|
function get(table: "guilds", key: string): Promise<GuildStruct | undefined>;
|
||||||
function get(table: "channels", key: string): Promise<Channel | undefined>;
|
function get(
|
||||||
function get(table: "messages", key: string): Promise<Message | undefined>;
|
table: "channels",
|
||||||
function get(table: "members", key: string): Promise<Member | undefined>;
|
key: string,
|
||||||
|
): Promise<ChannelStruct | undefined>;
|
||||||
|
function get(table: "messages", key: string): Promise<MemberStruct | undefined>;
|
||||||
|
function get(table: "members", key: string): Promise<MemberStruct | undefined>;
|
||||||
function get(
|
function get(
|
||||||
table: "presences",
|
table: "presences",
|
||||||
key: string,
|
key: string,
|
||||||
): Promise<PresenceUpdatePayload | undefined>;
|
): Promise<PresenceUpdate | undefined>;
|
||||||
function get(
|
function get(
|
||||||
table: "unavailableGuilds",
|
table: "unavailableGuilds",
|
||||||
key: string,
|
key: string,
|
||||||
): Promise<Guild | undefined>;
|
): Promise<number | undefined>;
|
||||||
async function get(table: TableName, key: string) {
|
async function get(table: TableName, key: string) {
|
||||||
return cache[table].get(key);
|
return cache[table].get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function forEach(
|
function forEach(
|
||||||
table: "guilds",
|
table: "guilds",
|
||||||
callback: (value: Guild, key: string, map: Map<string, Guild>) => unknown,
|
callback: (
|
||||||
|
value: GuildStruct,
|
||||||
|
key: string,
|
||||||
|
map: Map<string, GuildStruct>,
|
||||||
|
) => unknown,
|
||||||
): void;
|
): void;
|
||||||
function forEach(
|
function forEach(
|
||||||
table: "unavailableGuilds",
|
table: "unavailableGuilds",
|
||||||
callback: (value: Guild, key: string, map: Map<string, Guild>) => unknown,
|
callback: (value: number, key: string, map: Map<string, number>) => unknown,
|
||||||
): void;
|
): void;
|
||||||
function forEach(
|
function forEach(
|
||||||
table: "channels",
|
table: "channels",
|
||||||
callback: (value: Channel, key: string, map: Map<string, Channel>) => unknown,
|
callback: (
|
||||||
|
value: ChannelStruct,
|
||||||
|
key: string,
|
||||||
|
map: Map<string, ChannelStruct>,
|
||||||
|
) => unknown,
|
||||||
): void;
|
): void;
|
||||||
function forEach(
|
function forEach(
|
||||||
table: "messages",
|
table: "messages",
|
||||||
callback: (value: Message, key: string, map: Map<string, Message>) => unknown,
|
callback: (
|
||||||
|
value: MemberStruct,
|
||||||
|
key: string,
|
||||||
|
map: Map<string, MemberStruct>,
|
||||||
|
) => unknown,
|
||||||
): void;
|
): void;
|
||||||
function forEach(
|
function forEach(
|
||||||
table: "members",
|
table: "members",
|
||||||
callback: (value: Member, key: string, map: Map<string, Member>) => unknown,
|
callback: (
|
||||||
|
value: MemberStruct,
|
||||||
|
key: string,
|
||||||
|
map: Map<string, MemberStruct>,
|
||||||
|
) => unknown,
|
||||||
): void;
|
): void;
|
||||||
function forEach(
|
function forEach(
|
||||||
table: TableName,
|
table: TableName,
|
||||||
@@ -154,24 +176,24 @@ function forEach(
|
|||||||
|
|
||||||
function filter(
|
function filter(
|
||||||
table: "guilds",
|
table: "guilds",
|
||||||
callback: (value: Guild, key: string) => boolean,
|
callback: (value: GuildStruct, key: string) => boolean,
|
||||||
): Promise<Collection<string, Guild>>;
|
): Promise<Collection<string, GuildStruct>>;
|
||||||
function filter(
|
function filter(
|
||||||
table: "unavailableGuilds",
|
table: "unavailableGuilds",
|
||||||
callback: (value: Guild, key: string) => boolean,
|
callback: (value: number, key: string) => boolean,
|
||||||
): Promise<Collection<string, Guild>>;
|
): Promise<Collection<string, number>>;
|
||||||
function filter(
|
function filter(
|
||||||
table: "channels",
|
table: "channels",
|
||||||
callback: (value: Channel, key: string) => boolean,
|
callback: (value: ChannelStruct, key: string) => boolean,
|
||||||
): Promise<Collection<string, Channel>>;
|
): Promise<Collection<string, ChannelStruct>>;
|
||||||
function filter(
|
function filter(
|
||||||
table: "messages",
|
table: "messages",
|
||||||
callback: (value: Message, key: string) => boolean,
|
callback: (value: MessageStruct, key: string) => boolean,
|
||||||
): Promise<Collection<string, Message>>;
|
): Promise<Collection<string, MessageStruct>>;
|
||||||
function filter(
|
function filter(
|
||||||
table: "members",
|
table: "members",
|
||||||
callback: (value: Member, key: string) => boolean,
|
callback: (value: MemberStruct, key: string) => boolean,
|
||||||
): Promise<Collection<string, Member>>;
|
): Promise<Collection<string, MemberStruct>>;
|
||||||
async function filter(
|
async function filter(
|
||||||
table: TableName,
|
table: TableName,
|
||||||
callback: (value: any, key: string) => boolean,
|
callback: (value: any, key: string) => boolean,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import { DiscordApplicationCommandCreateUpdateDelete } from "../../types/interactions/application_command_create_update_delete.ts";
|
||||||
|
|
||||||
export function handleApplicationCommandCreate(
|
export function handleApplicationCommandCreate(
|
||||||
data: DiscordGatewayPayload,
|
data: DiscordGatewayPayload,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import { DiscordApplicationCommandCreateUpdateDelete } from "../../types/interactions/application_command_create_update_delete.ts";
|
||||||
|
|
||||||
export function handleApplicationCommandDelete(data: DiscordGatewayPayload) {
|
export function handleApplicationCommandDelete(data: DiscordGatewayPayload) {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import { DiscordApplicationCommandCreateUpdateDelete } from "../../types/interactions/application_command_create_update_delete.ts";
|
||||||
|
|
||||||
export function handleApplicationCommandUpdate(data: DiscordGatewayPayload) {
|
export function handleApplicationCommandUpdate(data: DiscordGatewayPayload) {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
import { cacheHandlers } from "../../cache.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import { DiscordGuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts";
|
||||||
|
|
||||||
export async function handleGuildBanAdd(data: DiscordGatewayPayload) {
|
export async function handleGuildBanAdd(data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as DiscordGuildBanAddRemove;
|
const payload = data.d as DiscordGuildBanAddRemove;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
import { cacheHandlers } from "../../cache.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import { DiscordGuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts";
|
||||||
|
|
||||||
export async function handleGuildBanRemove(data: DiscordGatewayPayload) {
|
export async function handleGuildBanRemove(data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as DiscordGuildBanAddRemove;
|
const payload = data.d as DiscordGuildBanAddRemove;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { cache, cacheHandlers } from "../../cache.ts";
|
|||||||
import { structures } from "../../structures/mod.ts";
|
import { structures } from "../../structures/mod.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import { DiscordGuild } from "../../types/guilds/guild.ts";
|
import { DiscordGuild } from "../../types/guilds/guild.ts";
|
||||||
|
import { ws } from "../../ws/ws.ts";
|
||||||
|
|
||||||
export async function handleGuildCreate(
|
export async function handleGuildCreate(
|
||||||
data: DiscordGatewayPayload,
|
data: DiscordGatewayPayload,
|
||||||
@@ -13,12 +14,12 @@ export async function handleGuildCreate(
|
|||||||
if (await cacheHandlers.has("guilds", payload.id)) return;
|
if (await cacheHandlers.has("guilds", payload.id)) return;
|
||||||
|
|
||||||
const guildStruct = await structures.createGuildStruct(
|
const guildStruct = await structures.createGuildStruct(
|
||||||
data.d,
|
payload,
|
||||||
shardId,
|
shardId,
|
||||||
);
|
);
|
||||||
await cacheHandlers.set("guilds", guildStruct.id, guildStruct);
|
await cacheHandlers.set("guilds", guildStruct.id, guildStruct);
|
||||||
|
|
||||||
const shard = basicShards.get(shardId);
|
const shard = ws.shards.get(shardId);
|
||||||
|
|
||||||
if (shard?.unavailableGuildIds.has(payload.id)) {
|
if (shard?.unavailableGuildIds.has(payload.id)) {
|
||||||
await cacheHandlers.delete("unavailableGuilds", payload.id);
|
await cacheHandlers.delete("unavailableGuilds", payload.id);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { eventHandlers } from "../../bot.ts";
|
|||||||
import { cacheHandlers } from "../../cache.ts";
|
import { cacheHandlers } from "../../cache.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import { DiscordUnavailableGuild } from "../../types/guilds/unavailable_guild.ts";
|
import { DiscordUnavailableGuild } from "../../types/guilds/unavailable_guild.ts";
|
||||||
|
import { ws } from "../../ws/ws.ts";
|
||||||
|
|
||||||
export async function handleGuildDelete(
|
export async function handleGuildDelete(
|
||||||
data: DiscordGatewayPayload,
|
data: DiscordGatewayPayload,
|
||||||
@@ -15,7 +16,7 @@ export async function handleGuildDelete(
|
|||||||
await cacheHandlers.delete("guilds", payload.id);
|
await cacheHandlers.delete("guilds", payload.id);
|
||||||
|
|
||||||
if (payload.unavailable) {
|
if (payload.unavailable) {
|
||||||
const shard = basicShards.get(shardId);
|
const shard = ws.shards.get(shardId);
|
||||||
if (shard) shard.unavailableGuildIds.add(payload.id);
|
if (shard) shard.unavailableGuildIds.add(payload.id);
|
||||||
|
|
||||||
await cacheHandlers.set("unavailableGuilds", payload.id, Date.now());
|
await cacheHandlers.set("unavailableGuilds", payload.id, Date.now());
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { cacheHandlers } from "../../cache.ts";
|
import { cacheHandlers } from "../../cache.ts";
|
||||||
|
import { GuildUpdateChange } from "../../types/discordeno/guild_update_change.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import { DiscordGuild } from "../../types/guilds/guild.ts";
|
import { DiscordGuild } from "../../types/guilds/guild.ts";
|
||||||
|
|
||||||
export async function handleGuildUpdate(data: DiscordGatewayPayload) {
|
export async function handleGuildUpdate(data: DiscordGatewayPayload) {
|
||||||
const payload = data.d as DiscordGuild;
|
const payload = data.d as DiscordGuild;
|
||||||
const cachedGuild = await cacheHandlers.get("guilds", payload.id);
|
const newGuild = await cacheHandlers.get("guilds", payload.id);
|
||||||
if (!cachedGuild) return;
|
if (!newGuild) return;
|
||||||
|
|
||||||
const keysToSkip = [
|
const keysToSkip = [
|
||||||
"roles",
|
"roles",
|
||||||
"guild_hashes",
|
"guildHashes",
|
||||||
"guild_id",
|
"guildId",
|
||||||
"max_members",
|
"maxMembers",
|
||||||
"emojis",
|
"emojis",
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ export async function handleGuildUpdate(data: DiscordGatewayPayload) {
|
|||||||
if (keysToSkip.includes(key)) return;
|
if (keysToSkip.includes(key)) return;
|
||||||
|
|
||||||
// @ts-ignore index signature
|
// @ts-ignore index signature
|
||||||
const cachedValue = cachedGuild[key];
|
const cachedValue = newGuild[key];
|
||||||
if (cachedValue !== value) {
|
if (cachedValue !== value) {
|
||||||
// Guild create sends undefined and update sends false.
|
// Guild create sends undefined and update sends false.
|
||||||
if (!cachedValue && !value) return;
|
if (!cachedValue && !value) return;
|
||||||
@@ -34,12 +35,12 @@ export async function handleGuildUpdate(data: DiscordGatewayPayload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore index signature
|
// @ts-ignore index signature
|
||||||
cachedGuild[key] = value;
|
newGuild[key] = value;
|
||||||
return { key, oldValue: cachedValue, value };
|
return { key, oldValue: cachedValue, value };
|
||||||
}
|
}
|
||||||
}).filter((change) => change) as GuildUpdateChange[];
|
}).filter((change) => change) as GuildUpdateChange[];
|
||||||
|
|
||||||
await cacheHandlers.set("guilds", payload.id, cachedGuild);
|
await cacheHandlers.set("guilds", payload.id, newGuild);
|
||||||
|
|
||||||
eventHandlers.guildUpdate?.(cachedGuild, changes);
|
eventHandlers.guildUpdate?.(newGuild, changes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,17 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import {
|
||||||
|
DiscordIntegrationCreateUpdate,
|
||||||
|
IntegrationCreateUpdate,
|
||||||
|
} from "../../types/integration/integration_create_update.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
export function handleIntegrationCreate(
|
export function handleIntegrationCreate(
|
||||||
data: DiscordGatewayPayload,
|
data: DiscordGatewayPayload,
|
||||||
) {
|
) {
|
||||||
const {
|
const payload = data.d as DiscordIntegrationCreateUpdate;
|
||||||
guild_id: guildId,
|
|
||||||
enable_emoticons: enableEmoticons,
|
|
||||||
expire_behavior: expireBehavior,
|
|
||||||
expire_grace_period: expireGracePeriod,
|
|
||||||
subscriber_count: subscriberCount,
|
|
||||||
role_id: roleId,
|
|
||||||
synced_at: syncedAt,
|
|
||||||
...rest
|
|
||||||
} = data.d as IntegrationCreateUpdateEvent;
|
|
||||||
|
|
||||||
eventHandlers.integrationCreate?.({
|
eventHandlers.integrationCreate?.(
|
||||||
...rest,
|
snakeKeysToCamelCase(payload) as IntegrationCreateUpdate,
|
||||||
guildId,
|
);
|
||||||
enableEmoticons,
|
|
||||||
expireBehavior,
|
|
||||||
expireGracePeriod,
|
|
||||||
syncedAt,
|
|
||||||
subscriberCount,
|
|
||||||
roleId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import {
|
||||||
|
DiscordIntegrationDelete,
|
||||||
|
IntegrationDelete,
|
||||||
|
} from "../../types/integration/integration_delete.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
export function handleIntegrationDelete(data: DiscordGatewayPayload) {
|
export function handleIntegrationDelete(data: DiscordGatewayPayload) {
|
||||||
const {
|
const payload = data.d as DiscordIntegrationDelete;
|
||||||
guild_id: guildId,
|
|
||||||
application_id: applicationId,
|
|
||||||
...rest
|
|
||||||
} = data.d as IntegrationDeleteEvent;
|
|
||||||
|
|
||||||
eventHandlers.integrationDelete?.({
|
eventHandlers.integrationDelete?.(
|
||||||
...rest,
|
snakeKeysToCamelCase(payload) as IntegrationDelete,
|
||||||
applicationId,
|
);
|
||||||
guildId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,15 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import {
|
||||||
|
DiscordIntegrationCreateUpdate,
|
||||||
|
IntegrationCreateUpdate,
|
||||||
|
} from "../../types/integration/integration_create_update.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
export function handleIntegrationUpdate(data: DiscordGatewayPayload) {
|
export function handleIntegrationUpdate(data: DiscordGatewayPayload) {
|
||||||
const {
|
const payload = data.d as DiscordIntegrationCreateUpdate;
|
||||||
enable_emoticons: enableEmoticons,
|
|
||||||
expire_behavior: expireBehavior,
|
|
||||||
expire_grace_period: expireGracePeriod,
|
|
||||||
role_id: roleId,
|
|
||||||
subscriber_count: subscriberCount,
|
|
||||||
synced_at: syncedAt,
|
|
||||||
guild_id: guildId,
|
|
||||||
...rest
|
|
||||||
} = data.d as IntegrationCreateUpdateEvent;
|
|
||||||
|
|
||||||
eventHandlers.integrationUpdate?.({
|
eventHandlers.integrationUpdate?.(
|
||||||
...rest,
|
snakeKeysToCamelCase(payload) as IntegrationCreateUpdate,
|
||||||
guildId,
|
);
|
||||||
subscriberCount,
|
|
||||||
enableEmoticons,
|
|
||||||
expireGracePeriod,
|
|
||||||
roleId,
|
|
||||||
expireBehavior,
|
|
||||||
syncedAt,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,13 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import { DiscordInviteCreate } from "../../types/invites/invite_create.ts";
|
import {
|
||||||
|
DiscordInviteCreate,
|
||||||
|
InviteCreate,
|
||||||
|
} from "../../types/invites/invite_create.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
export function handleInviteCreate(payload: DiscordGatewayPayload) {
|
export function handleInviteCreate(data: DiscordGatewayPayload) {
|
||||||
// TODO: replace with tocamelcase
|
const payload = data.d as DiscordInviteCreate;
|
||||||
const {
|
|
||||||
channel_id: channelId,
|
|
||||||
created_at: createdAt,
|
|
||||||
max_age: maxAge,
|
|
||||||
guild_id: guildId,
|
|
||||||
target_user: targetUser,
|
|
||||||
target_user_type: targetUserType,
|
|
||||||
max_uses: maxUses,
|
|
||||||
...rest
|
|
||||||
} = payload.d as DiscordInviteCreate;
|
|
||||||
|
|
||||||
eventHandlers.inviteCreate?.({
|
eventHandlers.inviteCreate?.(snakeKeysToCamelCase(payload) as InviteCreate);
|
||||||
...rest,
|
|
||||||
channelId,
|
|
||||||
guildId,
|
|
||||||
maxAge,
|
|
||||||
targetUser,
|
|
||||||
targetUserType,
|
|
||||||
maxUses,
|
|
||||||
createdAt,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
import { eventHandlers } from "../../bot.ts";
|
import { eventHandlers } from "../../bot.ts";
|
||||||
import { DiscordInviteDelete } from "../../types/invites/invite_delete.ts";
|
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
|
import {
|
||||||
|
DiscordInviteDelete,
|
||||||
|
InviteDelete,
|
||||||
|
} from "../../types/invites/invite_delete.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
export function handleInviteDelete(payload: DiscordGatewayPayload) {
|
export function handleInviteDelete(data: DiscordGatewayPayload) {
|
||||||
const {
|
const payload = data.d as DiscordInviteDelete;
|
||||||
channel_id: channelId,
|
|
||||||
guild_id: guildId,
|
|
||||||
...rest
|
|
||||||
} = payload.d as DiscordInviteDelete;
|
|
||||||
|
|
||||||
eventHandlers.inviteDelete?.({
|
eventHandlers.inviteDelete?.(snakeKeysToCamelCase(payload) as InviteDelete);
|
||||||
...rest,
|
|
||||||
channelId,
|
|
||||||
guildId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import { cache, cacheHandlers } from "../../cache.ts";
|
|||||||
import { initialMemberLoadQueue } from "../../structures/guild.ts";
|
import { initialMemberLoadQueue } from "../../structures/guild.ts";
|
||||||
import { structures } from "../../structures/mod.ts";
|
import { structures } from "../../structures/mod.ts";
|
||||||
import { delay } from "../../util/utils.ts";
|
import { delay } from "../../util/utils.ts";
|
||||||
import { allowNextShard, basicShards } from "../../ws/mod.ts";
|
|
||||||
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
|
||||||
import { DiscordReady } from "../../types/gateway/ready.ts";
|
import { DiscordReady } from "../../types/gateway/ready.ts";
|
||||||
|
import { ws } from "../../ws/ws.ts";
|
||||||
|
|
||||||
export async function handleReady(
|
export async function handleReady(
|
||||||
data: DiscordGatewayPayload,
|
data: DiscordGatewayPayload,
|
||||||
@@ -28,7 +28,7 @@ export async function handleReady(
|
|||||||
// Save when the READY event was received to prevent infinite load loops
|
// Save when the READY event was received to prevent infinite load loops
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
const shard = basicShards.get(shardId);
|
const shard = ws.shards.get(shardId);
|
||||||
if (!shard) return;
|
if (!shard) return;
|
||||||
|
|
||||||
// Set ready to false just to go sure
|
// Set ready to false just to go sure
|
||||||
@@ -41,13 +41,13 @@ export async function handleReady(
|
|||||||
|
|
||||||
// Wait 5 seconds to spawn next shard
|
// Wait 5 seconds to spawn next shard
|
||||||
await delay(5000);
|
await delay(5000);
|
||||||
allowNextShard();
|
ws.createNextShard = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't pass the shard itself because unavailableGuilds won't be updated by the GUILD_CREATE event
|
// Don't pass the shard itself because unavailableGuilds won't be updated by the GUILD_CREATE event
|
||||||
/** This function checks if the shard is fully loaded */
|
/** This function checks if the shard is fully loaded */
|
||||||
function checkReady(payload: DiscordReady, shardId: number, now: number) {
|
function checkReady(payload: DiscordReady, shardId: number, now: number) {
|
||||||
const shard = basicShards.get(shardId);
|
const shard = ws.shards.get(shardId);
|
||||||
if (!shard) return;
|
if (!shard) return;
|
||||||
|
|
||||||
// Check if all guilds were loaded
|
// Check if all guilds were loaded
|
||||||
@@ -67,7 +67,7 @@ function checkReady(payload: DiscordReady, shardId: number, now: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loaded(shardId: number) {
|
async function loaded(shardId: number) {
|
||||||
const shard = basicShards.get(shardId);
|
const shard = ws.shards.get(shardId);
|
||||||
if (!shard) return;
|
if (!shard) return;
|
||||||
|
|
||||||
shard.ready = true;
|
shard.ready = true;
|
||||||
@@ -75,7 +75,7 @@ async function loaded(shardId: number) {
|
|||||||
// If it is the last shard we can go full ready
|
// If it is the last shard we can go full ready
|
||||||
if (shardId === lastShardId - 1) {
|
if (shardId === lastShardId - 1) {
|
||||||
// Still some shards are loading so wait another 2 seconds for them
|
// Still some shards are loading so wait another 2 seconds for them
|
||||||
if (basicShards.some((shard) => !shard.ready)) {
|
if (ws.shards.some((shard) => !shard.ready)) {
|
||||||
setTimeout(() => loaded(shardId), 2000);
|
setTimeout(() => loaded(shardId), 2000);
|
||||||
} else {
|
} else {
|
||||||
cache.isReady = true;
|
cache.isReady = true;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export async function deleteChannel(
|
|||||||
guildId: string,
|
guildId: string,
|
||||||
channelId: string,
|
channelId: string,
|
||||||
reason?: string,
|
reason?: string,
|
||||||
) {
|
): Promise<undefined> {
|
||||||
await requireBotGuildPermissions(guildId, ["MANAGE_CHANNELS"]);
|
await requireBotGuildPermissions(guildId, ["MANAGE_CHANNELS"]);
|
||||||
|
|
||||||
const guild = await cacheHandlers.get("guilds", guildId);
|
const guild = await cacheHandlers.get("guilds", guildId);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export async function deleteChannelOverwrite(
|
|||||||
guildId: string,
|
guildId: string,
|
||||||
channelId: string,
|
channelId: string,
|
||||||
overwriteId: string,
|
overwriteId: string,
|
||||||
) {
|
): Promise<undefined> {
|
||||||
await requireBotGuildPermissions(guildId, ["MANAGE_ROLES"]);
|
await requireBotGuildPermissions(guildId, ["MANAGE_ROLES"]);
|
||||||
|
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { ModifyChannel } from "../../types/channels/modify_channel.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import {
|
import {
|
||||||
calculateBits,
|
calculateBits,
|
||||||
@@ -8,7 +9,7 @@ import {
|
|||||||
/** Update a channel's settings. Requires the `MANAGE_CHANNELS` permission for the guild. */
|
/** Update a channel's settings. Requires the `MANAGE_CHANNELS` permission for the guild. */
|
||||||
export async function editChannel(
|
export async function editChannel(
|
||||||
channelId: string,
|
channelId: string,
|
||||||
options: ChannelEditOptions,
|
options: ModifyChannel,
|
||||||
reason?: string,
|
reason?: string,
|
||||||
) {
|
) {
|
||||||
await requireBotChannelPermissions(channelId, ["MANAGE_CHANNELS"]);
|
await requireBotChannelPermissions(channelId, ["MANAGE_CHANNELS"]);
|
||||||
@@ -47,7 +48,7 @@ export async function editChannel(
|
|||||||
// deno-lint-ignore camelcase
|
// deno-lint-ignore camelcase
|
||||||
user_limit: options.userLimit,
|
user_limit: options.userLimit,
|
||||||
// deno-lint-ignore camelcase
|
// deno-lint-ignore camelcase
|
||||||
permission_overwrites: options.overwrites?.map((overwrite) => {
|
permission_overwrites: options.permissionOverwrites?.map((overwrite) => {
|
||||||
return {
|
return {
|
||||||
...overwrite,
|
...overwrite,
|
||||||
allow: calculateBits(overwrite.allow),
|
allow: calculateBits(overwrite.allow),
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export async function editChannelOverwrite(
|
|||||||
channelId: string,
|
channelId: string,
|
||||||
overwriteId: string,
|
overwriteId: string,
|
||||||
options: Omit<Overwrite, "id">,
|
options: Omit<Overwrite, "id">,
|
||||||
) {
|
): Promise<undefined> {
|
||||||
await requireBotGuildPermissions(guildId, ["MANAGE_ROLES"]);
|
await requireBotGuildPermissions(guildId, ["MANAGE_ROLES"]);
|
||||||
|
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { botHasChannelPermissions } from "../../util/permissions.ts";
|
|||||||
* However, if a bot is responding to a command and expects the computation to take a few seconds,
|
* However, if a bot is responding to a command and expects the computation to take a few seconds,
|
||||||
* this endpoint may be called to let the user know that the bot is processing their message.
|
* this endpoint may be called to let the user know that the bot is processing their message.
|
||||||
*/
|
*/
|
||||||
export async function startTyping(channelId: string) {
|
export async function startTyping(channelId: string): Promise<undefined> {
|
||||||
const channel = await cacheHandlers.get("channels", channelId);
|
const channel = await cacheHandlers.get("channels", channelId);
|
||||||
// If the channel is cached, we can do extra checks/safety
|
// If the channel is cached, we can do extra checks/safety
|
||||||
if (channel) {
|
if (channel) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { endpoints } from "../../util/constants.ts";
|
|||||||
export async function swapChannels(
|
export async function swapChannels(
|
||||||
guildId: string,
|
guildId: string,
|
||||||
channelPositions: ModifyGuildChannelPositions[],
|
channelPositions: ModifyGuildChannelPositions[],
|
||||||
) {
|
): Promise<undefined> {
|
||||||
if (channelPositions.length < 2) {
|
if (channelPositions.length < 2) {
|
||||||
throw "You must provide at least two channels to be swapped.";
|
throw "You must provide at least two channels to be swapped.";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { applicationId } from "../../bot.ts";
|
import { applicationId } from "../../bot.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { CreateGlobalApplicationCommand } from "../../types/interactions/create_global_application_command.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { validateSlashCommands } from "../../util/utils.ts";
|
import {
|
||||||
|
camelKeysToSnakeCase,
|
||||||
|
validateSlashCommands,
|
||||||
|
} from "../../util/utils.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There are two kinds of Slash Commands: global commands and guild commands. Global commands are available for every guild that adds your app; guild commands are specific to the guild you specify when making them. Command names are unique per application within each scope (global and guild). That means:
|
* There are two kinds of Slash Commands: global commands and guild commands. Global commands are available for every guild that adds your app; guild commands are specific to the guild you specify when making them. Command names are unique per application within each scope (global and guild). That means:
|
||||||
@@ -14,17 +18,18 @@ import { validateSlashCommands } from "../../util/utils.ts";
|
|||||||
* Global commands are cached for **1 hour**. That means that new global commands will fan out slowly across all guilds, and will be guaranteed to be updated in an hour.
|
* Global commands are cached for **1 hour**. That means that new global commands will fan out slowly across all guilds, and will be guaranteed to be updated in an hour.
|
||||||
* Guild commands update **instantly**. We recommend you use guild commands for quick testing, and global commands when they're ready for public use.
|
* Guild commands update **instantly**. We recommend you use guild commands for quick testing, and global commands when they're ready for public use.
|
||||||
*/
|
*/
|
||||||
export async function createSlashCommand(options: CreateSlashCommandOptions) {
|
export async function createSlashCommand(
|
||||||
|
options: CreateGlobalApplicationCommand,
|
||||||
|
guildId: string,
|
||||||
|
) {
|
||||||
validateSlashCommands([options], true);
|
validateSlashCommands([options], true);
|
||||||
|
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
"post",
|
"post",
|
||||||
options.guildId
|
guildId
|
||||||
? endpoints.COMMANDS_GUILD(applicationId, options.guildId)
|
? endpoints.COMMANDS_GUILD(applicationId, guildId)
|
||||||
: endpoints.COMMANDS(applicationId),
|
: endpoints.COMMANDS(applicationId),
|
||||||
{
|
camelKeysToSnakeCase(options),
|
||||||
...options,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -3,12 +3,16 @@ import { rest } from "../../rest/rest.ts";
|
|||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** Deletes a slash command. */
|
/** Deletes a slash command. */
|
||||||
export function deleteSlashCommand(id: string, guildId?: string) {
|
export async function deleteSlashCommand(
|
||||||
if (!guildId) {
|
id: string,
|
||||||
return rest.runMethod("delete", endpoints.COMMANDS_ID(applicationId, id));
|
guildId?: string,
|
||||||
}
|
): Promise<undefined> {
|
||||||
return rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
"delete",
|
"delete",
|
||||||
endpoints.COMMANDS_GUILD_ID(applicationId, guildId, id),
|
guildId
|
||||||
|
? endpoints.COMMANDS_GUILD_ID(applicationId, guildId, id)
|
||||||
|
: endpoints.COMMANDS_ID(applicationId, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { rest } from "../../rest/rest.ts";
|
|||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** To delete your response to a slash command. If a message id is not provided, it will default to deleting the original response. */
|
/** To delete your response to a slash command. If a message id is not provided, it will default to deleting the original response. */
|
||||||
export async function deleteSlashResponse(token: string, messageId?: string) {
|
export async function deleteSlashResponse(
|
||||||
|
token: string,
|
||||||
|
messageId?: string,
|
||||||
|
): Promise<undefined> {
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
"delete",
|
"delete",
|
||||||
messageId
|
messageId
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import { applicationId } from "../../bot.ts";
|
import { applicationId } from "../../bot.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
import { structures } from "../../structures/mod.ts";
|
import { structures } from "../../structures/mod.ts";
|
||||||
|
import { DiscordenoEditWebhookMessage } from "../../types/discordeno/edit_webhook_message.ts";
|
||||||
|
import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts";
|
||||||
|
import { DiscordMessage } from "../../types/messages/message.ts";
|
||||||
import { Errors } from "../../types/misc/errors.ts";
|
import { Errors } from "../../types/misc/errors.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** To edit your response to a slash command. If a messageId is not provided it will default to editing the original response. */
|
/** To edit your response to a slash command. If a messageId is not provided it will default to editing the original response. */
|
||||||
export async function editSlashResponse(
|
export async function editSlashResponse(
|
||||||
token: string,
|
token: string,
|
||||||
options: EditSlashResponseOptions,
|
options: DiscordenoEditWebhookMessage,
|
||||||
) {
|
) {
|
||||||
if (options.content && options.content.length > 2000) {
|
if (options.content && options.content.length > 2000) {
|
||||||
throw Error(Errors.MESSAGE_MAX_LENGTH);
|
throw Error(Errors.MESSAGE_MAX_LENGTH);
|
||||||
@@ -17,31 +20,39 @@ export async function editSlashResponse(
|
|||||||
options.embeds.splice(10);
|
options.embeds.splice(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.allowed_mentions) {
|
if (options.allowedMentions) {
|
||||||
if (options.allowed_mentions.users?.length) {
|
if (options.allowedMentions.users?.length) {
|
||||||
if (options.allowed_mentions.parse.includes("users")) {
|
if (
|
||||||
options.allowed_mentions.parse = options.allowed_mentions.parse.filter(
|
options.allowedMentions.parse.includes(
|
||||||
|
DiscordAllowedMentionsTypes.UserMentions,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
options.allowedMentions.parse = options.allowedMentions.parse.filter(
|
||||||
(p) => p !== "users",
|
(p) => p !== "users",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.allowed_mentions.users.length > 100) {
|
if (options.allowedMentions.users.length > 100) {
|
||||||
options.allowed_mentions.users = options.allowed_mentions.users.slice(
|
options.allowedMentions.users = options.allowedMentions.users.slice(
|
||||||
0,
|
0,
|
||||||
100,
|
100,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.allowed_mentions.roles?.length) {
|
if (options.allowedMentions.roles?.length) {
|
||||||
if (options.allowed_mentions.parse.includes("roles")) {
|
if (
|
||||||
options.allowed_mentions.parse = options.allowed_mentions.parse.filter(
|
options.allowedMentions.parse.includes(
|
||||||
|
DiscordAllowedMentionsTypes.RoleMentions,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
options.allowedMentions.parse = options.allowedMentions.parse.filter(
|
||||||
(p) => p !== "roles",
|
(p) => p !== "roles",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.allowed_mentions.roles.length > 100) {
|
if (options.allowedMentions.roles.length > 100) {
|
||||||
options.allowed_mentions.roles = options.allowed_mentions.roles.slice(
|
options.allowedMentions.roles = options.allowedMentions.roles.slice(
|
||||||
0,
|
0,
|
||||||
100,
|
100,
|
||||||
);
|
);
|
||||||
@@ -61,7 +72,7 @@ export async function editSlashResponse(
|
|||||||
if (!options.messageId) return result;
|
if (!options.messageId) return result;
|
||||||
|
|
||||||
const message = await structures.createMessageStruct(
|
const message = await structures.createMessageStruct(
|
||||||
result as MessageCreateOptions,
|
result as DiscordMessage,
|
||||||
);
|
);
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { applicationId } from "../../bot.ts";
|
import { applicationId } from "../../bot.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { ApplicationCommand } from "../../types/interactions/application_command.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** Fetchs the global command for the given Id. If a guildId is provided, the guild command will be fetched. */
|
/** Fetchs the global command for the given Id. If a guildId is provided, the guild command will be fetched. */
|
||||||
@@ -11,5 +12,5 @@ export async function getSlashCommand(commandId: string, guildId?: string) {
|
|||||||
: endpoints.COMMANDS_ID(applicationId, commandId),
|
: endpoints.COMMANDS_ID(applicationId, commandId),
|
||||||
);
|
);
|
||||||
|
|
||||||
return result as SlashCommand;
|
return result as ApplicationCommand;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { applicationId } from "../../bot.ts";
|
import { applicationId } from "../../bot.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { ApplicationCommand } from "../../types/interactions/application_command.ts";
|
||||||
import { Collection } from "../../util/collection.ts";
|
import { Collection } from "../../util/collection.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ export async function getSlashCommands(guildId?: string) {
|
|||||||
guildId
|
guildId
|
||||||
? endpoints.COMMANDS_GUILD(applicationId, guildId)
|
? endpoints.COMMANDS_GUILD(applicationId, guildId)
|
||||||
: endpoints.COMMANDS(applicationId),
|
: endpoints.COMMANDS(applicationId),
|
||||||
)) as SlashCommand[];
|
)) as ApplicationCommand[];
|
||||||
|
|
||||||
return new Collection(result.map((command) => [command.name, command]));
|
return new Collection(result.map((command) => [command.name, command]));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { applicationId } from "../../bot.ts";
|
import { applicationId } from "../../bot.ts";
|
||||||
import { cache } from "../../cache.ts";
|
import { cache } from "../../cache.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { DiscordenoInteractionResponse } from "../../types/discordeno/interaction_response.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,7 +13,7 @@ import { endpoints } from "../../util/constants.ts";
|
|||||||
export async function sendInteractionResponse(
|
export async function sendInteractionResponse(
|
||||||
id: string,
|
id: string,
|
||||||
token: string,
|
token: string,
|
||||||
options: SlashCommandResponseOptions,
|
options: DiscordenoInteractionResponse,
|
||||||
) {
|
) {
|
||||||
// If its already been executed, we need to send a followup response
|
// If its already been executed, we need to send a followup response
|
||||||
if (cache.executedSlashCommands.has(token)) {
|
if (cache.executedSlashCommands.has(token)) {
|
||||||
@@ -30,12 +31,12 @@ export async function sendInteractionResponse(
|
|||||||
|
|
||||||
// If the user wants this as a private message mark it ephemeral
|
// If the user wants this as a private message mark it ephemeral
|
||||||
if (options.private) {
|
if (options.private) {
|
||||||
options.data.flags = 64;
|
options.data = { ...options.data, flags: 64 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no mentions are provided, force disable mentions
|
// If no mentions are provided, force disable mentions
|
||||||
if (!options.data.allowed_mentions) {
|
if (!options.data?.allowedMentions) {
|
||||||
options.data.allowed_mentions = { parse: [] };
|
options.data = { ...options.data, allowedMentions: { parse: [] } };
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { applicationId } from "../../bot.ts";
|
import { applicationId } from "../../bot.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { EditGlobalApplicationCommand } from "../../types/interactions/edit_global_application_command.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { validateSlashCommands } from "../../util/utils.ts";
|
import { validateSlashCommands } from "../../util/utils.ts";
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ import { validateSlashCommands } from "../../util/utils.ts";
|
|||||||
*/
|
*/
|
||||||
export async function upsertSlashCommand(
|
export async function upsertSlashCommand(
|
||||||
commandId: string,
|
commandId: string,
|
||||||
options: UpsertSlashCommandOptions,
|
options: EditGlobalApplicationCommand,
|
||||||
guildId?: string,
|
guildId?: string,
|
||||||
) {
|
) {
|
||||||
validateSlashCommands([options]);
|
validateSlashCommands([options]);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { applicationId } from "../../bot.ts";
|
import { applicationId } from "../../bot.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { EditGlobalApplicationCommand } from "../../types/interactions/edit_global_application_command.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { validateSlashCommands } from "../../util/utils.ts";
|
import { validateSlashCommands } from "../../util/utils.ts";
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ import { validateSlashCommands } from "../../util/utils.ts";
|
|||||||
* **NOTE:** Any slash commands that are not specified in this function will be **deleted**. If you don't provide the commandId and rename your command, the command gets a new Id.
|
* **NOTE:** Any slash commands that are not specified in this function will be **deleted**. If you don't provide the commandId and rename your command, the command gets a new Id.
|
||||||
*/
|
*/
|
||||||
export async function upsertSlashCommands(
|
export async function upsertSlashCommands(
|
||||||
options: UpsertSlashCommandsOptions[],
|
options: EditGlobalApplicationCommand[],
|
||||||
guildId?: string,
|
guildId?: string,
|
||||||
) {
|
) {
|
||||||
validateSlashCommands(options);
|
validateSlashCommands(options);
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { CreateGuildEmoji } from "../../types/emojis/create_guild_emoji.ts";
|
||||||
|
import { Emoji } from "../../types/emojis/emoji.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
import { urlToBase64 } from "../../util/utils.ts";
|
import { snakeKeysToCamelCase, urlToBase64 } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Create an emoji in the server. Emojis and animated emojis have a maximum file size of 256kb. Attempting to upload an emoji larger than this limit will fail and return 400 Bad Request and an error message, but not a JSON status code. If a URL is provided to the image parameter, Discordeno will automatically convert it to a base64 string internally. */
|
/** Create an emoji in the server. Emojis and animated emojis have a maximum file size of 256kb. Attempting to upload an emoji larger than this limit will fail and return 400 Bad Request and an error message, but not a JSON status code. If a URL is provided to the image parameter, Discordeno will automatically convert it to a base64 string internally. */
|
||||||
export async function createEmoji(
|
export async function createEmoji(
|
||||||
guildId: string,
|
guildId: string,
|
||||||
name: string,
|
name: string,
|
||||||
image: string,
|
image: string,
|
||||||
options: CreateEmojisOptions,
|
options: CreateGuildEmoji,
|
||||||
) {
|
) {
|
||||||
await requireBotGuildPermissions(guildId, ["MANAGE_EMOJIS"]);
|
await requireBotGuildPermissions(guildId, ["MANAGE_EMOJIS"]);
|
||||||
|
|
||||||
@@ -22,5 +24,5 @@ export async function createEmoji(
|
|||||||
image,
|
image,
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return snakeKeysToCamelCase(result) as Emoji;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export async function deleteEmoji(
|
|||||||
guildId: string,
|
guildId: string,
|
||||||
id: string,
|
id: string,
|
||||||
reason?: string,
|
reason?: string,
|
||||||
) {
|
): Promise<undefined> {
|
||||||
await requireBotGuildPermissions(guildId, ["MANAGE_EMOJIS"]);
|
await requireBotGuildPermissions(guildId, ["MANAGE_EMOJIS"]);
|
||||||
|
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { ModifyGuildEmoji } from "../../types/emojis/modify_guild_emoji.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@ import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
|||||||
export async function editEmoji(
|
export async function editEmoji(
|
||||||
guildId: string,
|
guildId: string,
|
||||||
id: string,
|
id: string,
|
||||||
options: EditEmojisOptions,
|
options: ModifyGuildEmoji,
|
||||||
) {
|
) {
|
||||||
await requireBotGuildPermissions(guildId, ["MANAGE_EMOJIS"]);
|
await requireBotGuildPermissions(guildId, ["MANAGE_EMOJIS"]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { cacheHandlers } from "../../cache.ts";
|
import { cacheHandlers } from "../../cache.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { Emoji } from "../../types/emojis/emoji.ts";
|
||||||
import { Errors } from "../../types/misc/errors.ts";
|
import { Errors } from "../../types/misc/errors.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ export async function getEmoji(
|
|||||||
if (addToCache) {
|
if (addToCache) {
|
||||||
const guild = await cacheHandlers.get("guilds", guildId);
|
const guild = await cacheHandlers.get("guilds", guildId);
|
||||||
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
|
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
|
||||||
guild.emojis.set(result.id ?? result.name, result);
|
guild.emojis.set(emojiId, result);
|
||||||
cacheHandlers.set(
|
cacheHandlers.set(
|
||||||
"guilds",
|
"guilds",
|
||||||
guildId,
|
guildId,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { cacheHandlers } from "../../cache.ts";
|
import { cacheHandlers } from "../../cache.ts";
|
||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { Emoji } from "../../types/emojis/emoji.ts";
|
||||||
import { Errors } from "../../types/misc/errors.ts";
|
import { Errors } from "../../types/misc/errors.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ export async function getEmojis(guildId: string, addToCache = true) {
|
|||||||
const guild = await cacheHandlers.get("guilds", guildId);
|
const guild = await cacheHandlers.get("guilds", guildId);
|
||||||
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
|
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
|
||||||
|
|
||||||
result.forEach((emoji) => guild.emojis.set(emoji.id ?? emoji.name, emoji));
|
result.forEach((emoji) => guild.emojis.set(emoji.id!, emoji));
|
||||||
|
|
||||||
cacheHandlers.set("guilds", guildId, guild);
|
cacheHandlers.set("guilds", guildId, guild);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
import { structures } from "../../structures/mod.ts";
|
import { structures } from "../../structures/mod.ts";
|
||||||
|
import { CreateGuild } from "../../types/guilds/create_guild.ts";
|
||||||
|
import { DiscordGuild } from "../../types/guilds/guild.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** Create a new guild. Returns a guild object on success. Fires a Guild Create Gateway event. This endpoint can be used only by bots in less than 10 guilds. */
|
/** Create a new guild. Returns a guild object on success. Fires a Guild Create Gateway event. This endpoint can be used only by bots in less than 10 guilds. */
|
||||||
export async function createGuild(options: CreateServerOptions) {
|
export async function createGuild(options: CreateGuild) {
|
||||||
const guild = (await rest.runMethod(
|
const guild = (await rest.runMethod(
|
||||||
"post",
|
"post",
|
||||||
endpoints.GUILDS,
|
endpoints.GUILDS,
|
||||||
options,
|
options,
|
||||||
)) as CreateGuildPayload;
|
)) as DiscordGuild;
|
||||||
|
|
||||||
return structures.createGuildStruct(guild, 0);
|
return structures.createGuildStruct(guild, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { endpoints } from "../../util/constants.ts";
|
|||||||
|
|
||||||
/** Delete a guild permanently. User must be owner. Returns 204 No Content on success. Fires a Guild Delete Gateway event.
|
/** Delete a guild permanently. User must be owner. Returns 204 No Content on success. Fires a Guild Delete Gateway event.
|
||||||
*/
|
*/
|
||||||
export async function deleteServer(guildId: string) {
|
export async function deleteServer(guildId: string): Promise<undefined> {
|
||||||
const result = await rest.runMethod("delete", endpoints.GUILDS_BASE(guildId));
|
const result = await rest.runMethod("delete", endpoints.GUILDS_BASE(guildId));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { structures } from "../../structures/mod.ts";
|
||||||
|
import { DiscordGuild } from "../../types/guilds/guild.ts";
|
||||||
|
import { ModifyGuild } from "../../types/guilds/modify_guild.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
import { urlToBase64 } from "../../util/utils.ts";
|
import { urlToBase64 } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Modify a guilds settings. Requires the MANAGE_GUILD permission. */
|
/** Modify a guilds settings. Requires the MANAGE_GUILD permission. */
|
||||||
export async function editGuild(guildId: string, options: GuildEditOptions) {
|
export async function editGuild(guildId: string, options: ModifyGuild) {
|
||||||
await requireBotGuildPermissions(guildId, ["MANAGE_GUILD"]);
|
await requireBotGuildPermissions(guildId, ["MANAGE_GUILD"]);
|
||||||
|
|
||||||
if (options.icon && !options.icon.startsWith("data:image/")) {
|
if (options.icon && !options.icon.startsWith("data:image/")) {
|
||||||
@@ -23,7 +26,7 @@ export async function editGuild(guildId: string, options: GuildEditOptions) {
|
|||||||
"patch",
|
"patch",
|
||||||
endpoints.GUILDS_BASE(guildId),
|
endpoints.GUILDS_BASE(guildId),
|
||||||
options,
|
options,
|
||||||
);
|
) as DiscordGuild;
|
||||||
|
|
||||||
return result;
|
return structures.createGuildStruct(result, -1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { GuildWidget } from "../../types/guilds/guild_widget.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Modify a guild widget object for the guild. Requires the MANAGE_GUILD permission. */
|
/** Modify a guild widget object for the guild. Requires the MANAGE_GUILD permission. */
|
||||||
export async function editWidget(
|
export async function editWidget(
|
||||||
@@ -19,5 +21,5 @@ export async function editWidget(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return snakeKeysToCamelCase(result) as GuildWidget;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { AuditLog } from "../../types/audit_log/audit_log.ts";
|
||||||
|
import { GetGuildAuditLog } from "../../types/audit_log/get_guild_audit_log.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
|
import {
|
||||||
|
camelKeysToSnakeCase,
|
||||||
|
snakeKeysToCamelCase,
|
||||||
|
} from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Returns the audit logs for the guild. Requires VIEW AUDIT LOGS permission */
|
/** Returns the audit logs for the guild. Requires VIEW AUDIT LOGS permission */
|
||||||
export async function getAuditLogs(
|
export async function getAuditLogs(
|
||||||
guildId: string,
|
guildId: string,
|
||||||
options: GetAuditLogsOptions,
|
options: GetGuildAuditLog,
|
||||||
) {
|
) {
|
||||||
await requireBotGuildPermissions(guildId, ["VIEW_AUDIT_LOG"]);
|
await requireBotGuildPermissions(guildId, ["VIEW_AUDIT_LOG"]);
|
||||||
|
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
"get",
|
"get",
|
||||||
endpoints.GUILD_AUDIT_LOGS(guildId),
|
endpoints.GUILD_AUDIT_LOGS(guildId),
|
||||||
{
|
camelKeysToSnakeCase({
|
||||||
...options,
|
...options,
|
||||||
action_type: options.action_type
|
|
||||||
? AuditLogs[options.action_type]
|
|
||||||
: undefined,
|
|
||||||
limit: options.limit && options.limit >= 1 && options.limit <= 100
|
limit: options.limit && options.limit >= 1 && options.limit <= 100
|
||||||
? options.limit
|
? options.limit
|
||||||
: 50,
|
: 50,
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return snakeKeysToCamelCase(result) as AuditLog;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { VoiceRegion } from "../../types/voice/voice_region.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** Returns an array of voice regions that can be used when creating servers. */
|
/** Returns an array of voice regions that can be used when creating servers. */
|
||||||
export async function getAvailableVoiceRegions() {
|
export async function getAvailableVoiceRegions() {
|
||||||
const result = await rest.runMethod("get", endpoints.VOICE_REGIONS);
|
const result = await rest.runMethod("get", endpoints.VOICE_REGIONS);
|
||||||
|
|
||||||
return result;
|
return result as VoiceRegion;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { Ban } from "../../types/guilds/ban.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Returns a ban object for the given user or a 404 not found if the ban cannot be found. Requires the BAN_MEMBERS permission. */
|
/** Returns a ban object for the given user or a 404 not found if the ban cannot be found. Requires the BAN_MEMBERS permission. */
|
||||||
export async function getBan(guildId: string, memberId: string) {
|
export async function getBan(guildId: string, memberId: string) {
|
||||||
@@ -11,5 +13,5 @@ export async function getBan(guildId: string, memberId: string) {
|
|||||||
endpoints.GUILD_BAN(guildId, memberId),
|
endpoints.GUILD_BAN(guildId, memberId),
|
||||||
);
|
);
|
||||||
|
|
||||||
return result as BannedUser;
|
return snakeKeysToCamelCase(result) as Ban;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { Ban, DiscordBan } from "../../types/guilds/ban.ts";
|
||||||
import { Collection } from "../../util/collection.ts";
|
import { Collection } from "../../util/collection.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Returns a list of ban objects for the users banned from this guild. Requires the BAN_MEMBERS permission. */
|
/** Returns a list of ban objects for the users banned from this guild. Requires the BAN_MEMBERS permission. */
|
||||||
export async function getBans(guildId: string) {
|
export async function getBans(guildId: string) {
|
||||||
@@ -10,9 +12,9 @@ export async function getBans(guildId: string) {
|
|||||||
const results = (await rest.runMethod(
|
const results = (await rest.runMethod(
|
||||||
"get",
|
"get",
|
||||||
endpoints.GUILD_BANS(guildId),
|
endpoints.GUILD_BANS(guildId),
|
||||||
)) as BannedUser[];
|
)) as DiscordBan[];
|
||||||
|
|
||||||
return new Collection<string, BannedUser>(
|
return new Collection<string, Ban>(
|
||||||
results.map((res) => [res.user.id, res]),
|
results.map((res) => [res.user.id, snakeKeysToCamelCase(res) as Ban]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { Guild } from "../../types/guilds/guild.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ⚠️ **If you need this, you are probably doing something wrong. Always use cache.guilds.get()
|
* ⚠️ **If you need this, you are probably doing something wrong. Always use cache.guilds.get()
|
||||||
@@ -13,5 +15,5 @@ export async function getGuild(guildId: string, counts = true) {
|
|||||||
with_counts: counts,
|
with_counts: counts,
|
||||||
});
|
});
|
||||||
|
|
||||||
return result as UpdateGuildPayload;
|
return snakeKeysToCamelCase(result) as Guild;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { GuildPreview } from "../../types/guilds/guild_preview.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Returns the guild preview object for the given id. If the bot is not in the guild, then the guild must be Discoverable. */
|
/** Returns the guild preview object for the given id. If the bot is not in the guild, then the guild must be Discoverable. */
|
||||||
export async function getGuildPreview(guildId: string) {
|
export async function getGuildPreview(guildId: string) {
|
||||||
const result = await rest.runMethod("get", endpoints.GUILD_PREVIEW(guildId));
|
const result = await rest.runMethod("get", endpoints.GUILD_PREVIEW(guildId));
|
||||||
|
|
||||||
return result;
|
return snakeKeysToCamelCase(result) as GuildPreview;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { GetGuildPruneCountQuery } from "../../types/guilds/get_guild_prune_count.ts";
|
||||||
import { Errors } from "../../types/misc/errors.ts";
|
import { Errors } from "../../types/misc/errors.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
import { camelKeysToSnakeCase } from "../../util/utils.ts";
|
import { camelKeysToSnakeCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Check how many members would be removed from the server in a prune operation. Requires the KICK_MEMBERS permission */
|
/** Check how many members would be removed from the server in a prune operation. Requires the KICK_MEMBERS permission */
|
||||||
export async function getPruneCount(guildId: string, options?: PruneOptions) {
|
export async function getPruneCount(
|
||||||
|
guildId: string,
|
||||||
|
options?: GetGuildPruneCountQuery,
|
||||||
|
) {
|
||||||
if (options?.days && options.days < 1) throw new Error(Errors.PRUNE_MIN_DAYS);
|
if (options?.days && options.days < 1) throw new Error(Errors.PRUNE_MIN_DAYS);
|
||||||
if (options?.days && options.days > 30) {
|
if (options?.days && options.days > 30) {
|
||||||
throw new Error(Errors.PRUNE_MAX_DAYS);
|
throw new Error(Errors.PRUNE_MAX_DAYS);
|
||||||
@@ -17,7 +21,7 @@ export async function getPruneCount(guildId: string, options?: PruneOptions) {
|
|||||||
"get",
|
"get",
|
||||||
endpoints.GUILD_PRUNE(guildId),
|
endpoints.GUILD_PRUNE(guildId),
|
||||||
camelKeysToSnakeCase(options ?? {}),
|
camelKeysToSnakeCase(options ?? {}),
|
||||||
) as PrunePayload;
|
);
|
||||||
|
|
||||||
return result.pruned;
|
return result.pruned as number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { InviteMetadata } from "../../types/invites/invite_metadata.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Returns the code and uses of the vanity url for this server if it is enabled. Requires the MANAGE_GUILD permission. */
|
/** Returns the code and uses of the vanity url for this server if it is enabled else `code` will be null. Requires the `MANAGE_GUILD` permission. */
|
||||||
export async function getVanityURL(guildId: string) {
|
export async function getVanityURL(guildId: string) {
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
"get",
|
"get",
|
||||||
endpoints.GUILD_VANITY_URL(guildId),
|
endpoints.GUILD_VANITY_URL(guildId),
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return snakeKeysToCamelCase(result) as
|
||||||
|
| (Partial<InviteMetadata> & Pick<InviteMetadata, "uses" | "code">)
|
||||||
|
| { code: null };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,22 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import {
|
||||||
|
DiscordVoiceRegion,
|
||||||
|
VoiceRegion,
|
||||||
|
} from "../../types/voice/voice_region.ts";
|
||||||
|
import { Collection } from "../../util/collection.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
import { snakeKeysToCamelCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Returns a list of voice region objects for the guild. Unlike the similar /voice route, this returns VIP servers when the guild is VIP-enabled. */
|
/** Returns a list of voice region objects for the guild. Unlike the similar /voice route, this returns VIP servers when the guild is VIP-enabled. */
|
||||||
export async function getVoiceRegions(guildId: string) {
|
export async function getVoiceRegions(guildId: string) {
|
||||||
const result = await rest.runMethod("get", endpoints.GUILD_REGIONS(guildId));
|
const result = await rest.runMethod(
|
||||||
|
"get",
|
||||||
|
endpoints.GUILD_REGIONS(guildId),
|
||||||
|
) as DiscordVoiceRegion[];
|
||||||
|
|
||||||
return result;
|
const convertedRegions = snakeKeysToCamelCase<VoiceRegion[]>(result);
|
||||||
|
|
||||||
|
return new Collection<string, VoiceRegion>(
|
||||||
|
convertedRegions.map((region) => [region.id, region]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { cacheHandlers } from "../../cache.ts";
|
import { cacheHandlers } from "../../cache.ts";
|
||||||
|
import { GetGuildWidgetImageQuery } from "../../types/guilds/get_guild_widget_image.ts";
|
||||||
import { Errors } from "../../types/misc/errors.ts";
|
import { Errors } from "../../types/misc/errors.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** Returns the widget image URL for the guild. */
|
/** Returns the widget image URL for the guild. */
|
||||||
export async function getWidgetImageURL(
|
export async function getWidgetImageURL(
|
||||||
guildId: string,
|
guildId: string,
|
||||||
options?: {
|
options?: GetGuildWidgetImageQuery & { force?: boolean },
|
||||||
style?: "shield" | "banner1" | "banner2" | "banner3" | "banner4";
|
|
||||||
force?: boolean;
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
if (!options?.force) {
|
if (!options?.force) {
|
||||||
const guild = await cacheHandlers.get("guilds", guildId);
|
const guild = await cacheHandlers.get("guilds", guildId);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
|
import { GuildWidget } from "../../types/guilds/guild_widget.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
import { requireBotGuildPermissions } from "../../util/permissions.ts";
|
||||||
|
|
||||||
@@ -8,5 +9,5 @@ export async function getWidgetSettings(guildId: string) {
|
|||||||
|
|
||||||
const result = await rest.runMethod("get", endpoints.GUILD_WIDGET(guildId));
|
const result = await rest.runMethod("get", endpoints.GUILD_WIDGET(guildId));
|
||||||
|
|
||||||
return result;
|
return result as GuildWidget;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { formatImageURL } from "../../util/utils.ts";
|
|||||||
/** The full URL of the banner from Discords CDN. Undefined if no banner is set. */
|
/** The full URL of the banner from Discords CDN. Undefined if no banner is set. */
|
||||||
export function guildBannerURL(
|
export function guildBannerURL(
|
||||||
id: string,
|
id: string,
|
||||||
banner: string,
|
banner?: string,
|
||||||
size: DiscordImageSize = 128,
|
size: DiscordImageSize = 128,
|
||||||
format?: DiscordImageFormat,
|
format?: DiscordImageFormat,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { formatImageURL } from "../../util/utils.ts";
|
|||||||
/** The full URL of the icon from Discords CDN. Undefined when no icon is set. */
|
/** The full URL of the icon from Discords CDN. Undefined when no icon is set. */
|
||||||
export function guildIconURL(
|
export function guildIconURL(
|
||||||
id: string,
|
id: string,
|
||||||
icon: string,
|
icon?: string,
|
||||||
size: DiscordImageSize = 128,
|
size: DiscordImageSize = 128,
|
||||||
format?: DiscordImageFormat,
|
format?: DiscordImageFormat,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { formatImageURL } from "../../util/utils.ts";
|
|||||||
/** The full URL of the splash from Discords CDN. Undefined if no splash is set. */
|
/** The full URL of the splash from Discords CDN. Undefined if no splash is set. */
|
||||||
export function guildSplashURL(
|
export function guildSplashURL(
|
||||||
id: string,
|
id: string,
|
||||||
splash: string,
|
splash?: string,
|
||||||
size: DiscordImageSize = 128,
|
size: DiscordImageSize = 128,
|
||||||
format?: DiscordImageFormat,
|
format?: DiscordImageFormat,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { rest } from "../../rest/rest.ts";
|
|||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
|
|
||||||
/** Leave a guild */
|
/** Leave a guild */
|
||||||
export async function leaveGuild(guildId: string) {
|
export async function leaveGuild(guildId: string): Promise<undefined> {
|
||||||
const result = await rest.runMethod("delete", endpoints.GUILD_LEAVE(guildId));
|
const result = await rest.runMethod("delete", endpoints.GUILD_LEAVE(guildId));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -2,15 +2,19 @@ import { cacheHandlers } from "../../cache.ts";
|
|||||||
import { rest } from "../../rest/rest.ts";
|
import { rest } from "../../rest/rest.ts";
|
||||||
import { structures } from "../../structures/mod.ts";
|
import { structures } from "../../structures/mod.ts";
|
||||||
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
|
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
|
||||||
|
import { DiscordenoCreateMessage } from "../../types/discordeno/create_message.ts";
|
||||||
|
import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts";
|
||||||
|
import { DiscordMessage } from "../../types/messages/message.ts";
|
||||||
import { Errors } from "../../types/misc/errors.ts";
|
import { Errors } from "../../types/misc/errors.ts";
|
||||||
import { PermissionStrings } from "../../types/permissions/permission_strings.ts";
|
import { PermissionStrings } from "../../types/permissions/permission_strings.ts";
|
||||||
import { endpoints } from "../../util/constants.ts";
|
import { endpoints } from "../../util/constants.ts";
|
||||||
import { requireBotChannelPermissions } from "../../util/permissions.ts";
|
import { requireBotChannelPermissions } from "../../util/permissions.ts";
|
||||||
|
import { camelKeysToSnakeCase } from "../../util/utils.ts";
|
||||||
|
|
||||||
/** Send a message to the channel. Requires SEND_MESSAGES permission. */
|
/** Send a message to the channel. Requires SEND_MESSAGES permission. */
|
||||||
export async function sendMessage(
|
export async function sendMessage(
|
||||||
channelId: string,
|
channelId: string,
|
||||||
content: string | MessageContent,
|
content: string | DiscordenoCreateMessage,
|
||||||
) {
|
) {
|
||||||
if (typeof content === "string") content = { content };
|
if (typeof content === "string") content = { content };
|
||||||
|
|
||||||
@@ -33,7 +37,10 @@ export async function sendMessage(
|
|||||||
|
|
||||||
if (content.tts) requiredPerms.add("SEND_TTS_MESSAGES");
|
if (content.tts) requiredPerms.add("SEND_TTS_MESSAGES");
|
||||||
if (content.embed) requiredPerms.add("EMBED_LINKS");
|
if (content.embed) requiredPerms.add("EMBED_LINKS");
|
||||||
if (content.replyMessageId || content.mentions?.repliedUser) {
|
if (
|
||||||
|
content.messageReference?.messageId ||
|
||||||
|
content.allowedMentions?.repliedUser
|
||||||
|
) {
|
||||||
requiredPerms.add("READ_MESSAGE_HISTORY");
|
requiredPerms.add("READ_MESSAGE_HISTORY");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,50 +52,63 @@ export async function sendMessage(
|
|||||||
throw new Error(Errors.MESSAGE_MAX_LENGTH);
|
throw new Error(Errors.MESSAGE_MAX_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.mentions) {
|
if (content.allowedMentions) {
|
||||||
if (content.mentions.users?.length) {
|
if (content.allowedMentions.users?.length) {
|
||||||
if (content.mentions.parse?.includes("users")) {
|
if (
|
||||||
content.mentions.parse = content.mentions.parse.filter(
|
content.allowedMentions.parse?.includes(
|
||||||
|
DiscordAllowedMentionsTypes.UserMentions,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
content.allowedMentions.parse = content.allowedMentions.parse.filter(
|
||||||
(p) => p !== "users",
|
(p) => p !== "users",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.mentions.users.length > 100) {
|
if (content.allowedMentions.users.length > 100) {
|
||||||
content.mentions.users = content.mentions.users.slice(0, 100);
|
content.allowedMentions.users = content.allowedMentions.users.slice(
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.mentions.roles?.length) {
|
if (content.allowedMentions.roles?.length) {
|
||||||
if (content.mentions.parse?.includes("roles")) {
|
if (
|
||||||
content.mentions.parse = content.mentions.parse.filter(
|
content.allowedMentions.parse?.includes(
|
||||||
|
DiscordAllowedMentionsTypes.RoleMentions,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
content.allowedMentions.parse = content.allowedMentions.parse.filter(
|
||||||
(p) => p !== "roles",
|
(p) => p !== "roles",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.mentions.roles.length > 100) {
|
if (content.allowedMentions.roles.length > 100) {
|
||||||
content.mentions.roles = content.mentions.roles.slice(0, 100);
|
content.allowedMentions.roles = content.allowedMentions.roles.slice(
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const result =
|
const result =
|
||||||
(await rest.runMethod("post", endpoints.CHANNEL_MESSAGES(channelId), {
|
(await rest.runMethod(
|
||||||
|
"post",
|
||||||
|
endpoints.CHANNEL_MESSAGES(channelId),
|
||||||
|
camelKeysToSnakeCase({
|
||||||
...content,
|
...content,
|
||||||
allowed_mentions: content.mentions
|
...(content.messageReference?.messageId
|
||||||
? {
|
? {
|
||||||
...content.mentions,
|
messageReference: {
|
||||||
replied_user: content.mentions.repliedUser,
|
...content.messageReference,
|
||||||
}
|
failIfNotExists:
|
||||||
: undefined,
|
content.messageReference.failIfNotExists === true,
|
||||||
...(content.replyMessageId
|
|
||||||
? {
|
|
||||||
message_reference: {
|
|
||||||
message_id: content.replyMessageId,
|
|
||||||
fail_if_not_exists: content.failReplyIfNotExists === true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
})) as MessageCreateOptions;
|
}),
|
||||||
|
)) as DiscordMessage;
|
||||||
|
|
||||||
return structures.createMessageStruct(result);
|
return structures.createMessageStruct(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { endpoints } from "../../util/constants.ts";
|
|||||||
import { requireBotChannelPermissions } from "../../util/permissions.ts";
|
import { requireBotChannelPermissions } from "../../util/permissions.ts";
|
||||||
|
|
||||||
/** Unpin a message in a channel. Requires MANAGE_MESSAGES. */
|
/** Unpin a message in a channel. Requires MANAGE_MESSAGES. */
|
||||||
export async function unpin(channelId: string, messageId: string) {
|
export async function unpin(
|
||||||
|
channelId: string,
|
||||||
|
messageId: string,
|
||||||
|
): Promise<undefined> {
|
||||||
await requireBotChannelPermissions(channelId, ["MANAGE_MESSAGES"]);
|
await requireBotChannelPermissions(channelId, ["MANAGE_MESSAGES"]);
|
||||||
|
|
||||||
const result = await rest.runMethod(
|
const result = await rest.runMethod(
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import { Errors } from "../types/misc/errors.ts";
|
import { Errors } from "../types/misc/errors.ts";
|
||||||
import { IMAGE_BASE_URL } from "../util/constants.ts";
|
import { API_VERSION, BASE_URL, IMAGE_BASE_URL } from "../util/constants.ts";
|
||||||
import { API_VERSION } from "../util/constants.ts";
|
|
||||||
import { BASE_URL } from "../util/constants.ts";
|
|
||||||
import { rest } from "./rest.ts";
|
import { rest } from "./rest.ts";
|
||||||
|
|
||||||
export function runMethod(
|
export function runMethod<T = any>(
|
||||||
method: "get" | "post" | "put" | "delete" | "patch",
|
method: "get" | "post" | "put" | "delete" | "patch",
|
||||||
url: string,
|
url: string,
|
||||||
body?: unknown,
|
body?: unknown,
|
||||||
retryCount = 0,
|
retryCount = 0,
|
||||||
bucketId?: string | null,
|
bucketId?: string | null,
|
||||||
) {
|
): Promise<T | undefined> {
|
||||||
rest.eventHandlers.debug?.("requestCreate", {
|
rest.eventHandlers.debug?.("requestCreate", {
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
@@ -37,7 +35,7 @@ export function runMethod(
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === 204) return undefined;
|
if (res.status === 204) return undefined;
|
||||||
|
|
||||||
return res.json();
|
return res.json() as unknown as T;
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
@@ -7,10 +7,16 @@ import { editChannelOverwrite } from "../helpers/channels/edit_channel_overwrite
|
|||||||
import { sendMessage } from "../helpers/messages/send_message.ts";
|
import { sendMessage } from "../helpers/messages/send_message.ts";
|
||||||
import { disconnectMember } from "../helpers/mod.ts";
|
import { disconnectMember } from "../helpers/mod.ts";
|
||||||
import { Channel, DiscordChannel } from "../types/channels/channel.ts";
|
import { Channel, DiscordChannel } from "../types/channels/channel.ts";
|
||||||
|
import { ModifyChannel } from "../types/channels/modify_channel.ts";
|
||||||
|
import { DiscordOverwrite, Overwrite } from "../types/channels/overwrite.ts";
|
||||||
|
import { CreateMessage } from "../types/messages/create_message.ts";
|
||||||
|
import { PermissionStrings } from "../types/permissions/permission_strings.ts";
|
||||||
|
import { VoiceState } from "../types/voice/voice_state.ts";
|
||||||
import { Collection } from "../util/collection.ts";
|
import { Collection } from "../util/collection.ts";
|
||||||
import { createNewProp, snakeKeysToCamelCase } from "../util/utils.ts";
|
import { createNewProp, snakeKeysToCamelCase } from "../util/utils.ts";
|
||||||
|
import { MessageStruct } from "./message.ts";
|
||||||
|
|
||||||
const baseChannel: Partial<Channel> = {
|
const baseChannel: Partial<ChannelStruct> = {
|
||||||
get guild() {
|
get guild() {
|
||||||
return cache.guilds.get(this.guildId!);
|
return cache.guilds.get(this.guildId!);
|
||||||
},
|
},
|
||||||
@@ -61,8 +67,8 @@ const baseChannel: Partial<Channel> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// deno-lint-ignore require-await
|
|
||||||
/** Create a structure object */
|
/** Create a structure object */
|
||||||
|
// deno-lint-ignore require-await
|
||||||
export async function createChannelStruct(
|
export async function createChannelStruct(
|
||||||
data: DiscordChannel,
|
data: DiscordChannel,
|
||||||
guildId?: string,
|
guildId?: string,
|
||||||
@@ -90,4 +96,61 @@ export async function createChannelStruct(
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ChannelStruct = Channel & typeof baseChannel;
|
export interface ChannelStruct extends Channel {
|
||||||
|
// GETTERS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the guild object for this channel.
|
||||||
|
*
|
||||||
|
* ⚠️ ADVANCED: If you use the custom cache, these will not work for you. Getters can not be async and custom cache requires async.
|
||||||
|
*/
|
||||||
|
guild?: GuildStruct;
|
||||||
|
/**
|
||||||
|
* Gets the messages from cache that were sent in this channel
|
||||||
|
*
|
||||||
|
* ⚠️ ADVANCED: If you use the custom cache, these will not work for you. Getters can not be async and custom cache requires async.
|
||||||
|
*/
|
||||||
|
messages: Collection<string, MessageStruct>;
|
||||||
|
/** The mention of the channel */
|
||||||
|
mention: string;
|
||||||
|
/**
|
||||||
|
* Gets the voice states for this channel
|
||||||
|
*
|
||||||
|
* ⚠️ ADVANCED: If you use the custom cache, these will not work for you. Getters can not be async and custom cache requires async.
|
||||||
|
*/
|
||||||
|
voiceStates?: Collection<string, VoiceState>;
|
||||||
|
/**
|
||||||
|
* Gets the connected members for this channel undefined if member is not cached
|
||||||
|
*
|
||||||
|
* ⚠️ ADVANCED: If you use the custom cache, these will not work for you. Getters can not be async and custom cache requires async.
|
||||||
|
*/
|
||||||
|
connectedMembers?: Collection<string, MemberStruct | undefined>;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
|
||||||
|
/** Send a message to the channel. Requires SEND_MESSAGES permission. */
|
||||||
|
send(content: string | CreateMessage): ReturnType<typeof sendMessage>;
|
||||||
|
/** Disconnect a member from a voice channel. Requires MOVE_MEMBERS permission. */
|
||||||
|
disconnect(memberID: string): ReturnType<typeof disconnectMember>;
|
||||||
|
/** Delete the channel */
|
||||||
|
delete(): ReturnType<typeof deleteChannel>;
|
||||||
|
/** Edit a channel Overwrite */
|
||||||
|
editOverwrite(
|
||||||
|
overwriteID: string,
|
||||||
|
options: Omit<Overwrite, "id">,
|
||||||
|
): ReturnType<typeof editChannelOverwrite>;
|
||||||
|
/** Delete a channel Overwrite */
|
||||||
|
deleteOverwrite(
|
||||||
|
overwriteID: string,
|
||||||
|
): ReturnType<typeof deleteChannelOverwrite>;
|
||||||
|
/** Checks if a channel overwrite for a user id or a role id has permission in this channel */
|
||||||
|
hasPermission(
|
||||||
|
overwrites: DiscordOverwrite[],
|
||||||
|
permissions: PermissionStrings[],
|
||||||
|
): ReturnType<typeof channelOverwriteHasPermission>;
|
||||||
|
/** Edit the channel */
|
||||||
|
edit(
|
||||||
|
options: ModifyChannel,
|
||||||
|
reason?: string,
|
||||||
|
): ReturnType<typeof editChannel>;
|
||||||
|
}
|
||||||
|
|||||||
+40
-9
@@ -13,17 +13,30 @@ import { getInvites } from "../helpers/invites/get_invites.ts";
|
|||||||
import { banMember } from "../helpers/members/ban_member.ts";
|
import { banMember } from "../helpers/members/ban_member.ts";
|
||||||
import { unbanMember } from "../helpers/members/unban_member.ts";
|
import { unbanMember } from "../helpers/members/unban_member.ts";
|
||||||
import { GetGuildAuditLog } from "../types/audit_log/get_guild_audit_log.ts";
|
import { GetGuildAuditLog } from "../types/audit_log/get_guild_audit_log.ts";
|
||||||
|
import { Emoji } from "../types/emojis/emoji.ts";
|
||||||
import { CreateGuildBan } from "../types/guilds/create_guild_ban.ts";
|
import { CreateGuildBan } from "../types/guilds/create_guild_ban.ts";
|
||||||
import { DiscordGuild, Guild } from "../types/guilds/guild.ts";
|
import { DiscordGuild, Guild } from "../types/guilds/guild.ts";
|
||||||
import { DiscordGuildFeatures } from "../types/guilds/guild_features.ts";
|
import { DiscordGuildFeatures } from "../types/guilds/guild_features.ts";
|
||||||
import { GuildMember } from "../types/guilds/guild_member.ts";
|
import {
|
||||||
|
DiscordGuildMember,
|
||||||
|
GuildMember,
|
||||||
|
} from "../types/guilds/guild_member.ts";
|
||||||
import { ModifyGuild } from "../types/guilds/modify_guild.ts";
|
import { ModifyGuild } from "../types/guilds/modify_guild.ts";
|
||||||
import { DiscordImageFormat } from "../types/misc/image_format.ts";
|
import { DiscordImageFormat } from "../types/misc/image_format.ts";
|
||||||
import { DiscordImageSize } from "../types/misc/image_size.ts";
|
import { DiscordImageSize } from "../types/misc/image_size.ts";
|
||||||
import { PresenceUpdate } from "../types/misc/presence_update.ts";
|
import { PresenceUpdate } from "../types/misc/presence_update.ts";
|
||||||
|
import { DiscordUser } from "../types/users/user.ts";
|
||||||
|
import { VoiceState } from "../types/voice/voice_state.ts";
|
||||||
import { Collection } from "../util/collection.ts";
|
import { Collection } from "../util/collection.ts";
|
||||||
import { createNewProp, snakeKeysToCamelCase } from "../util/utils.ts";
|
import {
|
||||||
import { RoleStruct, structures } from "./mod.ts";
|
camelKeysToSnakeCase,
|
||||||
|
createNewProp,
|
||||||
|
snakeKeysToCamelCase,
|
||||||
|
} from "../util/utils.ts";
|
||||||
|
import { ChannelStruct } from "./channel.ts";
|
||||||
|
import { MemberStruct } from "./member.ts";
|
||||||
|
import { structures } from "./mod.ts";
|
||||||
|
import { RoleStruct } from "./role.ts";
|
||||||
|
|
||||||
export const initialMemberLoadQueue = new Map<string, GuildMember[]>();
|
export const initialMemberLoadQueue = new Map<string, GuildMember[]>();
|
||||||
|
|
||||||
@@ -118,7 +131,9 @@ export async function createGuildStruct(
|
|||||||
} = snakeKeysToCamelCase(data) as Guild;
|
} = snakeKeysToCamelCase(data) as Guild;
|
||||||
|
|
||||||
const roles = await Promise.all(
|
const roles = await Promise.all(
|
||||||
data.roles.map((role) => structures.createRoleStruct(role)),
|
data.roles.map((role) =>
|
||||||
|
structures.createRoleStruct({ role, guild_id: rest.id })
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all(channels.map(async (channel) => {
|
await Promise.all(channels.map(async (channel) => {
|
||||||
@@ -164,7 +179,9 @@ export async function createGuildStruct(
|
|||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
members.map(async (member) => {
|
members.map(async (member) => {
|
||||||
const memberStruct = await structures.createMemberStruct(
|
const memberStruct = await structures.createMemberStruct(
|
||||||
member,
|
camelKeysToSnakeCase(member) as Omit<DiscordGuildMember, "user"> & {
|
||||||
|
user: DiscordUser;
|
||||||
|
},
|
||||||
guild.id,
|
guild.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -179,14 +196,25 @@ export async function createGuildStruct(
|
|||||||
export interface GuildStruct extends
|
export interface GuildStruct extends
|
||||||
Omit<
|
Omit<
|
||||||
Guild,
|
Guild,
|
||||||
"roles" | "presences" | "voiceStates" | "members" | "channels"
|
| "roles"
|
||||||
|
| "presences"
|
||||||
|
| "voiceStates"
|
||||||
|
| "members"
|
||||||
|
| "channels"
|
||||||
|
| "memberCount"
|
||||||
|
| "owner"
|
||||||
|
| "emojis"
|
||||||
> {
|
> {
|
||||||
|
/** Total number of members in this guild */
|
||||||
|
memberCount?: number;
|
||||||
/** The roles in the guild */
|
/** The roles in the guild */
|
||||||
roles: Collection<string, RoleStruct>;
|
roles: Collection<string, RoleStruct>;
|
||||||
/** The presences of all the users in the guild. */
|
/** The presences of all the users in the guild. */
|
||||||
presences: Collection<string, PresenceUpdate>;
|
presences: Collection<string, PresenceUpdate>;
|
||||||
/** The Voice State data for each user in a voice channel in this server. */
|
/** The Voice State data for each user in a voice channel in this server. */
|
||||||
voiceStates: Collection<string, CleanVoiceState>;
|
voiceStates: Collection<string, VoiceState>;
|
||||||
|
/** Custom guild emojis */
|
||||||
|
emojis: Collection<string, Emoji>;
|
||||||
|
|
||||||
// GETTERS
|
// GETTERS
|
||||||
/** Members in this guild. */
|
/** Members in this guild. */
|
||||||
@@ -204,9 +232,12 @@ export interface GuildStruct extends
|
|||||||
/** The bot member in this guild if cached */
|
/** The bot member in this guild if cached */
|
||||||
bot?: MemberStruct;
|
bot?: MemberStruct;
|
||||||
/** The bot guild member in this guild if cached */
|
/** The bot guild member in this guild if cached */
|
||||||
botMember?: GuildMember;
|
botMember?: Omit<GuildMember, "joinedAt" | "premiumSince"> & {
|
||||||
|
joinedAt: number;
|
||||||
|
premiumSince?: number;
|
||||||
|
};
|
||||||
/** The bots voice state if there is one in this guild */
|
/** The bots voice state if there is one in this guild */
|
||||||
botVoice?: CleanVoiceState;
|
botVoice?: VoiceState;
|
||||||
/** The owner member of this guild */
|
/** The owner member of this guild */
|
||||||
owner?: MemberStruct;
|
owner?: MemberStruct;
|
||||||
/** Whether or not this guild is partnered */
|
/** Whether or not this guild is partnered */
|
||||||
|
|||||||
+96
-27
@@ -6,10 +6,21 @@ import { kickMember } from "../helpers/members/kick_member.ts";
|
|||||||
import { sendDirectMessage } from "../helpers/members/send_direct_message.ts";
|
import { sendDirectMessage } from "../helpers/members/send_direct_message.ts";
|
||||||
import { addRole } from "../helpers/roles/add_role.ts";
|
import { addRole } from "../helpers/roles/add_role.ts";
|
||||||
import { removeRole } from "../helpers/roles/remove_role.ts";
|
import { removeRole } from "../helpers/roles/remove_role.ts";
|
||||||
|
import { CreateGuildBan } from "../types/guilds/create_guild_ban.ts";
|
||||||
|
import {
|
||||||
|
DiscordGuildMember,
|
||||||
|
GuildMember,
|
||||||
|
} from "../types/guilds/guild_member.ts";
|
||||||
|
import { ModifyGuildMember } from "../types/guilds/modify_guild_member.ts";
|
||||||
|
import { CreateMessage } from "../types/messages/create_message.ts";
|
||||||
|
import { DiscordImageFormat } from "../types/misc/image_format.ts";
|
||||||
|
import { DiscordImageSize } from "../types/misc/image_size.ts";
|
||||||
|
import { DiscordUser, User } from "../types/users/user.ts";
|
||||||
import { Collection } from "../util/collection.ts";
|
import { Collection } from "../util/collection.ts";
|
||||||
import { createNewProp } from "../util/utils.ts";
|
import { createNewProp, snakeKeysToCamelCase } from "../util/utils.ts";
|
||||||
|
import { GuildStruct } from "./guild.ts";
|
||||||
|
|
||||||
const baseMember: Partial<Member> = {
|
const baseMember: Partial<MemberStruct> = {
|
||||||
get avatarURL() {
|
get avatarURL() {
|
||||||
return avatarURL(this.id!, this.discriminator!, this.avatar!);
|
return avatarURL(this.id!, this.discriminator!, this.avatar!);
|
||||||
},
|
},
|
||||||
@@ -22,7 +33,7 @@ const baseMember: Partial<Member> = {
|
|||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
makeAvatarURL(options) {
|
makeAvatarURL(options) {
|
||||||
return rawAvatarURL(
|
return avatarURL(
|
||||||
this.id!,
|
this.id!,
|
||||||
this.discriminator!,
|
this.discriminator!,
|
||||||
this.avatar!,
|
this.avatar!,
|
||||||
@@ -60,39 +71,33 @@ const baseMember: Partial<Member> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function createMemberStruct(
|
export async function createMemberStruct(
|
||||||
data: MemberCreatePayload,
|
// The `user` param in `DiscordGuildMember` is optional since discord does not send it in `MESSAGE_CREATE` and `MESSAGE_UPDATE` events. But this data in there is required to build this structure so it is required in this case
|
||||||
|
data: Omit<DiscordGuildMember, "user"> & { user: DiscordUser },
|
||||||
guildId: string,
|
guildId: string,
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
joined_at: joinedAt,
|
user,
|
||||||
premium_since: premiumSince,
|
joinedAt,
|
||||||
user: userData,
|
premiumSince,
|
||||||
roles,
|
|
||||||
deaf,
|
|
||||||
mute,
|
|
||||||
nick,
|
|
||||||
...rest
|
...rest
|
||||||
} = data;
|
} = snakeKeysToCamelCase(data) as Omit<GuildMember, "user"> & {
|
||||||
|
user: DiscordUser;
|
||||||
|
};
|
||||||
|
|
||||||
const { mfa_enabled: mfaEnabled, premium_type: premiumType, ...user } =
|
const props: Record<string, ReturnType<typeof createNewProp>> = {};
|
||||||
data.user || {};
|
|
||||||
|
|
||||||
const restProps: Record<string, ReturnType<typeof createNewProp>> = {};
|
|
||||||
|
|
||||||
for (const key of Object.keys(rest)) {
|
for (const key of Object.keys(rest)) {
|
||||||
// @ts-ignore index signature
|
// @ts-ignore index signature
|
||||||
restProps[key] = createNewProp(rest[key]);
|
props[key] = createNewProp(rest[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const key of Object.keys(user)) {
|
for (const key of Object.keys(user)) {
|
||||||
// @ts-ignore index signature
|
// @ts-ignore index signature
|
||||||
restProps[key] = createNewProp(user[key]);
|
props[key] = createNewProp(user[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const member = Object.create(baseMember, {
|
const member: MemberStruct = Object.create(baseMember, {
|
||||||
...restProps,
|
...props,
|
||||||
mfaEnabled: createNewProp(mfaEnabled),
|
|
||||||
premiumType: createNewProp(premiumType),
|
|
||||||
/** The guild related data mapped by guild id */
|
/** The guild related data mapped by guild id */
|
||||||
guilds: createNewProp(new Collection<string, GuildMember>()),
|
guilds: createNewProp(new Collection<string, GuildMember>()),
|
||||||
});
|
});
|
||||||
@@ -106,13 +111,77 @@ export async function createMemberStruct(
|
|||||||
|
|
||||||
// User was never cached before
|
// User was never cached before
|
||||||
member.guilds.set(guildId, {
|
member.guilds.set(guildId, {
|
||||||
nick: nick,
|
nick: rest.nick,
|
||||||
roles: roles,
|
roles: rest.roles,
|
||||||
joinedAt: Date.parse(joinedAt),
|
joinedAt: Date.parse(joinedAt),
|
||||||
premiumSince: premiumSince ? Date.parse(premiumSince) : undefined,
|
premiumSince: premiumSince ? Date.parse(premiumSince) : undefined,
|
||||||
deaf: deaf,
|
deaf: rest.deaf,
|
||||||
mute: mute,
|
mute: rest.mute,
|
||||||
});
|
});
|
||||||
|
|
||||||
return member as Member;
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MemberStruct extends GuildMember, User {
|
||||||
|
/** The guild related data mapped by guild id */
|
||||||
|
guilds: Collection<
|
||||||
|
string,
|
||||||
|
Omit<GuildMember, "joinedAt" | "premiumSince"> & {
|
||||||
|
joinedAt: number;
|
||||||
|
premiumSince?: number;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
// GETTERS
|
||||||
|
/** The avatar url using the default format and size. */
|
||||||
|
avatarURL: string;
|
||||||
|
/** The mention string for this member */
|
||||||
|
mention: string;
|
||||||
|
/** The username#discriminator tag for this member */
|
||||||
|
tag: string;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
|
||||||
|
/** Returns the avatar url for this member and can be dynamically modified with a size or format */
|
||||||
|
makeAvatarURL(
|
||||||
|
options: { size?: DiscordImageSize; format?: DiscordImageFormat },
|
||||||
|
): string;
|
||||||
|
/** Returns the guild for this guildID */
|
||||||
|
guild(guildID: string): GuildStruct | undefined;
|
||||||
|
/** Get the nickname or the username if no nickname */
|
||||||
|
name(guildID: string): string;
|
||||||
|
/** Get the guild member object for the specified guild */
|
||||||
|
guildMember(
|
||||||
|
guildID: string,
|
||||||
|
):
|
||||||
|
| Omit<GuildMember, "joinedAt" | "premiumSince"> & {
|
||||||
|
joinedAt: number;
|
||||||
|
premiumSince?: number;
|
||||||
|
}
|
||||||
|
| undefined;
|
||||||
|
/** Send a direct message to the user is possible */
|
||||||
|
sendDM(
|
||||||
|
content: string | CreateMessage,
|
||||||
|
): ReturnType<typeof sendDirectMessage>;
|
||||||
|
/** Kick the member from a guild */
|
||||||
|
kick(guildID: string, reason?: string): ReturnType<typeof kickMember>;
|
||||||
|
/** Edit the member in a guild */
|
||||||
|
edit(
|
||||||
|
guildID: string,
|
||||||
|
options: ModifyGuildMember,
|
||||||
|
): ReturnType<typeof editMember>;
|
||||||
|
/** Ban a member in a guild */
|
||||||
|
ban(guildID: string, options: CreateGuildBan): ReturnType<typeof banMember>;
|
||||||
|
/** Add a role to the member */
|
||||||
|
addRole(
|
||||||
|
guildID: string,
|
||||||
|
roleID: string,
|
||||||
|
reason?: string,
|
||||||
|
): ReturnType<typeof addRole>;
|
||||||
|
/** Remove a role from the member */
|
||||||
|
removeRole(
|
||||||
|
guildID: string,
|
||||||
|
roleID: string,
|
||||||
|
reason?: string,
|
||||||
|
): ReturnType<typeof removeRole>;
|
||||||
}
|
}
|
||||||
|
|||||||
+110
-33
@@ -9,10 +9,18 @@ import { removeAllReactions } from "../helpers/messages/remove_all_reactions.ts"
|
|||||||
import { removeReaction } from "../helpers/messages/remove_reaction.ts";
|
import { removeReaction } from "../helpers/messages/remove_reaction.ts";
|
||||||
import { removeReactionEmoji } from "../helpers/messages/remove_reaction_emoji.ts";
|
import { removeReactionEmoji } from "../helpers/messages/remove_reaction_emoji.ts";
|
||||||
import { sendMessage } from "../helpers/messages/send_message.ts";
|
import { sendMessage } from "../helpers/messages/send_message.ts";
|
||||||
|
import { DiscordenoCreateMessage } from "../types/discordeno/create_message.ts";
|
||||||
|
import { GuildMember } from "../types/guilds/guild_member.ts";
|
||||||
|
import { EditMessage } from "../types/messages/edit_message.ts";
|
||||||
|
import { DiscordMessage, Message } from "../types/messages/message.ts";
|
||||||
import { CHANNEL_MENTION_REGEX } from "../util/constants.ts";
|
import { CHANNEL_MENTION_REGEX } from "../util/constants.ts";
|
||||||
import { createNewProp } from "../util/utils.ts";
|
import { createNewProp, snakeKeysToCamelCase } from "../util/utils.ts";
|
||||||
|
import { ChannelStruct } from "./channel.ts";
|
||||||
|
import { GuildStruct } from "./guild.ts";
|
||||||
|
import { MemberStruct } from "./member.ts";
|
||||||
|
import { RoleStruct } from "./role.ts";
|
||||||
|
|
||||||
const baseMessage: Partial<Message> = {
|
const baseMessage: Partial<MessageStruct> = {
|
||||||
get channel() {
|
get channel() {
|
||||||
if (this.guildId) return cache.channels.get(this.channelId!);
|
if (this.guildId) return cache.channels.get(this.channelId!);
|
||||||
return cache.channels.get(this.author?.id!);
|
return cache.channels.get(this.author?.id!);
|
||||||
@@ -34,13 +42,13 @@ const baseMessage: Partial<Message> = {
|
|||||||
"@me"}/${this.channelId}/${this.id}`;
|
"@me"}/${this.channelId}/${this.id}`;
|
||||||
},
|
},
|
||||||
get mentionedRoles() {
|
get mentionedRoles() {
|
||||||
return this.mentionRoleIds?.map((id) => this.guild?.roles.get(id)) || [];
|
return this.mentionedRoleIds?.map((id) => this.guild?.roles.get(id)) || [];
|
||||||
},
|
},
|
||||||
get mentionedChannels() {
|
get mentionedChannels() {
|
||||||
return this.mentionChannelIds?.map((id) => cache.channels.get(id)) || [];
|
return this.mentionedChannelIds?.map((id) => cache.channels.get(id)) || [];
|
||||||
},
|
},
|
||||||
get mentionedMembers() {
|
get mentionedMembers() {
|
||||||
return this.mentions?.map((id) => cache.members.get(id)) || [];
|
return this.mentionedUserIds?.map((id) => cache.members.get(id)) || [];
|
||||||
},
|
},
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -69,9 +77,10 @@ const baseMessage: Partial<Message> = {
|
|||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
...content,
|
...content,
|
||||||
mentions: { ...(content.mentions || {}), repliedUser: true },
|
mentions: { ...(content.allowedMentions || {}), repliedUser: true },
|
||||||
replyMessageId: this.id,
|
replyMessageId: this.id,
|
||||||
failReplyIfNotExists: content.failReplyIfNotExists === true,
|
failReplyIfNotExists:
|
||||||
|
content.messageReference?.failIfNotExists === true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.guildId) return sendMessage(this.channelId!, contentWithMention);
|
if (this.guildId) return sendMessage(this.channelId!, contentWithMention);
|
||||||
@@ -108,58 +117,126 @@ const baseMessage: Partial<Message> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function createMessageStruct(data: MessageCreateOptions) {
|
export async function createMessageStruct(data: DiscordMessage) {
|
||||||
const {
|
const {
|
||||||
guild_id: guildId = "",
|
guildId = "",
|
||||||
channel_id: channelId,
|
channelId,
|
||||||
mentions_everyone: mentionsEveryone,
|
mentionChannels = [],
|
||||||
mention_channels: mentionChannelIds = [],
|
mentions,
|
||||||
mention_roles: mentionRoleIds,
|
mentionRoles,
|
||||||
webhook_id: webhookId,
|
|
||||||
message_reference: messageReference,
|
|
||||||
edited_timestamp: editedTimestamp,
|
edited_timestamp: editedTimestamp,
|
||||||
referenced_message: referencedMessageId,
|
|
||||||
member,
|
|
||||||
...rest
|
...rest
|
||||||
} = data;
|
} = snakeKeysToCamelCase(data) as Message;
|
||||||
|
|
||||||
const restProps: Record<string, ReturnType<typeof createNewProp>> = {};
|
const props: Record<string, ReturnType<typeof createNewProp>> = {};
|
||||||
for (const key of Object.keys(rest)) {
|
for (const key of Object.keys(rest)) {
|
||||||
// @ts-ignore index signature
|
// @ts-ignore index signature
|
||||||
restProps[key] = createNewProp(rest[key]);
|
props[key] = createNewProp(rest[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discord doesnt give guild id for getMessage() so this will fill it in
|
// Discord doesnt give guild id for getMessage() so this will fill it in
|
||||||
const guildIdFinal = guildId ||
|
const guildIdFinal = guildId ||
|
||||||
(await cacheHandlers.get("channels", channelId))?.guildId || "";
|
(await cacheHandlers.get("channels", channelId))?.guildId || "";
|
||||||
|
|
||||||
const message = Object.create(baseMessage, {
|
const message: MessageStruct = Object.create(baseMessage, {
|
||||||
...restProps,
|
...props,
|
||||||
/** The message id of the original message if this message was sent as a reply. If null, the original message was deleted. */
|
/** The message id of the original message if this message was sent as a reply. If null, the original message was deleted. */
|
||||||
referencedMessageId: createNewProp(referencedMessageId),
|
|
||||||
channelId: createNewProp(channelId),
|
channelId: createNewProp(channelId),
|
||||||
guildId: createNewProp(guildId || guildIdFinal),
|
guildId: createNewProp(guildIdFinal),
|
||||||
mentions: createNewProp(data.mentions.map((m) => m.id)),
|
mentionedUserIds: createNewProp(mentions.map((m) => m.id)),
|
||||||
mentionsEveryone: createNewProp(mentionsEveryone),
|
mentionedRoleIds: createNewProp(mentionRoles),
|
||||||
mentionRoleIds: createNewProp(mentionRoleIds),
|
mentionedChannelIds: createNewProp(
|
||||||
mentionChannelIds: createNewProp(
|
|
||||||
[
|
[
|
||||||
// Keep any ids that discord sends
|
// Keep any ids that discord sends
|
||||||
...mentionChannelIds,
|
...mentionChannels.map((m) => m.id),
|
||||||
// Add any other ids that can be validated in a channel mention format
|
// Add any other ids that can be validated in a channel mention format
|
||||||
...(rest.content.match(CHANNEL_MENTION_REGEX) || []).map((text) =>
|
...(rest.content.match(CHANNEL_MENTION_REGEX) || []).map((text) =>
|
||||||
// converts the <#123> into 123
|
// converts the <#123> into 123
|
||||||
text.substring(2, text.length - 1)
|
text.substring(2, text.length - 1)
|
||||||
),
|
),
|
||||||
].map((m) => m.id),
|
],
|
||||||
),
|
),
|
||||||
webhookId: createNewProp(webhookId),
|
|
||||||
messageReference: createNewProp(messageReference),
|
|
||||||
timestamp: createNewProp(Date.parse(data.timestamp)),
|
timestamp: createNewProp(Date.parse(data.timestamp)),
|
||||||
editedTimestamp: createNewProp(
|
editedTimestamp: createNewProp(
|
||||||
editedTimestamp ? Date.parse(editedTimestamp) : undefined,
|
editedTimestamp ? Date.parse(editedTimestamp) : undefined,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
return message as Message;
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageStruct extends Message {
|
||||||
|
// For better user experience
|
||||||
|
/** Ids of users specifically mentioned in the message */
|
||||||
|
mentionedUserIds: string[];
|
||||||
|
/** Ids of roles specifically mentioned in this message */
|
||||||
|
mentionedRoleIds: string[];
|
||||||
|
/** Channels specifically mentioned in this message */
|
||||||
|
mentionedChannelIds?: string[];
|
||||||
|
// GETTERS
|
||||||
|
|
||||||
|
/** The channel where this message was sent. Can be undefined if uncached. */
|
||||||
|
channel?: ChannelStruct;
|
||||||
|
/** The guild of this message. Can be undefined if not in cache or in DM */
|
||||||
|
guild?: GuildStruct;
|
||||||
|
/** The member for the user who sent the message. Can be undefined if not in cache or in dm. */
|
||||||
|
member?: MemberStruct;
|
||||||
|
/** The guild member details for this guild and member. Can be undefined if not in cache or in dm. */
|
||||||
|
guildMember?: Omit<GuildMember, "joinedAt" | "premiumSince"> & {
|
||||||
|
joinedAt: number;
|
||||||
|
premiumSince?: number;
|
||||||
|
};
|
||||||
|
/** The url link to this message */
|
||||||
|
link: string;
|
||||||
|
/** The role objects for all the roles that were mentioned in this message */
|
||||||
|
mentionedRoles: (RoleStruct | undefined)[];
|
||||||
|
/** The channel objects for all the channels that were mentioned in this message. */
|
||||||
|
mentionedChannels: (ChannelStruct | undefined)[];
|
||||||
|
/** The member objects for all the members that were mentioned in this message. */
|
||||||
|
mentionedMembers: (MemberStruct | undefined)[];
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
|
||||||
|
/** Delete the message */
|
||||||
|
delete(
|
||||||
|
reason?: string,
|
||||||
|
delayMilliseconds?: number,
|
||||||
|
): ReturnType<typeof deleteMessage>;
|
||||||
|
/** Edit the message */
|
||||||
|
edit(content: string | EditMessage): ReturnType<typeof editMessage>;
|
||||||
|
/** Pins the message in the channel */
|
||||||
|
pin(): ReturnType<typeof pinMessage>;
|
||||||
|
/** Add a reaction to the message */
|
||||||
|
addReaction(reaction: string): ReturnType<typeof addReaction>;
|
||||||
|
/** Add multiple reactions to the message without or without order. */
|
||||||
|
addReactions(
|
||||||
|
reactions: string[],
|
||||||
|
ordered?: boolean,
|
||||||
|
): ReturnType<typeof addReactions>;
|
||||||
|
/** Send a inline reply to this message */
|
||||||
|
reply(
|
||||||
|
content: string | DiscordenoCreateMessage,
|
||||||
|
): ReturnType<typeof sendMessage>;
|
||||||
|
/** Send a message to this channel where this message is */
|
||||||
|
send(
|
||||||
|
content: string | DiscordenoCreateMessage,
|
||||||
|
): ReturnType<typeof sendMessage>;
|
||||||
|
/** Send a message to this channel and then delete it after a bit. By default it will delete after 10 seconds with no reason provided. */
|
||||||
|
alert(
|
||||||
|
content: string | DiscordenoCreateMessage,
|
||||||
|
timeout?: number,
|
||||||
|
reason?: string,
|
||||||
|
): Promise<void>;
|
||||||
|
/** Send a inline reply to this message but then delete it after a bit. By default it will delete after 10 seconds with no reason provided. */
|
||||||
|
alertReply(
|
||||||
|
content: string | DiscordenoCreateMessage,
|
||||||
|
timeout?: number,
|
||||||
|
reason?: string,
|
||||||
|
): Promise<unknown>;
|
||||||
|
/** Remove all reactions */
|
||||||
|
removeAllReactions(): ReturnType<typeof removeAllReactions>;
|
||||||
|
/** Remove all reactions */
|
||||||
|
removeReactionEmoji(reaction: string): ReturnType<typeof removeReactionEmoji>;
|
||||||
|
/** Remove all reactions */
|
||||||
|
removeReaction(reaction: string): ReturnType<typeof removeReaction>;
|
||||||
}
|
}
|
||||||
|
|||||||
+75
-35
@@ -1,11 +1,17 @@
|
|||||||
import { cache } from "../cache.ts";
|
import { cache } from "../cache.ts";
|
||||||
import { deleteRole } from "../helpers/roles/delete_role.ts";
|
import { deleteRole } from "../helpers/roles/delete_role.ts";
|
||||||
import { editRole } from "../helpers/roles/edit_role.ts";
|
import { editRole } from "../helpers/roles/edit_role.ts";
|
||||||
import { createNewProp } from "../util/utils.ts";
|
import { CreateGuildRole } from "../types/guilds/create_guild_role.ts";
|
||||||
|
import { DiscordGuildRoleCreate } from "../types/guilds/guild_role_create.ts";
|
||||||
|
import { Errors } from "../types/misc/errors.ts";
|
||||||
|
import { Role } from "../types/permissions/role.ts";
|
||||||
|
import { Collection } from "../util/collection.ts";
|
||||||
|
import { highestRole } from "../util/permissions.ts";
|
||||||
|
import { createNewProp, snakeKeysToCamelCase } from "../util/utils.ts";
|
||||||
|
|
||||||
const baseRole: Partial<Role> = {
|
const baseRole: Partial<RoleStruct> = {
|
||||||
get guild() {
|
get guild() {
|
||||||
return cache.guilds.find((g) => g.roles.has(this.id!));
|
return cache.guilds.get(this.guildId!);
|
||||||
},
|
},
|
||||||
get hexColor() {
|
get hexColor() {
|
||||||
return this.color!.toString(16);
|
return this.color!.toString(16);
|
||||||
@@ -20,31 +26,13 @@ const baseRole: Partial<Role> = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
delete(guildId?: string) {
|
delete() {
|
||||||
// If not guild id was provided try and find one
|
return deleteRole(this.guildId!, this.id!).catch(console.error);
|
||||||
if (!guildId) guildId = guildId || this.guild?.id;
|
|
||||||
// If a guild id is still not available error out
|
|
||||||
if (!guildId) {
|
|
||||||
throw new Error(
|
|
||||||
"role.delete() did not find a valid guild in cache. Please provide the guildId like role.delete(guildId)",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return deleteRole(guildId, this.id!).catch(console.error);
|
|
||||||
},
|
},
|
||||||
edit(options: CreateRoleOptions, guildId?: string) {
|
edit(options) {
|
||||||
// If not guild id was provided try and find one
|
return editRole(this.guildId!, this.id!, options);
|
||||||
if (!guildId) guildId = guildId || this.guild?.id;
|
|
||||||
// If a guild id is still not available error out
|
|
||||||
if (!guildId) {
|
|
||||||
throw new Error(
|
|
||||||
"role.edit() did not find a valid guild in cache. Please provide the guildId like role.edit({}, guildId)",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return editRole(guildId, this.id!, options);
|
|
||||||
},
|
},
|
||||||
higherThanRoleId(roleId: string, position?: number) {
|
higherThanRole(roleId: string, position?: number) {
|
||||||
// If no position try and find one from cache
|
// If no position try and find one from cache
|
||||||
if (!position) position = this.guild?.roles.get(roleId)?.position;
|
if (!position) position = this.guild?.roles.get(roleId)?.position;
|
||||||
// If still none error out.
|
// If still none error out.
|
||||||
@@ -61,22 +49,74 @@ const baseRole: Partial<Role> = {
|
|||||||
|
|
||||||
return this.position! > position;
|
return this.position! > position;
|
||||||
},
|
},
|
||||||
|
async higherThanMember(memberId: string) {
|
||||||
|
const guild = this.guild;
|
||||||
|
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
|
||||||
|
|
||||||
|
if (this.guild.ownerId === memberId) return false;
|
||||||
|
|
||||||
|
const memberHighestRole = await highestRole(guild, memberId);
|
||||||
|
return this.higherThanRole!(
|
||||||
|
memberHighestRole.id,
|
||||||
|
memberHighestRole.position,
|
||||||
|
);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// deno-lint-ignore require-await
|
// deno-lint-ignore require-await
|
||||||
export async function createRoleStruct({ tags = {}, ...rest }: RoleData) {
|
export async function createRoleStruct(data: DiscordGuildRoleCreate) {
|
||||||
const restProps: Record<string, ReturnType<typeof createNewProp>> = {};
|
const {
|
||||||
|
tags = {},
|
||||||
|
...rest
|
||||||
|
} = snakeKeysToCamelCase({ guildId: data.guild_id, ...data.role }) as Role & {
|
||||||
|
guildId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const props: Record<string, ReturnType<typeof createNewProp>> = {};
|
||||||
for (const key of Object.keys(rest)) {
|
for (const key of Object.keys(rest)) {
|
||||||
// @ts-ignore index signature
|
// @ts-ignore index signature
|
||||||
restProps[key] = createNewProp(rest[key]);
|
props[key] = createNewProp(rest[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = Object.create(baseRole, {
|
const role: RoleStruct = Object.create(baseRole, {
|
||||||
...restProps,
|
...props,
|
||||||
botId: createNewProp(tags.bot_id),
|
botId: createNewProp(tags.botId),
|
||||||
isNitroBoostRole: createNewProp("premium_subscriber" in tags),
|
isNitroBoostRole: createNewProp("premiumSubscriber" in tags),
|
||||||
integrationId: createNewProp(tags.integration_id),
|
integrationId: createNewProp(tags.integrationId),
|
||||||
});
|
});
|
||||||
|
|
||||||
return role as Role;
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoleStruct extends Omit<Role, "tags"> {
|
||||||
|
/** The bot id that is associated with this role. */
|
||||||
|
botId?: string;
|
||||||
|
/** If this role is the nitro boost role. */
|
||||||
|
isNitroBoostRole: boolean;
|
||||||
|
/** The integration id that is associated with this role */
|
||||||
|
integrationId: string;
|
||||||
|
/** The roles guildId */
|
||||||
|
guildId: string;
|
||||||
|
|
||||||
|
// GETTERS
|
||||||
|
|
||||||
|
/** The guild where this role is. If undefined, the guild is not cached */
|
||||||
|
guild?: GuildStruct;
|
||||||
|
/** The hex color for this role. */
|
||||||
|
hexColor: string;
|
||||||
|
/** The cached members that have this role */
|
||||||
|
members: Collection<string, MemberStruct>;
|
||||||
|
/** The @ mention of the role in a string. */
|
||||||
|
mention: string;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
|
||||||
|
/** Delete the role */
|
||||||
|
delete(): ReturnType<typeof deleteRole>;
|
||||||
|
/** Edits the role */
|
||||||
|
edit(options: CreateGuildRole): ReturnType<typeof editRole>;
|
||||||
|
/** Checks if this role is higher than another role. */
|
||||||
|
higherThanRole(roleId: string, position?: number): boolean;
|
||||||
|
/** Checks if the role has a higher position than the given member */
|
||||||
|
higherThanMember(memberId: string): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { CreateGlobalApplicationCommand } from "../interactions/create_global_application_command.ts";
|
||||||
|
|
||||||
|
export interface DiscordenoCreateApplicationCommand
|
||||||
|
extends CreateGlobalApplicationCommand {
|
||||||
|
/** Id of the guild to create a guild only application command */
|
||||||
|
guildId: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { EditWebhookMessage } from "../webhooks/edit_webhook_message.ts";
|
||||||
|
|
||||||
|
export interface DiscordenoEditWebhookMessage extends EditWebhookMessage {
|
||||||
|
/** Id of the message you want to edit */
|
||||||
|
messageId: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { Guild } from "../guilds/guild.ts";
|
||||||
|
|
||||||
|
export interface GuildUpdateChange {
|
||||||
|
key: keyof Guild;
|
||||||
|
oldValue?: unknown;
|
||||||
|
value?: unknown;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { InteractionResponse } from "../interactions/interaction_response.ts";
|
||||||
|
|
||||||
|
export interface DiscordenoInteractionResponse extends InteractionResponse {
|
||||||
|
/** Set to true if the response should be private */
|
||||||
|
private?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { SnakeCaseProps } from "../util.ts";
|
||||||
|
import { Integration } from "./integration.ts";
|
||||||
|
|
||||||
|
export interface IntegrationCreateUpdate extends Integration {
|
||||||
|
/** Id of the guild */
|
||||||
|
guildId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** https://github.com/discord/discord-api-docs/blob/master/docs/topics/Gateway.md#integration-create-event-additional-fields */
|
||||||
|
export type DiscordIntegrationCreateUpdate = SnakeCaseProps<
|
||||||
|
IntegrationCreateUpdate
|
||||||
|
>;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { SnakeCaseProps } from "../util.ts";
|
||||||
|
|
||||||
|
export interface IntegrationDelete {
|
||||||
|
/** Integration id */
|
||||||
|
id: string;
|
||||||
|
/** Id of the guild */
|
||||||
|
guildId: string;
|
||||||
|
/** Id of the bot/OAuth2 application for this discord integration */
|
||||||
|
applicationId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** https://github.com/discord/discord-api-docs/blob/master/docs/topics/Gateway.md#integration-delete-event-fields */
|
||||||
|
export type DiscordIntegrationDelete = SnakeCaseProps<IntegrationDelete>;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { GuildMember } from "../guilds/guild_member.ts";
|
||||||
import { User } from "../users/user.ts";
|
import { User } from "../users/user.ts";
|
||||||
import { SnakeCaseProps } from "../util.ts";
|
import { SnakeCaseProps } from "../util.ts";
|
||||||
import { InteractionApplicationCommandCallbackData } from "./application_command_callback_data.ts";
|
import { InteractionApplicationCommandCallbackData } from "./application_command_callback_data.ts";
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { SnakeCaseProps } from "../util.ts";
|
import { SnakeCaseProps } from "../util.ts";
|
||||||
|
import { Invite } from "./invite.ts";
|
||||||
|
|
||||||
export interface InviteMetadata {
|
export interface InviteMetadata extends Invite {
|
||||||
/** Number of times this invite has been used */
|
/** Number of times this invite has been used */
|
||||||
uses: number;
|
uses: number;
|
||||||
/** Max number of times this invite can be used */
|
/** Max number of times this invite can be used */
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ export interface AllowedMentions {
|
|||||||
/** An array of allowed mention types to parse from the content. */
|
/** An array of allowed mention types to parse from the content. */
|
||||||
parse: DiscordAllowedMentionsTypes[];
|
parse: DiscordAllowedMentionsTypes[];
|
||||||
/** Array of role_ids to mention (Max size of 100) */
|
/** Array of role_ids to mention (Max size of 100) */
|
||||||
roles: string[];
|
roles?: string[];
|
||||||
/** Array of user_ids to mention (Max size of 100) */
|
/** Array of user_ids to mention (Max size of 100) */
|
||||||
users: string[];
|
users?: string[];
|
||||||
/** For replies, whether to mention the author of the message being replied to (default false) */
|
/** For replies, whether to mention the author of the message being replied to (default false) */
|
||||||
repliedUser: boolean;
|
repliedUser?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** https://discord.com/developers/docs/resources/channel#allowed-mentions-object */
|
/** https://discord.com/developers/docs/resources/channel#allowed-mentions-object */
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Embed } from "../embeds/embed.ts";
|
import { Embed } from "../embeds/embed.ts";
|
||||||
import { AllowedMentions } from "../messages/allowed_mentions.ts";
|
import { AllowedMentions } from "../messages/allowed_mentions.ts";
|
||||||
import { MessageReference } from "../messages/message_reference.ts";
|
import { MessageReference } from "../messages/message_reference.ts";
|
||||||
|
import { FileContent } from "../misc/file_content.ts";
|
||||||
import { SnakeCaseProps } from "../util.ts";
|
import { SnakeCaseProps } from "../util.ts";
|
||||||
|
|
||||||
export interface CreateMessage {
|
export interface CreateMessage {
|
||||||
@@ -16,7 +17,9 @@ export interface CreateMessage {
|
|||||||
allowedMentions?: AllowedMentions;
|
allowedMentions?: AllowedMentions;
|
||||||
/** Include to make your message a reply */
|
/** Include to make your message a reply */
|
||||||
messageReference?: MessageReference;
|
messageReference?: MessageReference;
|
||||||
|
/** The contents of the file being sent */
|
||||||
|
file?: FileContent | FileContent[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** https://discord.com/developers/docs/resources/channel#create-message */
|
/** https://discord.com/developers/docs/resources/channel#create-message */
|
||||||
export type DiscordCreateMessage = SnakeCaseProps<CreateMessage>;
|
export type DiscordCreateMessage = SnakeCaseProps<Omit<CreateMessage, "file">>;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Embed } from "../embeds/embed.ts";
|
||||||
|
import { SnakeCaseProps } from "../util.ts";
|
||||||
|
import { AllowedMentions } from "./allowed_mentions.ts";
|
||||||
|
|
||||||
|
export interface EditMessage {
|
||||||
|
/** The new message contents (up to 2000 characters) */
|
||||||
|
content?: string | null;
|
||||||
|
/** Embedded `rich` content */
|
||||||
|
embed?: Embed | null;
|
||||||
|
/** Edit the flags of the message (only `SUPRESS_EMBEDS` can currently be set/unset) */
|
||||||
|
flags?: 4 | null;
|
||||||
|
/** Allowed mentions for the message */
|
||||||
|
allowedMentions?: AllowedMentions | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** https://discord.com/developers/docs/resources/channel#edit-message-json-params */
|
||||||
|
export type DiscordEditMessage = SnakeCaseProps<EditMessage>;
|
||||||
+18
-7
@@ -5,15 +5,18 @@ import { Errors } from "../types/misc/errors.ts";
|
|||||||
import { DiscordBitwisePermissionFlags } from "../types/permissions/bitwise_permission_flags.ts";
|
import { DiscordBitwisePermissionFlags } from "../types/permissions/bitwise_permission_flags.ts";
|
||||||
import { PermissionStrings } from "../types/permissions/permission_strings.ts";
|
import { PermissionStrings } from "../types/permissions/permission_strings.ts";
|
||||||
|
|
||||||
async function getCached(table: "guilds", key: string | Guild): Promise<Guild>;
|
async function getCached(
|
||||||
|
table: "guilds",
|
||||||
|
key: string | Guild,
|
||||||
|
): Promise<Guild | undefined>;
|
||||||
async function getCached(
|
async function getCached(
|
||||||
table: "channels",
|
table: "channels",
|
||||||
key: string | Channel,
|
key: string | Channel,
|
||||||
): Promise<Channel>;
|
): Promise<Channel | undefined>;
|
||||||
async function getCached(
|
async function getCached(
|
||||||
table: "members",
|
table: "members",
|
||||||
key: string | Member,
|
key: string | Member,
|
||||||
): Promise<Member>;
|
): Promise<Member | undefined>;
|
||||||
async function getCached(
|
async function getCached(
|
||||||
table: "guilds" | "channels" | "members",
|
table: "guilds" | "channels" | "members",
|
||||||
key: string | Guild | Channel | Member,
|
key: string | Guild | Channel | Member,
|
||||||
@@ -28,7 +31,7 @@ async function getCached(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cached;
|
return typeof cached === "string" ? undefined : cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calculates the permissions this member has in the given guild */
|
/** Calculates the permissions this member has in the given guild */
|
||||||
@@ -39,6 +42,8 @@ export async function calculateBasePermissions(
|
|||||||
guild = await getCached("guilds", guild);
|
guild = await getCached("guilds", guild);
|
||||||
member = await getCached("members", member);
|
member = await getCached("members", member);
|
||||||
|
|
||||||
|
if (!guild || !member) return "8";
|
||||||
|
|
||||||
let permissions = 0n;
|
let permissions = 0n;
|
||||||
// Calculate the role permissions bits, @everyone role is not in memberRoleIds so we need to pass guildId manualy
|
// Calculate the role permissions bits, @everyone role is not in memberRoleIds so we need to pass guildId manualy
|
||||||
permissions |= [...(member.guilds.get(guild.id)?.roles || []), guild.id]
|
permissions |= [...(member.guilds.get(guild.id)?.roles || []), guild.id]
|
||||||
@@ -64,10 +69,12 @@ export async function calculateChannelOverwrites(
|
|||||||
channel = await getCached("channels", channel);
|
channel = await getCached("channels", channel);
|
||||||
|
|
||||||
// This is a DM channel so return ADMINISTRATOR permission
|
// This is a DM channel so return ADMINISTRATOR permission
|
||||||
if (!channel.guildId) return "8";
|
if (!channel?.guildId) return "8";
|
||||||
|
|
||||||
member = await getCached("members", member);
|
member = await getCached("members", member);
|
||||||
|
|
||||||
|
if (!member) return "8";
|
||||||
|
|
||||||
// Get all the role permissions this member already has
|
// Get all the role permissions this member already has
|
||||||
let permissions = BigInt(
|
let permissions = BigInt(
|
||||||
await calculateBasePermissions(channel.guildId, member),
|
await calculateBasePermissions(channel.guildId, member),
|
||||||
@@ -285,8 +292,10 @@ export async function highestRole(
|
|||||||
) {
|
) {
|
||||||
guild = await getCached("guilds", guild);
|
guild = await getCached("guilds", guild);
|
||||||
|
|
||||||
|
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
|
||||||
|
|
||||||
// Get the roles from the member
|
// Get the roles from the member
|
||||||
const memberRoles = (await getCached("members", member)).guilds.get(guild.id)
|
const memberRoles = (await getCached("members", member))?.guilds.get(guild.id)
|
||||||
?.roles;
|
?.roles;
|
||||||
// This member has no roles so the highest one is the @everyone role
|
// This member has no roles so the highest one is the @everyone role
|
||||||
if (!memberRoles) return guild.roles.get(guild.id) as Role;
|
if (!memberRoles) return guild.roles.get(guild.id) as Role;
|
||||||
@@ -321,6 +330,8 @@ export async function higherRolePosition(
|
|||||||
) {
|
) {
|
||||||
guild = await getCached("guilds", guild);
|
guild = await getCached("guilds", guild);
|
||||||
|
|
||||||
|
if (!guild) return true;
|
||||||
|
|
||||||
const role = guild.roles.get(roleId);
|
const role = guild.roles.get(roleId);
|
||||||
const otherRole = guild.roles.get(otherRoleId);
|
const otherRole = guild.roles.get(otherRoleId);
|
||||||
if (!role || !otherRole) throw new Error(Errors.ROLE_NOT_FOUND);
|
if (!role || !otherRole) throw new Error(Errors.ROLE_NOT_FOUND);
|
||||||
@@ -341,7 +352,7 @@ export async function isHigherPosition(
|
|||||||
) {
|
) {
|
||||||
guild = await getCached("guilds", guild);
|
guild = await getCached("guilds", guild);
|
||||||
|
|
||||||
if (guild.ownerId === memberId) return true;
|
if (!guild || guild.ownerId === memberId) return true;
|
||||||
|
|
||||||
const memberHighestRole = await highestRole(guild, memberId);
|
const memberHighestRole = await highestRole(guild, memberId);
|
||||||
return higherRolePosition(guild.id, memberHighestRole.id, compareRoleId);
|
return higherRolePosition(guild.id, memberHighestRole.id, compareRoleId);
|
||||||
|
|||||||
+14
-9
@@ -3,6 +3,7 @@ import { DiscordGatewayOpcodes } from "../types/codes/gateway_opcodes.ts";
|
|||||||
import { Errors } from "../types/misc/errors.ts";
|
import { Errors } from "../types/misc/errors.ts";
|
||||||
import { DiscordImageFormat } from "../types/misc/image_format.ts";
|
import { DiscordImageFormat } from "../types/misc/image_format.ts";
|
||||||
import { DiscordImageSize } from "../types/misc/image_size.ts";
|
import { DiscordImageSize } from "../types/misc/image_size.ts";
|
||||||
|
import { ws } from "../ws/ws.ts";
|
||||||
import { SLASH_COMMANDS_NAME_REGEX } from "./constants.ts";
|
import { SLASH_COMMANDS_NAME_REGEX } from "./constants.ts";
|
||||||
|
|
||||||
export const sleep = (timeout: number) => {
|
export const sleep = (timeout: number) => {
|
||||||
@@ -12,7 +13,7 @@ export const sleep = (timeout: number) => {
|
|||||||
export function editBotStatus(
|
export function editBotStatus(
|
||||||
data: Pick<GatewayStatusUpdatePayload, "activities" | "status">,
|
data: Pick<GatewayStatusUpdatePayload, "activities" | "status">,
|
||||||
) {
|
) {
|
||||||
basicShards.forEach((shard) => {
|
ws.shards.forEach((shard) => {
|
||||||
sendWS({
|
sendWS({
|
||||||
op: DiscordGatewayOpcodes.StatusUpdate,
|
op: DiscordGatewayOpcodes.StatusUpdate,
|
||||||
d: {
|
d: {
|
||||||
@@ -71,7 +72,9 @@ function isObject(obj: unknown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
export function camelKeysToSnakeCase(obj: Record<string, any>) {
|
export function camelKeysToSnakeCase<T>(
|
||||||
|
obj: Record<string, any> | Record<string, any>[],
|
||||||
|
): T {
|
||||||
if (isObject(obj)) {
|
if (isObject(obj)) {
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
const convertedObject: Record<string, any> = {};
|
const convertedObject: Record<string, any> = {};
|
||||||
@@ -79,20 +82,22 @@ export function camelKeysToSnakeCase(obj: Record<string, any>) {
|
|||||||
Object.keys(obj)
|
Object.keys(obj)
|
||||||
.forEach((key) => {
|
.forEach((key) => {
|
||||||
convertedObject[camelToSnakeCase(key)] = camelKeysToSnakeCase(
|
convertedObject[camelToSnakeCase(key)] = camelKeysToSnakeCase(
|
||||||
obj[key],
|
(obj as Record<string, any>)[key],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return convertedObject;
|
return convertedObject as T;
|
||||||
} else if (Array.isArray(obj)) {
|
} else if (Array.isArray(obj)) {
|
||||||
obj = obj.map((element) => camelKeysToSnakeCase(element));
|
obj = obj.map((element) => camelKeysToSnakeCase(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
export function snakeKeysToCamelCase(obj: Record<string, any>) {
|
export function snakeKeysToCamelCase<T>(
|
||||||
|
obj: Record<string, any> | Record<string, any>[],
|
||||||
|
): T {
|
||||||
if (isObject(obj)) {
|
if (isObject(obj)) {
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
const convertedObject: Record<string, any> = {};
|
const convertedObject: Record<string, any> = {};
|
||||||
@@ -100,16 +105,16 @@ export function snakeKeysToCamelCase(obj: Record<string, any>) {
|
|||||||
Object.keys(obj)
|
Object.keys(obj)
|
||||||
.forEach((key) => {
|
.forEach((key) => {
|
||||||
convertedObject[snakeToCamelCase(key)] = snakeKeysToCamelCase(
|
convertedObject[snakeToCamelCase(key)] = snakeKeysToCamelCase(
|
||||||
obj[key],
|
(obj as Record<string, any>)[key],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return convertedObject;
|
return convertedObject as T;
|
||||||
} else if (Array.isArray(obj)) {
|
} else if (Array.isArray(obj)) {
|
||||||
obj = obj.map((element) => snakeKeysToCamelCase(element));
|
obj = obj.map((element) => snakeKeysToCamelCase(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
|
|||||||
Reference in New Issue
Block a user