mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 08:47:22 +00:00
feat: base plugin lib idea (#2308)
* feat: base plugin lib idea * fix: stuff * fmt * fix: imports and exports * fix: errors & tests * fix: remove logs
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
export function snowflakeToBigint(snowflake: string) {
|
||||
return BigInt(snowflake) | 0n;
|
||||
}
|
||||
|
||||
export function bigintToSnowflake(snowflake: bigint) {
|
||||
return snowflake === 0n ? "" : snowflake.toString();
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { PickPartial } from "../types/shared.ts";
|
||||
import { delay } from "./utils.ts";
|
||||
import { delay } from "./delay.ts";
|
||||
|
||||
/** A Leaky Bucket.
|
||||
* Useful for rate limiting purposes.
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { GatewayManager } from "../gateway/manager/gatewayManager.ts";
|
||||
|
||||
export function calculateShardId(gateway: GatewayManager, guildId: bigint) {
|
||||
if (gateway.manager.totalShards === 1) return 0;
|
||||
|
||||
return Number((guildId >> 22n) % BigInt(gateway.manager.totalShards - 1));
|
||||
}
|
||||
@@ -1,49 +1,10 @@
|
||||
import { Bot } from "../bot.ts";
|
||||
|
||||
export class Collection<K, V> extends Map<K, V> {
|
||||
maxSize: number | undefined;
|
||||
sweeper: CollectionSweeper<K, V> & { intervalId?: number } | undefined;
|
||||
|
||||
constructor(entries?: (readonly (readonly [K, V])[] | null) | Map<K, V>, options?: CollectionOptions<K, V>) {
|
||||
super(entries ?? []);
|
||||
|
||||
this.maxSize = options?.maxSize;
|
||||
|
||||
if (!options?.sweeper) return;
|
||||
|
||||
this.startSweeper(options.sweeper);
|
||||
}
|
||||
|
||||
startSweeper(options: CollectionSweeper<K, V>): number {
|
||||
if (this.sweeper?.intervalId) clearInterval(this.sweeper.intervalId);
|
||||
|
||||
this.sweeper = options;
|
||||
this.sweeper.intervalId = setInterval(() => {
|
||||
this.forEach((value, key) => {
|
||||
if (!this.sweeper?.filter(value, key, options.bot)) return;
|
||||
|
||||
this.delete(key);
|
||||
return key;
|
||||
});
|
||||
}, options.interval);
|
||||
|
||||
return this.sweeper.intervalId!;
|
||||
}
|
||||
|
||||
stopSweeper(): void {
|
||||
return clearInterval(this.sweeper?.intervalId);
|
||||
}
|
||||
|
||||
changeSweeperInterval(newInterval: number) {
|
||||
if (!this.sweeper) return;
|
||||
|
||||
this.startSweeper({ filter: this.sweeper.filter, interval: newInterval });
|
||||
}
|
||||
|
||||
changeSweeperFilter(newFilter: (value: V, key: K, bot: Bot) => boolean) {
|
||||
if (!this.sweeper) return;
|
||||
|
||||
this.startSweeper({ filter: newFilter, interval: this.sweeper.interval });
|
||||
}
|
||||
|
||||
set(key: K, value: V) {
|
||||
@@ -135,15 +96,5 @@ export class Collection<K, V> extends Map<K, V> {
|
||||
}
|
||||
|
||||
export interface CollectionOptions<K, V> {
|
||||
sweeper?: CollectionSweeper<K, V>;
|
||||
maxSize?: number;
|
||||
}
|
||||
|
||||
export interface CollectionSweeper<K, V> {
|
||||
/** The filter to determine whether an element should be deleted or not */
|
||||
filter: (value: V, key: K, ...args: any[]) => boolean;
|
||||
/** The interval in which the sweeper should run */
|
||||
interval: number;
|
||||
/** The bot object itself */
|
||||
bot?: Bot;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/** Pause the execution for a given amount of milliseconds. */
|
||||
export function delay(ms: number): Promise<void> {
|
||||
return new Promise((res): number =>
|
||||
setTimeout((): void => {
|
||||
res();
|
||||
}, ms)
|
||||
);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
export function iconHashToBigInt(hash: string) {
|
||||
// The icon is animated so it needs special handling
|
||||
if (hash.startsWith("a_")) {
|
||||
// Change the `a_` to just be `a`
|
||||
hash = `a${hash.substring(2)}`;
|
||||
} else {
|
||||
// The icon is not animated but it could be that it starts with a 0 so we just put a `b` in front so nothing breaks
|
||||
hash = `b${hash}`;
|
||||
}
|
||||
|
||||
return BigInt(`0x${hash}`);
|
||||
}
|
||||
|
||||
export function iconBigintToHash(icon: bigint) {
|
||||
// Convert the bigint back to a hash
|
||||
const hash = icon.toString(16);
|
||||
// Hashes starting with a are animated and with b are not so need to handle that
|
||||
return hash.startsWith("a") ? `a_${hash.substring(1)}` : hash.substring(1);
|
||||
}
|
||||
+3
-5
@@ -1,7 +1,5 @@
|
||||
export * from "./bigint.ts";
|
||||
export * from "./calculateShardId.ts";
|
||||
export * from "./bucket.ts";
|
||||
export * from "./collection.ts";
|
||||
export * from "./constants.ts";
|
||||
export * from "./hash.ts";
|
||||
export * from "./utils.ts";
|
||||
export * from "./validateLength.ts";
|
||||
export * from "./delay.ts";
|
||||
export * from "./token.ts";
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { BitwisePermissionFlags, PermissionStrings } from "../types/shared.ts";
|
||||
|
||||
/** This function converts a bitwise string to permission strings */
|
||||
export function calculatePermissions(permissionBits: bigint) {
|
||||
return Object.keys(BitwisePermissionFlags).filter((permission) => {
|
||||
// Since Object.keys() not only returns the permission names but also the bit values we need to return false if it is a Number
|
||||
if (Number(permission)) return false;
|
||||
// Check if permissionBits has this permission
|
||||
return permissionBits & BigInt(BitwisePermissionFlags[permission as PermissionStrings]);
|
||||
}) as PermissionStrings[];
|
||||
}
|
||||
|
||||
/** This function converts an array of permissions into the bitwise string. */
|
||||
export function calculateBits(permissions: PermissionStrings[]) {
|
||||
return permissions
|
||||
.reduce((bits, perm) => {
|
||||
bits |= BigInt(BitwisePermissionFlags[perm]);
|
||||
return bits;
|
||||
}, 0n)
|
||||
.toString();
|
||||
}
|
||||
-508
@@ -1,508 +0,0 @@
|
||||
import { ListArchivedThreads } from "../helpers/channels/threads/getArchivedThreads.ts";
|
||||
import { GetGuildAuditLog } from "../helpers/guilds/getAuditLogs.ts";
|
||||
import { GetBans } from "../helpers/guilds/getBans.ts";
|
||||
import { GetGuildPruneCountQuery } from "../helpers/guilds/getPruneCount.ts";
|
||||
import { GetScheduledEventUsers } from "../helpers/guilds/scheduledEvents/getScheduledEventUsers.ts";
|
||||
import { GetInvite } from "../helpers/invites/getInvite.ts";
|
||||
import { ListGuildMembers } from "../helpers/members/getMembers.ts";
|
||||
import {
|
||||
GetMessagesOptions,
|
||||
isGetMessagesAfter,
|
||||
isGetMessagesAround,
|
||||
isGetMessagesBefore,
|
||||
isGetMessagesLimit,
|
||||
} from "../helpers/messages/getMessages.ts";
|
||||
import { GetReactions } from "../helpers/messages/getReactions.ts";
|
||||
import { baseEndpoints } from "./constants.ts";
|
||||
|
||||
export const routes = {
|
||||
GATEWAY_BOT: () => {
|
||||
return `/gateway/bot`;
|
||||
},
|
||||
|
||||
// Automod Endpoints
|
||||
AUTOMOD_RULES: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/auto-moderation/rules`;
|
||||
},
|
||||
AUTOMOD_RULE: (guildId: bigint, ruleId: bigint) => {
|
||||
return `/guilds/${guildId}/auto-moderation/rules/${ruleId}`;
|
||||
},
|
||||
|
||||
// Channel Endpoints
|
||||
CHANNEL: (channelId: bigint) => {
|
||||
return `/channels/${channelId}`;
|
||||
},
|
||||
CHANNEL_MESSAGE: (channelId: bigint, messageId: bigint) => {
|
||||
return `/channels/${channelId}/messages/${messageId}`;
|
||||
},
|
||||
CHANNEL_MESSAGES: (channelId: bigint, options?: GetMessagesOptions) => {
|
||||
let url = `/channels/${channelId}/messages?`;
|
||||
|
||||
if (options) {
|
||||
if (isGetMessagesAfter(options) && options.after) url += `after=${options.after}`;
|
||||
if (isGetMessagesBefore(options) && options.before) url += `&before=${options.before}`;
|
||||
if (isGetMessagesAround(options) && options.around) url += `&around=${options.around}`;
|
||||
if (isGetMessagesLimit(options) && options.limit) url += `&limit=${options.limit}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
CHANNEL_PIN: (channelId: bigint, messageId: bigint) => {
|
||||
return `/channels/${channelId}/pins/${messageId}`;
|
||||
},
|
||||
CHANNEL_PINS: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/pins`;
|
||||
},
|
||||
CHANNEL_BULK_DELETE: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/messages/bulk-delete`;
|
||||
},
|
||||
CHANNEL_INVITES: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/invites`;
|
||||
},
|
||||
CHANNEL_WEBHOOKS: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/webhooks`;
|
||||
},
|
||||
CHANNEL_MESSAGE_REACTION_ME: (channelId: bigint, messageId: bigint, emoji: string) => {
|
||||
return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/@me`;
|
||||
},
|
||||
CHANNEL_MESSAGE_REACTION_USER: (channelId: bigint, messageId: bigint, emoji: string, userId: bigint) => {
|
||||
return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/${userId}`;
|
||||
},
|
||||
CHANNEL_MESSAGE_REACTIONS: (channelId: bigint, messageId: bigint) => {
|
||||
return `/channels/${channelId}/messages/${messageId}/reactions`;
|
||||
},
|
||||
CHANNEL_MESSAGE_REACTION: (channelId: bigint, messageId: bigint, emoji: string, options?: GetReactions) => {
|
||||
let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`;
|
||||
|
||||
if (options) {
|
||||
if (options.after) url += `after=${options.after}`;
|
||||
if (options.limit) url += `&limit=${options.limit}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
CHANNEL_FOLLOW: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/followers`;
|
||||
},
|
||||
CHANNEL_MESSAGE_CROSSPOST: (channelId: bigint, messageId: bigint) => {
|
||||
return `/channels/${channelId}/messages/${messageId}/crosspost`;
|
||||
},
|
||||
CHANNEL_OVERWRITE: (channelId: bigint, overwriteId: bigint) => {
|
||||
return `/channels/${channelId}/permissions/${overwriteId}`;
|
||||
},
|
||||
// Bots SHALL NOT use this endpoint but they can
|
||||
CHANNEL_TYPING: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/typing`;
|
||||
},
|
||||
|
||||
// Thread Endpoints
|
||||
THREAD_START_PUBLIC: (channelId: bigint, messageId: bigint) => {
|
||||
return `/channels/${channelId}/messages/${messageId}/threads`;
|
||||
},
|
||||
THREAD_START_PRIVATE: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/threads`;
|
||||
},
|
||||
THREAD_ACTIVE: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/threads/active`;
|
||||
},
|
||||
THREAD_MEMBERS: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/thread-members`;
|
||||
},
|
||||
THREAD_ME: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/thread-members/@me`;
|
||||
},
|
||||
THREAD_USER: (channelId: bigint, userId: bigint) => {
|
||||
return `/channels/${channelId}/thread-members/${userId}`;
|
||||
},
|
||||
THREAD_ARCHIVED: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/threads/archived`;
|
||||
},
|
||||
THREAD_ARCHIVED_PUBLIC: (channelId: bigint, options?: ListArchivedThreads) => {
|
||||
let url = `/channels/${channelId}/threads/archived/public?`;
|
||||
|
||||
if (options) {
|
||||
if (options.before) url += `before=${new Date(options.before).toISOString()}`;
|
||||
if (options.limit) url += `&limit=${options.limit}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
THREAD_ARCHIVED_PRIVATE: (channelId: bigint, options?: ListArchivedThreads) => {
|
||||
let url = `/channels/${channelId}/threads/archived/private?`;
|
||||
|
||||
if (options) {
|
||||
if (options.before) url += `before=${new Date(options.before).toISOString()}`;
|
||||
if (options.limit) url += `&limit=${options.limit}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
THREAD_ARCHIVED_PRIVATE_JOINED: (channelId: bigint, options?: ListArchivedThreads) => {
|
||||
let url = `/channels/${channelId}/users/@me/threads/archived/private?`;
|
||||
|
||||
if (options) {
|
||||
if (options.before) url += `before=${new Date(options.before).toISOString()}`;
|
||||
if (options.limit) url += `&limit=${options.limit}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
// Thread -> Forum Endpoints
|
||||
FORUM_START: (channelId: bigint) => {
|
||||
return `/channels/${channelId}/threads?has_message=true`;
|
||||
},
|
||||
|
||||
// Guild Endpoints
|
||||
GUILD: (guildId: bigint, withCounts?: boolean) => {
|
||||
let url = `/guilds/${guildId}?`;
|
||||
|
||||
if (withCounts !== undefined) {
|
||||
url += `with_counts=${withCounts}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
GUILDS: () => {
|
||||
return `/guilds`;
|
||||
},
|
||||
GUILD_AUDIT_LOGS: (guildId: bigint, options?: GetGuildAuditLog) => {
|
||||
let url = `/guilds/${guildId}/audit-logs?`;
|
||||
|
||||
if (options) {
|
||||
if (options.actionType) url += `action_type=${options.actionType}`;
|
||||
if (options.before) url += `&before=${options.before}`;
|
||||
if (options.limit) url += `&limit=${options.limit}`;
|
||||
if (options.userId) url += `&user_id=${options.userId}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
GUILD_BAN: (guildId: bigint, userId: bigint) => {
|
||||
return `/guilds/${guildId}/bans/${userId}`;
|
||||
},
|
||||
GUILD_BANS: (guildId: bigint, options?: GetBans) => {
|
||||
let url = `/guilds/${guildId}/bans?`;
|
||||
|
||||
if (options) {
|
||||
if (options.limit) url += `limit=${options.limit}`;
|
||||
if (options.after) url += `&after=${options.after}`;
|
||||
if (options.before) url += `&before=${options.before}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
// TODO: move this away
|
||||
GUILD_BANNER: (guildId: bigint, icon: string) => {
|
||||
return `${baseEndpoints.CDN_URL}/banners/${guildId}/${icon}`;
|
||||
},
|
||||
GUILD_CHANNELS: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/channels`;
|
||||
},
|
||||
GUILD_WIDGET: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/widget`;
|
||||
},
|
||||
GUILD_WIDGET_JSON: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/widget.json`;
|
||||
},
|
||||
GUILD_WIDGET_IMAGE: (
|
||||
guildId: bigint,
|
||||
style?:
|
||||
| "shield"
|
||||
| "banner1"
|
||||
| "banner2"
|
||||
| "banner3"
|
||||
| "banner4",
|
||||
) => {
|
||||
let url = `/guilds/${guildId}/widget.png?`;
|
||||
|
||||
if (style) {
|
||||
url += `style=${style}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
GUILD_EMOJI: (guildId: bigint, emojiId: bigint) => {
|
||||
return `/guilds/${guildId}/emojis/${emojiId}`;
|
||||
},
|
||||
GUILD_EMOJIS: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/emojis`;
|
||||
},
|
||||
// TODO: move this away
|
||||
GUILD_ICON: (guildId: bigint, icon: string) => {
|
||||
return `${baseEndpoints.CDN_URL}/icons/${guildId}/${icon}`;
|
||||
},
|
||||
GUILD_INTEGRATION: (guildId: bigint, integrationId: bigint) => {
|
||||
return `/guilds/${guildId}/integrations/${integrationId}`;
|
||||
},
|
||||
GUILD_INTEGRATION_SYNC: (guildId: bigint, integrationId: bigint) => {
|
||||
return `/guilds/${guildId}/integrations/${integrationId}/sync`;
|
||||
},
|
||||
GUILD_INTEGRATIONS: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/integrations?include_applications=true`;
|
||||
},
|
||||
GUILD_INVITES: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/invites`;
|
||||
},
|
||||
GUILD_LEAVE: (guildId: bigint) => {
|
||||
return `/users/@me/guilds/${guildId}`;
|
||||
},
|
||||
GUILD_MEMBER: (guildId: bigint, userId: bigint) => {
|
||||
return `/guilds/${guildId}/members/${userId}`;
|
||||
},
|
||||
GUILD_MEMBERS: (guildId: bigint, options?: ListGuildMembers) => {
|
||||
let url = `/guilds/${guildId}/members?`;
|
||||
|
||||
if (options !== undefined) {
|
||||
if (options.limit) url += `limit=${options.limit}`;
|
||||
if (options.after) url += `&after=${options.after}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
GUILD_MEMBER_ROLE: (guildId: bigint, memberId: bigint, roleId: bigint) => {
|
||||
return `/guilds/${guildId}/members/${memberId}/roles/${roleId}`;
|
||||
},
|
||||
GUILD_MEMBERS_SEARCH: (guildId: bigint, query: string, options?: { limit?: number }) => {
|
||||
let url = `/guilds/${guildId}/members/search?query=${encodeURIComponent(query)}`;
|
||||
|
||||
if (options) {
|
||||
if (options.limit !== undefined) url += `&limit=${options.limit}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
GUILD_PRUNE: (guildId: bigint, options?: GetGuildPruneCountQuery) => {
|
||||
let url = `/guilds/${guildId}/prune?`;
|
||||
|
||||
if (options) {
|
||||
if (options.days) url += `days=${options.days}`;
|
||||
if (options.includeRoles) url += `&include_roles=${options.includeRoles}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
GUILD_REGIONS: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/regions`;
|
||||
},
|
||||
GUILD_ROLE: (guildId: bigint, roleId: bigint) => {
|
||||
return `/guilds/${guildId}/roles/${roleId}`;
|
||||
},
|
||||
GUILD_ROLES: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/roles`;
|
||||
},
|
||||
// TODO: move this away
|
||||
GUILD_SPLASH: (guildId: bigint, icon: string) => {
|
||||
return `${baseEndpoints.CDN_URL}/splashes/${guildId}/${icon}`;
|
||||
},
|
||||
GUILD_VANITY_URL: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/vanity-url`;
|
||||
},
|
||||
GUILD_WEBHOOKS: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/webhooks`;
|
||||
},
|
||||
TEMPLATE: (code: string) => {
|
||||
return `/guilds/templates/${code}`;
|
||||
},
|
||||
GUILD_TEMPLATE: (guildId: bigint, code: string) => {
|
||||
return `/guilds/${guildId}/templates/${code}`;
|
||||
},
|
||||
GUILD_TEMPLATES: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/templates`;
|
||||
},
|
||||
GUILD_PREVIEW: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/preview`;
|
||||
},
|
||||
UPDATE_VOICE_STATE: (guildId: bigint, userId?: bigint) => {
|
||||
return `/guilds/${guildId}/voice-states/${userId ?? "@me"}`;
|
||||
},
|
||||
GUILD_WELCOME_SCREEN: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/welcome-screen`;
|
||||
},
|
||||
GUILD_SCHEDULED_EVENTS: (guildId: bigint, withUserCount?: boolean) => {
|
||||
let url = `/guilds/${guildId}/scheduled-events?`;
|
||||
|
||||
if (withUserCount !== undefined) {
|
||||
url += `with_user_count=${withUserCount}`;
|
||||
}
|
||||
return url;
|
||||
},
|
||||
GUILD_SCHEDULED_EVENT: (guildId: bigint, eventId: bigint, withUserCount?: boolean) => {
|
||||
let url = `/guilds/${guildId}/scheduled-events/${eventId}`;
|
||||
|
||||
if (withUserCount !== undefined) {
|
||||
url += `with_user_count=${withUserCount}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
GUILD_SCHEDULED_EVENT_USERS: (guildId: bigint, eventId: bigint, options?: GetScheduledEventUsers) => {
|
||||
let url = `/guilds/${guildId}/scheduled-events/${eventId}/users?`;
|
||||
|
||||
if (options) {
|
||||
if (options.limit) url += `limit=${options.limit}`;
|
||||
if (options.withMember) url += `&with_member=${options.withMember}`;
|
||||
if (options.after) url += `&after=${options.after}`;
|
||||
if (options.before) url += `&before=${options.before}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
// Voice
|
||||
VOICE_REGIONS: () => {
|
||||
return `/voice/regions`;
|
||||
},
|
||||
|
||||
INVITE: (inviteCode: string, options?: GetInvite) => {
|
||||
let url = `/invites/${inviteCode}?`;
|
||||
|
||||
if (options) {
|
||||
if (options.withCounts) url += `with_counts=${options.withCounts}`;
|
||||
if (options.withExpiration) url += `&with_expiration=${options.withExpiration}`;
|
||||
if (options.scheduledEventId) url += `&guild_scheduled_event_id=${options.scheduledEventId}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
WEBHOOK: (webhookId: bigint, token: string, options?: { wait?: boolean; threadId?: bigint }) => {
|
||||
let url = `/webhooks/${webhookId}/${token}?`;
|
||||
|
||||
if (options) {
|
||||
if (options?.wait !== undefined) url += `wait=${options.wait}`;
|
||||
if (options.threadId) url += `threadId=${options.threadId}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
WEBHOOK_ID: (webhookId: bigint) => {
|
||||
return `/webhooks/${webhookId}`;
|
||||
},
|
||||
WEBHOOK_MESSAGE: (webhookId: bigint, token: string, messageId: bigint, options?: { threadId?: bigint }) => {
|
||||
let url = `/webhooks/${webhookId}/${token}/messages/${messageId}?`;
|
||||
|
||||
if (options) {
|
||||
if (options.threadId) url += `threadId=${options.threadId}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
WEBHOOK_MESSAGE_ORIGINAL: (webhookId: bigint, token: string, options?: { threadId?: bigint }) => {
|
||||
let url = `/webhooks/${webhookId}/${token}/messages/@original?`;
|
||||
|
||||
if (options) {
|
||||
if (options.threadId) url += `threadId=${options.threadId}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
WEBHOOK_SLACK: (webhookId: bigint, token: string) => {
|
||||
return `/webhooks/${webhookId}/${token}/slack`;
|
||||
},
|
||||
WEBHOOK_GITHUB: (webhookId: bigint, token: string) => {
|
||||
return `/webhooks/${webhookId}/${token}/github`;
|
||||
},
|
||||
|
||||
// Application Endpoints
|
||||
COMMANDS: (applicationId: bigint) => {
|
||||
return `/applications/${applicationId}/commands`;
|
||||
},
|
||||
COMMANDS_GUILD: (applicationId: bigint, guildId: bigint) => {
|
||||
return `/applications/${applicationId}/guilds/${guildId}/commands`;
|
||||
},
|
||||
COMMANDS_PERMISSIONS: (applicationId: bigint, guildId: bigint) => {
|
||||
return `/applications/${applicationId}/guilds/${guildId}/commands/permissions`;
|
||||
},
|
||||
COMMANDS_PERMISSION: (applicationId: bigint, guildId: bigint, commandId: bigint) => {
|
||||
return `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}/permissions`;
|
||||
},
|
||||
COMMANDS_ID: (applicationId: bigint, commandId: bigint, withLocalizations?: boolean) => {
|
||||
let url = `/applications/${applicationId}/commands/${commandId}?`;
|
||||
|
||||
if (withLocalizations !== undefined) {
|
||||
url += `withLocalizations=${withLocalizations}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
COMMANDS_GUILD_ID: (applicationId: bigint, guildId: bigint, commandId: bigint, withLocalizations?: boolean) => {
|
||||
let url = `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}?`;
|
||||
|
||||
if (withLocalizations !== undefined) {
|
||||
url += `with_localizations=${withLocalizations}`;
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
// Interaction Endpoints
|
||||
INTERACTION_ID_TOKEN: (interactionId: bigint, token: string) => {
|
||||
return `/interactions/${interactionId}/${token}/callback`;
|
||||
},
|
||||
INTERACTION_ORIGINAL_ID_TOKEN: (interactionId: bigint, token: string) => {
|
||||
return `/webhooks/${interactionId}/${token}/messages/@original`;
|
||||
},
|
||||
INTERACTION_ID_TOKEN_MESSAGE_ID: (applicationId: bigint, token: string, messageId: bigint) => {
|
||||
return `/webhooks/${applicationId}/${token}/messages/${messageId}`;
|
||||
},
|
||||
|
||||
// User endpoints
|
||||
USER: (userId: bigint) => {
|
||||
return `/users/${userId}`;
|
||||
},
|
||||
USER_BOT: () => {
|
||||
return `/users/@me`;
|
||||
},
|
||||
USER_GUILDS: () => {
|
||||
return `/users/@me/guilds`;
|
||||
},
|
||||
// TODO: move this away
|
||||
USER_AVATAR: (userId: bigint, icon: string) => {
|
||||
return `${baseEndpoints.CDN_URL}/avatars/${userId}/${icon}`;
|
||||
},
|
||||
// TODO: move this away
|
||||
USER_DEFAULT_AVATAR: (icon: number) => {
|
||||
return `${baseEndpoints.CDN_URL}/embed/avatars/${icon}.png`;
|
||||
},
|
||||
USER_DM: () => {
|
||||
return `/users/@me/channels`;
|
||||
},
|
||||
USER_CONNECTIONS: () => {
|
||||
return `/users/@me/connections`;
|
||||
},
|
||||
USER_NICK: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/members/@me`;
|
||||
},
|
||||
|
||||
// Discovery Endpoints
|
||||
DISCOVERY_CATEGORIES: () => {
|
||||
return `/discovery/categories`;
|
||||
},
|
||||
DISCOVERY_VALID_TERM: (term: string) => {
|
||||
return `/discovery/valid-term?term=${term}`;
|
||||
},
|
||||
DISCOVERY_METADATA: (guildId: bigint) => {
|
||||
return `/guilds/${guildId}/discovery-metadata`;
|
||||
},
|
||||
DISCOVERY_SUBCATEGORY: (guildId: bigint, categoryId: number) => {
|
||||
return `/guilds/${guildId}/discovery-categories/${categoryId}`;
|
||||
},
|
||||
|
||||
// OAuth2
|
||||
OAUTH2_APPLICATION: () => {
|
||||
return `/oauth2/applications/@me`;
|
||||
},
|
||||
|
||||
// Stage instances
|
||||
STAGE_INSTANCES: () => {
|
||||
return `/stage-instances`;
|
||||
},
|
||||
STAGE_INSTANCE: (channelId: bigint) => {
|
||||
return `/stage-instances/${channelId}`;
|
||||
},
|
||||
|
||||
// Misc Endpoints
|
||||
NITRO_STICKER_PACKS: () => {
|
||||
return `/sticker-packs`;
|
||||
},
|
||||
};
|
||||
@@ -1,111 +0,0 @@
|
||||
/** Converts a url to base 64. Useful for example, uploading/creating server emojis. */
|
||||
export async function urlToBase64(url: string) {
|
||||
const buffer = await fetch(url).then((res) => res.arrayBuffer());
|
||||
const imageStr = encode(buffer);
|
||||
const type = url.substring(url.lastIndexOf(".") + 1);
|
||||
return `data:image/${type};base64,${imageStr}`;
|
||||
}
|
||||
|
||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
const base64abc = [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"L",
|
||||
"M",
|
||||
"N",
|
||||
"O",
|
||||
"P",
|
||||
"Q",
|
||||
"R",
|
||||
"S",
|
||||
"T",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"e",
|
||||
"f",
|
||||
"g",
|
||||
"h",
|
||||
"i",
|
||||
"j",
|
||||
"k",
|
||||
"l",
|
||||
"m",
|
||||
"n",
|
||||
"o",
|
||||
"p",
|
||||
"q",
|
||||
"r",
|
||||
"s",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"+",
|
||||
"/",
|
||||
];
|
||||
|
||||
/**
|
||||
* CREDIT: https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727
|
||||
* Encodes a given Uint8Array, ArrayBuffer or string into RFC4648 base64 representation
|
||||
* @param data
|
||||
*/
|
||||
export function encode(data: ArrayBuffer | string): string {
|
||||
const uint8 = typeof data === "string"
|
||||
? new TextEncoder().encode(data)
|
||||
: data instanceof Uint8Array
|
||||
? data
|
||||
: new Uint8Array(data);
|
||||
let result = "",
|
||||
i;
|
||||
const l = uint8.length;
|
||||
for (i = 2; i < l; i += 3) {
|
||||
result += base64abc[uint8[i - 2] >> 2];
|
||||
result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];
|
||||
result += base64abc[((uint8[i - 1] & 0x0f) << 2) | (uint8[i] >> 6)];
|
||||
result += base64abc[uint8[i] & 0x3f];
|
||||
}
|
||||
if (i === l + 1) {
|
||||
// 1 octet yet to write
|
||||
result += base64abc[uint8[i - 2] >> 2];
|
||||
result += base64abc[(uint8[i - 2] & 0x03) << 4];
|
||||
result += "==";
|
||||
}
|
||||
if (i === l) {
|
||||
// 2 octets yet to write
|
||||
result += base64abc[uint8[i - 2] >> 2];
|
||||
result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];
|
||||
result += base64abc[(uint8[i - 1] & 0x0f) << 2];
|
||||
result += "=";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ImageFormat, ImageSize } from "../helpers/members/avatarUrl.ts";
|
||||
|
||||
/** Pause the execution for a given amount of milliseconds. */
|
||||
export function delay(ms: number): Promise<void> {
|
||||
return new Promise((res): number =>
|
||||
setTimeout((): void => {
|
||||
res();
|
||||
}, ms)
|
||||
);
|
||||
}
|
||||
|
||||
/** Help format an image url. */
|
||||
export function formatImageURL(url: string, size: ImageSize = 128, format?: ImageFormat) {
|
||||
return `${url}.${format || (url.includes("/a_") ? "gif" : "jpg")}?size=${size}`;
|
||||
}
|
||||
|
||||
// Typescript is not so good as we developers so we need this little utility function to help it out
|
||||
// Taken from https://fettblog.eu/typescript-hasownproperty/
|
||||
/** TS save way to check if a property exists in an object */
|
||||
export function hasProperty<T extends {}, Y extends PropertyKey = string>(
|
||||
obj: T,
|
||||
prop: Y,
|
||||
): obj is T & Record<Y, unknown> {
|
||||
return obj.hasOwnProperty(prop);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/** Validates the length of a string in JS. Certain characters in JS can have multiple numbers in length in unicode and discords api is in python which treats length differently. */
|
||||
export function validateLength(text: string, options: { max?: number; min?: number }) {
|
||||
const length = [...text].length;
|
||||
|
||||
// Text is too long
|
||||
if (options.max && length > options.max) return false;
|
||||
// Text is too short
|
||||
if (options.min && length < options.min) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user