From b2af730bec0573c9a6e7b7bd4ea9a25f6e998d40 Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 27 Apr 2020 18:33:44 -0400 Subject: [PATCH] get rid of snake case and methods --- events/channels.ts | 38 +- events/guilds.ts | 14 +- mod.ts | 11 +- module/client.ts | 364 ++++++++--------- module/gateway.ts | 12 +- module/requestManager.ts | 108 +++++ module/request_manager.ts | 108 ----- ...sharding_manager.ts => shardingManager.ts} | 4 +- structures/channel.ts | 146 +++---- structures/guild.ts | 379 +++++++----------- structures/member.ts | 97 ++--- structures/message.ts | 175 ++++---- structures/queue.ts | 61 --- structures/role.ts | 27 +- structures/user.ts | 32 +- types/activity.ts | 27 +- types/cdn.ts | 4 +- types/channel.ts | 22 +- types/discord.ts | 14 +- types/guild.ts | 66 +-- types/member.ts | 12 +- types/message.ts | 47 ++- types/options.ts | 83 ++-- types/queue.ts | 38 -- types/return-type.ts | 5 - types/role.ts | 2 +- utils/cache.ts | 27 +- utils/cdn.ts | 6 +- utils/logger.ts | 16 +- utils/permissions.ts | 26 +- 30 files changed, 854 insertions(+), 1117 deletions(-) create mode 100644 module/requestManager.ts delete mode 100644 module/request_manager.ts rename module/{sharding_manager.ts => shardingManager.ts} (73%) delete mode 100644 structures/queue.ts delete mode 100644 types/queue.ts delete mode 100644 types/return-type.ts diff --git a/events/channels.ts b/events/channels.ts index 36a4c89b0..c76568e6d 100644 --- a/events/channels.ts +++ b/events/channels.ts @@ -1,47 +1,47 @@ import { cache } from "../utils/cache.ts" -import { Channel_Create_Payload, Channel_Types } from "../types/channel.ts" -import { create_channel } from "../structures/channel.ts" -import { event_handlers } from "../module/client.ts" +import { ChannelCreatePayload, ChannelTypes } from "../types/channel.ts" +import { createChannel } from "../structures/channel.ts" +import { eventHandlers } from "../module/client.ts" -export const handle_internal_channel_create = (data: Channel_Create_Payload) => { - const channel = create_channel(data) +export const handleInternalChannelCreate = (data: ChannelCreatePayload) => { + const channel = createChannel(data) cache.channels.set(channel.id, channel) - event_handlers.channel_create?.(channel) + eventHandlers.channelCreate?.(channel) } -export const handle_internal_channel_update = (data: Channel_Create_Payload) => { - const cached_channel = cache.channels.get(data.id) - const channel = create_channel(data) +export const handleInternalChannelUpdate = (data: ChannelCreatePayload) => { + const cachedChannel = cache.channels.get(data.id) + const channel = createChannel(data) cache.channels.set(channel.id, channel) - if (!cached_channel) return + if (!cachedChannel) return - event_handlers.channel_update?.(channel, cached_channel) + eventHandlers.channel_update?.(channel, cachedChannel) } -export const handle_internal_channel_delete = (data: Channel_Create_Payload) => { - const cached_channel = cache.channels.get(data.id) - if (!cached_channel) return +export const handleInternalChannelDelete = (data: ChannelCreatePayload) => { + const cachedChannel = cache.channels.get(data.id) + if (!cachedChannel) return - if (cached_channel.type() === Channel_Types.GUILD_VOICE && data.guild_id) { + if (cachedChannel.type === ChannelTypes.GUILD_VOICE && data.guild_id) { const guild = cache.guilds.get(data.guild_id) - guild?.voice_states().forEach(vs => { + guild?.voice_states.forEach((vs) => { if (vs.channel_id !== data.id) return const member = guild.members.get(vs.user_id) if (!member) return - event_handlers.voice_channel_leave?.(member, vs.channel_id) + eventHandlers.voiceChannelLeave?.(member, vs.channel_id) }) if (guild) { cache.guilds.set(data.guild_id, { ...guild, - voice_states: () => [...guild.voice_states().filter(vs => vs.channel_id !== data.id)] + voice_states: [...guild.voice_states.filter((vs) => vs.channel_id !== data.id)], }) } } cache.channels.delete(data.id) - event_handlers.channel_delete?.(cached_channel) + eventHandlers.channelDelete?.(cachedChannel) } diff --git a/events/guilds.ts b/events/guilds.ts index da114beda..b1ee88500 100644 --- a/events/guilds.ts +++ b/events/guilds.ts @@ -1,14 +1,14 @@ -import { Guild } from "../types/return-type.ts" import { cache } from "../utils/cache.ts" +import { Guild } from "../structures/guild.ts" -export const handle_internal_guild_create = (guild: Guild) => { - cache.guilds.set(guild.id(), guild) +export const handleInternalGuildCreate = (guild: Guild) => { + cache.guilds.set(guild.id, guild) } -export const handle_internal_guild_update = (guild: Guild) => { - cache.guilds.set(guild.id(), guild) +export const handleInternalGuildUpdate = (guild: Guild) => { + cache.guilds.set(guild.id, guild) } -export const handle_internal_guild_delete = (guild: Guild) => { - cache.guilds.delete(guild.id()) +export const handleInternalGuildDelete = (guild: Guild) => { + cache.guilds.delete(guild.id) } diff --git a/mod.ts b/mod.ts index c394d8c01..79f9eb567 100644 --- a/mod.ts +++ b/mod.ts @@ -1,13 +1,14 @@ import Client from "./module/client.ts" import { configs } from "./configs.ts" import { Intents } from "./types/options.ts" -import { logYellow } from "./utils/logger.ts" +import { logYellow, logGreen } from "./utils/logger.ts" Client({ token: configs.token, - bot_id: "675412054529540107", + botID: "675412054529540107", intents: [Intents.GUILDS, Intents.GUILD_MESSAGES], - event_handlers: { - ready: () => logYellow("Bot ready emitted") - } + eventHandlers: { + ready: () => logYellow("Bot ready emitted"), + raw: (data) => logGreen("[RAW] => " + JSON.stringify(data)), + }, }) diff --git a/module/client.ts b/module/client.ts index 67f63698e..63f83e1f7 100644 --- a/module/client.ts +++ b/module/client.ts @@ -4,55 +4,52 @@ import { DiscordPayload, DiscordHeartbeatPayload, GatewayOpcode, - Webhook_Update_Payload, - Presence_Update_Payload, - Typing_Start_Payload, - Voice_State_Update_Payload, + WebhookUpdatePayload, + PresenceUpdatePayload, + TypingStartPayload, + VoiceStateUpdatePayload, ReadyPayload, } from "../types/discord.ts" // import { spawnShards } from "./sharding_manager.ts" import { connectWebSocket, isWebSocketCloseEvent, WebSocket } from "https://deno.land/std@v0.41.0/ws/mod.ts" -import { Client_Options, Event_Handlers } from "../types/options.ts" -import { send_constant_heartbeats, update_previous_sequence_number, previous_sequence_number } from "./gateway.ts" -import { create_guild } from "../structures/guild.ts" +import { ClientOptions, EventHandlers } from "../types/options.ts" +import { sendConstantHeartbeats, updatePreviousSequenceNumber, previousSequenceNumber } from "./gateway.ts" +import { createGuild } from "../structures/guild.ts" +import { handleInternalGuildCreate, handleInternalGuildUpdate, handleInternalGuildDelete } from "../events/guilds.ts" import { - handle_internal_guild_create, - handle_internal_guild_update, - handle_internal_guild_delete, -} from "../events/guilds.ts" -import { - Create_Guild_Payload, - Guild_Delete_Payload, - Guild_Ban_Payload, - Guild_Emojis_Update_Payload, - Guild_Member_Add_Payload, - Guild_Member_Update_Payload, - Guild_Member_Chunk_Payload, - Guild_Role_Payload, - User_Payload, + CreateGuildPayload, + GuildDeletePayload, + GuildBanPayload, + GuildEmojisUpdatePayload, + GuildMemberAddPayload, + GuildMemberUpdatePayload, + GuildMemberChunkPayload, + GuildRolePayload, + UserPayload, } from "../types/guild.ts" -import { Channel_Create_Payload } from "../types/channel.ts" +import { ChannelCreatePayload } from "../types/channel.ts" import { - handle_internal_channel_create, - handle_internal_channel_update, - handle_internal_channel_delete, + handleInternalChannelCreate, + handleInternalChannelUpdate, + handleInternalChannelDelete, } from "../events/channels.ts" import { cache } from "../utils/cache.ts" -import { create_user } from "../structures/user.ts" -import { create_member } from "../structures/member.ts" -import { create_role } from "../structures/role.ts" -import { create_message } from "../structures/message.ts" +import { createUser } from "../structures/user.ts" +import { createMember } from "../structures/member.ts" +import { createRole } from "../structures/role.ts" +import { createMessage } from "../structures/message.ts" import { - Message_Create_Options, - Message_Delete_Payload, - Message_Delete_Bulk_Payload, - Message_Update_Payload, - Message_Reaction_Payload, - Base_Message_Reaction_Payload, - Message_Reaction_Remove_Emoji_Payload, + MessageCreateOptions, + MessageDeletePayload, + MessageDeleteBulkPayload, + MessageUpdatePayload, + MessageReactionPayload, + BaseMessageReactionPayload, + MessageReactionRemoveEmojiPayload, } from "../types/message.ts" import { logRed } from "../utils/logger.ts" -import { Request_Manager } from "./request_manager.ts" +import { RequestManager } from "./requestManager.ts" +import { Channel } from "../structures/channel.ts" const defaultOptions = { properties: { @@ -64,32 +61,32 @@ const defaultOptions = { } export let authorization = "" -export let bot_id = "" +export let botID = "" /** The bot's token. This should never be used by end users. It is meant to be used internally to make requests to the Discord API. */ export let token = "" /** The session id is needed for RESUME functionality when discord disconnects randomly. */ export let sessionID = "" -export let event_handlers: Event_Handlers = {} +export let eventHandlers: EventHandlers = {} -let bot_gateway_data: DiscordBotGatewayData +let botGatewayData: DiscordBotGatewayData let socket: WebSocket let resumeInterval: number -export const create_client = async (data: Client_Options) => { +export const createClient = async (data: ClientOptions) => { // Assign some defaults to the options to make them fulfilled / not annoying to use. const options = { ...defaultOptions, ...data, intents: data.intents.reduce((bits, next) => (bits |= next), 0), } - bot_id = data.bot_id + botID = data.botID token = data.token - if (data.event_handlers) event_handlers = data.event_handlers + if (data.eventHandlers) eventHandlers = data.eventHandlers authorization = `Bot ${data.token}` // Initial API connection to get info about bots connection - bot_gateway_data = (await Request_Manager.get(endpoints.GATEWAY_BOT)) as DiscordBotGatewayData - socket = await connectWebSocket(bot_gateway_data.url) + botGatewayData = await RequestManager.get(endpoints.GATEWAY_BOT) + socket = await connectWebSocket(botGatewayData.url) const payload = { token: data.token, @@ -97,63 +94,51 @@ export const create_client = async (data: Client_Options) => { compress: false, properties: options.properties, intents: options.intents, - shards: [0, bot_gateway_data.shards], + shards: [0, botGatewayData.shards], } // Intial identify with the gateway await socket.send(JSON.stringify({ op: GatewayOpcode.Identify, d: payload })) for await (const message of socket.receive()) { if (typeof message === "string") { - handle_discord_payload(JSON.parse(message), socket) + handleDiscordPayload(JSON.parse(message), socket) } else if (isWebSocketCloseEvent(message)) { - logRed(`Close :( ${message}`) - // RESUME: Websocket closed/disconnected so we should try and resume the connection. + logRed(`Close :( ${JSON.stringify(message)}`) resumeConnection(payload) - socket = await connectWebSocket(bot_gateway_data.url) - - await socket.send( - JSON.stringify({ - op: GatewayOpcode.Resume, - d: { - ...payload, - session_id: sessionID, - seq: previous_sequence_number, - }, - }) - ) } } - // spawnShards(bot_gateway_data, 1, socket, payload) + // spawnShards(botGatewayData, 1, socket, payload) } async function resumeConnection(payload: object) { resumeInterval = setInterval(async () => { - socket = await connectWebSocket(bot_gateway_data.url) + socket = await connectWebSocket(botGatewayData.url) await socket.send( JSON.stringify({ op: GatewayOpcode.Resume, d: { ...payload, session_id: sessionID, - seq: previous_sequence_number, + seq: previousSequenceNumber, }, }) ) }, 1000 * 15) } -function handle_discord_payload(data: DiscordPayload, socket: WebSocket) { - // Update the sequence number if it is present so that heartbeating can be accurate - if (data.s) update_previous_sequence_number(data.s) +function handleDiscordPayload(data: DiscordPayload, socket: WebSocket) { + // Update the sequence number if it is present + if (data.s) updatePreviousSequenceNumber(data.s) + eventHandlers.raw?.(data) switch (data.op) { case GatewayOpcode.Hello: - send_constant_heartbeats(socket, (data.d as DiscordHeartbeatPayload).heartbeat_interval) + sendConstantHeartbeats(socket, (data.d as DiscordHeartbeatPayload).heartbeat_interval) return case GatewayOpcode.HeartbeatACK: // Incase the user wants to listen to heartbeat responses - return event_handlers.heartbeat?.() + return eventHandlers.heartbeat?.() case GatewayOpcode.Reconnect: case GatewayOpcode.InvalidSession: // Reconnect to the gateway https://discordapp.com/developers/docs/topics/gateway#reconnect @@ -163,276 +148,274 @@ function handle_discord_payload(data: DiscordPayload, socket: WebSocket) { return clearInterval(resumeInterval) case GatewayOpcode.Dispatch: if (data.t === "READY") { + // Important for RESUME sessionID = (data.d as ReadyPayload).session_id - return event_handlers.ready?.() + return eventHandlers.ready?.() } - if (data.t === "CHANNEL_CREATE") return handle_internal_channel_create(data.d as Channel_Create_Payload) - if (data.t === "CHANNEL_UPDATE") return handle_internal_channel_update(data.d as Channel_Create_Payload) - if (data.t === "CHANNEL_DELETE") return handle_internal_channel_delete(data.d as Channel_Create_Payload) + + if (data.t === "CHANNEL_CREATE") return handleInternalChannelCreate(data.d as ChannelCreatePayload) + if (data.t === "CHANNEL_UPDATE") return handleInternalChannelUpdate(data.d as ChannelCreatePayload) + if (data.t === "CHANNEL_DELETE") return handleInternalChannelDelete(data.d as ChannelCreatePayload) if (data.t === "GUILD_CREATE") { - const guild = create_guild(data.d as Create_Guild_Payload) - handle_internal_guild_create(guild) - if (cache.unavailableGuilds.get(guild.id())) { - cache.unavailableGuilds.delete(guild.id()) - return - } - return event_handlers.guild_create?.(guild) + const guild = createGuild(data.d as CreateGuildPayload) + handleInternalGuildCreate(guild) + if (cache.unavailableGuilds.get(guild.id)) return cache.unavailableGuilds.delete(guild.id) + return eventHandlers.guildCreate?.(guild) } if (data.t === "GUILD_UPDATE") { - const options = data.d as Create_Guild_Payload - const cached_guild = cache.guilds.get(options.id) - const guild = create_guild(options) - handle_internal_guild_update(guild) - if (!cached_guild) return + const options = data.d as CreateGuildPayload + const cachedGuild = cache.guilds.get(options.id) + const guild = createGuild(options) + handleInternalGuildUpdate(guild) + if (!cachedGuild) return - return event_handlers.guild_update?.(guild, cached_guild) + return eventHandlers.guildUpdate?.(guild, cachedGuild) } if (data.t === "GUILD_DELETE") { - const options = data.d as Guild_Delete_Payload + const options = data.d as GuildDeletePayload const guild = cache.guilds.get(options.id) if (!guild) return - guild.channels.forEach((_channel, id) => cache.channels.delete(id)) + guild.channels.forEach((channel) => cache.channels.delete(channel.id)) if (options.unavailable) return cache.unavailableGuilds.set(options.id, Date.now()) - handle_internal_guild_delete(guild) - return event_handlers.guild_delete?.(guild) + handleInternalGuildDelete(guild) + return eventHandlers.guildDelete?.(guild) } if (data.t && ["GUILD_BAN_ADD", "GUILD_BAN_REMOVE"].includes(data.t)) { - const options = data.d as Guild_Ban_Payload + const options = data.d as GuildBanPayload const guild = cache.guilds.get(options.guild_id) if (!guild) return - const user = create_user(options.user) + const user = createUser(options.user) return data.t === "GUILD_BAN_ADD" - ? event_handlers.guild_ban_add?.(guild, user) - : event_handlers.guild_ban_remove?.(guild, user) + ? eventHandlers.guildBanAdd?.(guild, user) + : eventHandlers.guildBanRemove?.(guild, user) } if (data.t === "GUILD_EMOJIS_UPDATE") { - const options = data.d as Guild_Emojis_Update_Payload + const options = data.d as GuildEmojisUpdatePayload const guild = cache.guilds.get(options.guild_id) if (!guild) return - const cached_emojis = guild.emojis() - guild.emojis = () => options.emojis + const cachedEmojis = guild.emojis + guild.emojis = options.emojis - return event_handlers.guild_emojis_update?.(guild, options.emojis, cached_emojis) + return eventHandlers.guildEmojisUpdate?.(guild, options.emojis, cachedEmojis) } if (data.t === "GUILD_MEMBER_ADD") { - const options = data.d as Guild_Member_Add_Payload + const options = data.d as GuildMemberAddPayload const guild = cache.guilds.get(options.guild_id) if (!guild) return - const member_count = guild.member_count() + 1 - guild.member_count = () => member_count - const member = create_member( + const memberCount = guild.memberCount + 1 + guild.memberCount = memberCount + const member = createMember( options, options.guild_id, - [...guild.roles().values()].map((role) => role.raw()), - guild.owner_id() + [...guild.roles.values()].map((role) => role.raw), + guild.owner_id ) guild.members.set(options.user.id, member) - return event_handlers.guild_member_add?.(guild, member) + return eventHandlers.guildMemberAdd?.(guild, member) } if (data.t === "GUILD_MEMBER_REMOVE") { - const options = data.d as Guild_Ban_Payload + const options = data.d as GuildBanPayload const guild = cache.guilds.get(options.guild_id) if (!guild) return - const member_count = guild.member_count() - 1 - guild.member_count = () => member_count + const memberCount = guild.memberCount - 1 + guild.memberCount = memberCount const member = guild.members.get(options.user.id) - return event_handlers.guild_member_remove?.(guild, member || create_user(options.user)) + return eventHandlers.guildMemberRemove?.(guild, member || createUser(options.user)) } if (data.t === "GUILD_MEMBER_UPDATE") { - const options = data.d as Guild_Member_Update_Payload + const options = data.d as GuildMemberUpdatePayload const guild = cache.guilds.get(options.guild_id) if (!guild) return - const cached_member = guild.members.get(options.user.id) + const cachedMember = guild.members.get(options.user.id) - const new_member_data = { + const newMemberData = { ...options, premium_since: options.premium_since || undefined, - joined_at: new Date(cached_member?.joined_at() || Date.now()).toISOString(), - deaf: cached_member?.deaf() || false, - mute: cached_member?.mute() || false, + joined_at: new Date(cachedMember?.joined_at || Date.now()).toISOString(), + deaf: cachedMember?.deaf || false, + mute: cachedMember?.mute || false, } - const member = create_member( - new_member_data, + const member = createMember( + newMemberData, options.guild_id, - [...guild.roles().values()].map((r) => r.raw()), - guild.owner_id() + [...guild.roles.values()].map((r) => r.raw), + guild.owner_id ) guild.members.set(options.user.id, member) - if (cached_member?.nick() !== options.nick) - event_handlers.nickname_update?.(guild, member, options.nick, cached_member?.nick()) - const role_ids = cached_member?.roles() || [] + if (cachedMember?.nick !== options.nick) + eventHandlers.nicknameUpdate?.(guild, member, options.nick, cachedMember?.nick) + const roleIDs = cachedMember?.roles || [] - role_ids.forEach((id) => { - if (!options.roles.includes(id)) event_handlers.role_lost?.(guild, member, id) + roleIDs.forEach((id) => { + if (!options.roles.includes(id)) eventHandlers.role_lost?.(guild, member, id) }) options.roles.forEach((id) => { - if (!role_ids.includes(id)) event_handlers.role_gained?.(guild, member, id) + if (!roleIDs.includes(id)) eventHandlers.role_gained?.(guild, member, id) }) - return event_handlers.guild_member_update?.(guild, member, cached_member) + return eventHandlers.guild_member_update?.(guild, member, cachedMember) } if (data.t === "GUILD_MEMBERS_CHUNK") { - const options = data.d as Guild_Member_Chunk_Payload + const options = data.d as GuildMemberChunkPayload const guild = cache.guilds.get(options.guild_id) if (!guild) return options.members.forEach((member) => guild.members.set( member.user.id, - create_member( + createMember( member, options.guild_id, - [...guild.roles().values()].map((r) => r.raw()), - guild.owner_id() + [...guild.roles.values()].map((r) => r.raw), + guild.owner_id ) ) ) } if (data.t && ["GUILD_ROLE_CREATE", "GUILD_ROLE_DELETE", "GUILD_ROLE_UPDATE"].includes(data.t)) { - const options = data.d as Guild_Role_Payload + const options = data.d as GuildRolePayload const guild = cache.guilds.get(options.guild_id) if (!guild) return if (data.t === "GUILD_ROLE_CREATE") { - const role = create_role(options.role) - const roles = guild.roles().set(options.role.id, role) - guild.roles = () => roles - return event_handlers.role_create?.(guild, role) + const role = createRole(options.role) + const roles = guild.roles.set(options.role.id, role) + guild.roles = roles + return eventHandlers.roleCreate?.(guild, role) } - const cached_role = guild.roles().get(options.role.id) + const cached_role = guild.roles.get(options.role.id) if (!cached_role) return if (data.t === "GUILD_ROLE_DELETE") { - const roles = guild.roles() + const roles = guild.roles roles.delete(options.role.id) - guild.roles = () => roles - return event_handlers.role_delete?.(guild, cached_role) + guild.roles = roles + return eventHandlers.roleDelete?.(guild, cached_role) } if (data.t === "GUILD_ROLE_UPDATE") { - const role = create_role(options.role) - return event_handlers.role_update?.(guild, role, cached_role) + const role = createRole(options.role) + return eventHandlers.roleUpdate?.(guild, role, cached_role) } } if (data.t === "MESSAGE_CREATE") { - const options = data.d as Message_Create_Options - const message = create_message(options) - const channel = message.channel() + const options = data.d as MessageCreateOptions + const channel = cache.channels.get(options.channel_id) + const message = createMessage(options) + if (channel) { // channel.last_message_id = () => options.id // if (channel.messages().size > 99) { // TODO: LIMIT THIS TO 100 messages // } } - return event_handlers.message_create?.(message) + return eventHandlers.messageCreate?.(message) } if (data.t && ["MESSAGE_DELETE", "MESSAGE_DELETE_BULK"].includes(data.t)) { - const options = data.d as Message_Delete_Payload - const deleted_messages = - data.t === "MESSAGE_DELETE" ? [options.id] : (data.d as Message_Delete_Bulk_Payload).ids + const options = data.d as MessageDeletePayload + const deletedMessages = data.t === "MESSAGE_DELETE" ? [options.id] : (data.d as MessageDeleteBulkPayload).ids const channel = cache.channels.get(options.channel_id) if (!channel) return - deleted_messages.forEach((id) => { + deletedMessages.forEach((id) => { console.log(id) // const message = channel.messages().get(id) // if (message) { // // TODO: update the messages cache // } - // return event_handlers.message_delete?.(message || { id, channel }) + // return eventHandlers.message_delete?.(message || { id, channel }) }) } if (data.t === "MESSAGE_UPDATE") { - const options = data.d as Message_Update_Payload + const options = data.d as MessageUpdatePayload const channel = cache.channels.get(options.channel_id) if (!channel) return // const cachedMessage = channel.messages().get(options.id) - // return event_handlers.message_update?.(message, cachedMessage) + // return eventHandlers.message_update?.(message, cachedMessage) } if (data.t && ["MESSAGE_REACTION_ADD", "MESSAGE_REACTION_REMOVE"].includes(data.t)) { - const options = data.d as Message_Reaction_Payload + const options = data.d as MessageReactionPayload const message = cache.messages.get(options.message_id) const isAdd = data.t === "MESSAGE_REACTION_ADD" if (message) { - const previous_reactions = message.reactions() - const reaction_existed = previous_reactions.find( + const previousReactions = message.reactions + const reactionExisted = previousReactions?.find( (reaction) => reaction.emoji.id === options.emoji.id && reaction.emoji.name === options.emoji.name ) - if (reaction_existed) reaction_existed.count = isAdd ? reaction_existed.count + 1 : reaction_existed.count - 1 - else - message.reactions = () => [ - ...message.reactions(), - { - count: 1, - me: options.user_id === bot_id, - emoji: { ...options.emoji, id: options.emoji.id || undefined }, - }, - ] + if (reactionExisted) reactionExisted.count = isAdd ? reactionExisted.count + 1 : reactionExisted.count - 1 + else { + const newReaction = { + count: 1, + me: options.user_id === botID, + emoji: { ...options.emoji, id: options.emoji.id || undefined }, + } + message.reactions = message.reactions ? [...message.reactions, newReaction] : [newReaction] + } cache.messages.set(options.message_id, message) } return isAdd - ? event_handlers.reaction_add?.(message || options, options.emoji, options.user_id) - : event_handlers.reaction_remove?.(message || options, options.emoji, options.user_id) + ? eventHandlers.reactionAdd?.(message || options, options.emoji, options.user_id) + : eventHandlers.reactionRemove?.(message || options, options.emoji, options.user_id) } if (data.t === "MESSAGE_REACTION_REMOVE_ALL") { - return event_handlers.reaction_remove_all?.(data.d as Base_Message_Reaction_Payload) + return eventHandlers.reactionRemoveAll?.(data.d as BaseMessageReactionPayload) } if (data.t === "MESSAGE_REACTION_REMOVE_EMOJI") { - return event_handlers.reaction_remove_emoji?.(data.d as Message_Reaction_Remove_Emoji_Payload) + return eventHandlers.reactionRemoveEmoji?.(data.d as MessageReactionRemoveEmojiPayload) } if (data.t === "PRESENCE_UPDATE") { - return event_handlers.presence_update?.(data.d as Presence_Update_Payload) + return eventHandlers.presenceUpdate?.(data.d as PresenceUpdatePayload) } if (data.t === "TYPING_START") { - return event_handlers.typing_start?.(data.d as Typing_Start_Payload) + return eventHandlers.typingStart?.(data.d as TypingStartPayload) } if (data.t === "USER_UPDATE") { - const user_data = data.d as User_Payload - const cached_user = cache.users.get(bot_id) - const user = create_user(user_data) - cache.users.set(user_data.id, user) - return event_handlers.bot_update?.(user, cached_user) + const userData = data.d as UserPayload + const cachedUser = cache.users.get(botID) + const user = createUser(userData) + cache.users.set(userData.id, user) + return eventHandlers.botUpdate?.(user, cachedUser) } if (data.t === "VOICE_STATE_UPDATE") { - const payload = data.d as Voice_State_Update_Payload + const payload = data.d as VoiceStateUpdatePayload if (!payload.guild_id) return const guild = cache.guilds.get(payload.guild_id) @@ -441,37 +424,44 @@ function handle_discord_payload(data: DiscordPayload, socket: WebSocket) { const member = guild.members.get(payload.user_id) if (!member) return - const cached_state = guild.voice_states().find((state) => state.user_id === payload.user_id) + const cached_state = guild.voice_states.find((state) => state.user_id === payload.user_id) // No cached state before so lets make one for em - if (!cached_state) return (guild.voice_states = () => [...guild.voice_states(), payload]) + if (!cached_state) { + guild.voice_states = [...guild.voice_states, payload] + return + } if (cached_state.channel_id !== payload.channel_id) { // Either joined or moved channels if (payload.channel_id) { cached_state.channel_id ? // Was in a channel before - event_handlers.voice_channel_switch?.(member, payload.channel_id, cached_state.channel_id) + eventHandlers.voiceChannelSwitch?.(member, payload.channel_id, cached_state.channel_id) : // Was not in a channel before so user just joined - event_handlers.voice_channel_join?.(member, payload.channel_id) + eventHandlers.voiceChannelJoin?.(member, payload.channel_id) } // Left the channel else if (cached_state.channel_id) { - event_handlers.voice_channel_leave?.(member, cached_state.channel_id) + eventHandlers.voiceChannelLeave?.(member, cached_state.channel_id) } } - return event_handlers.voice_state_update?.(member, payload) + return eventHandlers.voiceStateUpdate?.(member, payload) } if (data.t === "WEBHOOKS_UPDATE") { - const options = data.d as Webhook_Update_Payload - return event_handlers.webhooks_update?.(options.channel_id, options.guild_id) + const options = data.d as WebhookUpdatePayload + return eventHandlers.webhooksUpdate?.(options.channel_id, options.guild_id) } - return event_handlers.raw?.(data) + return default: return } } -export default create_client +export default createClient + +export const updateChannelCache = (key: string, value: Channel) => { + cache.channels.set(key, value) +} diff --git a/module/gateway.ts b/module/gateway.ts index 44aa712e7..c0a4609a6 100644 --- a/module/gateway.ts +++ b/module/gateway.ts @@ -3,15 +3,15 @@ import { GatewayOpcode } from "../types/discord.ts" import { delay } from "https://deno.land/std@v0.41.0/util/async.ts" // Discord requests null if no number has yet been sent by discord -export let previous_sequence_number: number | null = null +export let previousSequenceNumber: number | null = null // TODO: If a client does not receive a heartbeat ack between its attempts at sending heartbeats, it should immediately terminate the connection with a non-1000 close code, reconnect, and attempt to resume. -export const send_constant_heartbeats = async (socket: WebSocket, interval: number) => { +export const sendConstantHeartbeats = async (socket: WebSocket, interval: number) => { await delay(interval) - socket.send(JSON.stringify({ op: GatewayOpcode.Heartbeat, d: previous_sequence_number })) - send_constant_heartbeats(socket, interval) + socket.send(JSON.stringify({ op: GatewayOpcode.Heartbeat, d: previousSequenceNumber })) + sendConstantHeartbeats(socket, interval) } -export const update_previous_sequence_number = (sequence: number) => { - previous_sequence_number = sequence +export const updatePreviousSequenceNumber = (sequence: number) => { + previousSequenceNumber = sequence } diff --git a/module/requestManager.ts b/module/requestManager.ts new file mode 100644 index 000000000..289275310 --- /dev/null +++ b/module/requestManager.ts @@ -0,0 +1,108 @@ +import { RequestMethod } from "../types/fetch.ts" +import { authorization } from "./client.ts" +import { sleep } from "../utils/utils.ts" + +const ratelimitedPaths = new Map() + +export interface RateLimitedPath { + url: string + resetTimestamp: number +} + +setInterval(() => { + const now = Date.now() + ratelimitedPaths.forEach((value, key) => { + if (value.resetTimestamp > now) return + ratelimitedPaths.delete(key) + }) +}, 1000) + +export const RequestManager = { + // Something off about using runMethod with get breaks when using fetch + get: async (url: string, body?: unknown) => { + await checkRatelimits(url) + const result = await fetch(url, createRequestBody(body)) + processHeaders(url, result.headers) + + return result.json() + }, + post: (url: string, body?: unknown) => { + return runMethod(RequestMethod.Post, url, body) + }, + delete: (url: string, body?: unknown) => { + return runMethod(RequestMethod.Delete, url, body) + }, + patch: (url: string, body?: unknown) => { + return runMethod(RequestMethod.Patch, url, body) + }, + put: (url: string, body?: unknown) => { + return runMethod(RequestMethod.Put, url, body) + }, +} + +const createRequestBody = (body: any, method?: RequestMethod) => { + return { + headers: { + Authorization: authorization, + "User-Agent": `DiscordBot (https://github.com/skillz4killz/discordeno, 0.0.1)`, + "Content-Type": "application/json", + "X-Audit-Log-Reason": body ? encodeURIComponent(body.reason) : "", + }, + body: JSON.stringify(body), + method: method?.toUpperCase(), + } +} + +const runMethod = async (method: RequestMethod, url: string, body?: unknown) => { + await checkRatelimits(url) + const response = await fetch(url, createRequestBody(body, method)) + processHeaders(url, response.headers) + + // Sometimes Discord returns an empty 204 response that can't be made to JSON. + if (response.status === 204) return + + return await response.json() +} + +const checkRatelimits = async (url: string) => { + const ratelimited = ratelimitedPaths.get(url) + const global = ratelimitedPaths.get("global") + + const now = Date.now() + if (ratelimited && now < ratelimited.resetTimestamp) await sleep(now - ratelimited.resetTimestamp) + if (global && now < global.resetTimestamp) await sleep(now - global.resetTimestamp) +} + +const processHeaders = (url: string, headers: Headers) => { + // If a rate limit response is encountered this will become true and returned + let ratelimited = false + + // Get all useful headers + const remaining = headers.get("x-ratelimit-remaining") + const resetTimestamp = headers.get("x-ratelimit-reset") + const retryAfter = headers.get("retry-after") + const global = headers.get("x-ratelimit-global") + + // If there is no remaining rate limit for this endpoint, we save it in cache + if (remaining && remaining === "0") { + ratelimited = true + + ratelimitedPaths.set(url, { + url, + resetTimestamp: Number(resetTimestamp), + }) + } + + // If there is no remaining global limit, we save it in cache + if (global) { + ratelimited = true + + ratelimitedPaths.set("global", { + url: "global", + resetTimestamp: Date.now() + Number(retryAfter), + }) + } + + // Returns a boolean to check if we need to request again once the rate limit resets + return ratelimited +} diff --git a/module/request_manager.ts b/module/request_manager.ts deleted file mode 100644 index 0aea01b9f..000000000 --- a/module/request_manager.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { RequestMethod } from "../types/fetch.ts" -import { authorization } from "./client.ts" -import { sleep } from "../utils/utils.ts" - -const ratelimited_paths = new Map() - -export interface Rate_Limited_Path { - url: string - reset_timestamp: number -} - -setInterval(() => { - const now = Date.now() - ratelimited_paths.forEach((value, key) => { - if (value.reset_timestamp > now) return - ratelimited_paths.delete(key) - }) -}, 1000) - -export const Request_Manager = { - // Something off about using run_method with get breaks when using fetch - get: async (url: string, body?: unknown) => { - await check_ratelimits(url) - const result = await fetch(url, create_request_body(body)) - process_headers(url, result.headers) - - return result.json() - }, - post: (url: string, body?: unknown) => { - return run_method(RequestMethod.Post, url, body) - }, - delete: (url: string, body?: unknown) => { - return run_method(RequestMethod.Delete, url, body) - }, - patch: (url: string, body?: unknown) => { - return run_method(RequestMethod.Patch, url, body) - }, - put: (url: string, body?: unknown) => { - return run_method(RequestMethod.Put, url, body) - }, -} - -const create_request_body = (body: any, method?: RequestMethod) => { - return { - headers: { - Authorization: authorization, - "User-Agent": `DiscordBot (https://github.com/skillz4killz/discordeno, 0.0.1)`, - "Content-Type": "application/json", - "X-Audit-Log-Reason": body ? encodeURIComponent(body.reason) : "", - }, - body: JSON.stringify(body), - method: method?.toUpperCase(), - } -} - -const run_method = async (method: RequestMethod, url: string, body?: unknown) => { - await check_ratelimits(url) - const response = await fetch(url, create_request_body(body, method)) - process_headers(url, response.headers) - - // Sometimes Discord returns an empty 204 response that can't be made to JSON. - if (response.status === 204) return - - return await response.json() -} - -const check_ratelimits = async (url: string) => { - const ratelimited = ratelimited_paths.get(url) - const global = ratelimited_paths.get("global") - - const now = Date.now() - if (ratelimited && now < ratelimited.reset_timestamp) await sleep(now - ratelimited.reset_timestamp) - if (global && now < global.reset_timestamp) await sleep(now - global.reset_timestamp) -} - -const process_headers = (url: string, headers: Headers) => { - // If a rate limit response is encountered this will become true and returned - let ratelimited = false - - // Get all useful headers - const remaining = headers.get("x-ratelimit-remaining") - const reset_timestamp = headers.get("x-ratelimit-reset") - const retry_after = headers.get("retry-after") - const global = headers.get("x-ratelimit-global") - - // If there is no remaining rate limit for this endpoint, we save it in cache - if (remaining && remaining === "0") { - ratelimited = true - - ratelimited_paths.set(url, { - url, - reset_timestamp: Number(reset_timestamp), - }) - } - - // If there is no remaining global limit, we save it in cache - if (global) { - ratelimited = true - - ratelimited_paths.set("global", { - url: "global", - reset_timestamp: Date.now() + Number(retry_after), - }) - } - - // Returns a boolean to check if we need to request again once the rate limit resets - return ratelimited -} diff --git a/module/sharding_manager.ts b/module/shardingManager.ts similarity index 73% rename from module/sharding_manager.ts rename to module/shardingManager.ts index 397d8dcd1..81c4c6d45 100644 --- a/module/sharding_manager.ts +++ b/module/shardingManager.ts @@ -1,11 +1,11 @@ // import { WebSocket } from "https://deno.land/std@v0.41.0/ws/mod.ts" -// import { Client_Options } from "../types/options.ts" +// import { ClientOptions } from "../types/options.ts" export const spawnShards = (total: number, id = 1) => { // this.ShardingManager.spawnShard(id); if (id < total) spawnShards(total, id + 1) } -// export const spawnShardss = (total: number, socket: WebSocket, data: Client_Options, payload: unknown) => { +// export const spawnShardss = (total: number, socket: WebSocket, data: ClientOptions, payload: unknown) => { // } diff --git a/structures/channel.ts b/structures/channel.ts index 53418b186..52a04cd07 100644 --- a/structures/channel.ts +++ b/structures/channel.ts @@ -1,110 +1,90 @@ import { - Channel_Create_Payload, - Get_Messages_After, - Get_Messages_Around, - Get_Messages, - Get_Messages_Before, + ChannelCreatePayload, + GetMessagesAfter, + GetMessagesAround, + GetMessages, + GetMessagesBefore, MessageContent, - Create_Invite_Options, - Channel_Edit_Options + CreateInviteOptions, + ChannelEditOptions, } from "../types/channel.ts" -import { bot_id } from "../module/client.ts" +import { botID, updateChannelCache } from "../module/client.ts" import { endpoints } from "../constants/discord.ts" -import { create_message, Message } from "./message.ts" -import { Message_Create_Options } from "../types/message.ts" -import { calculate_permissions, bot_has_permission } from "../utils/permissions.ts" +import { createMessage } from "./message.ts" +import { MessageCreateOptions } from "../types/message.ts" +import { calculatePermissions, botHasPermission } from "../utils/permissions.ts" import { Permissions } from "../types/permission.ts" import { Errors } from "../types/errors.ts" -import { Request_Manager } from "../module/request_manager.ts" -import { cache } from "../utils/cache.ts" +import { RequestManager } from "../module/requestManager.ts" -export const create_channel = (data: Channel_Create_Payload) => { +export function createChannel(data: ChannelCreatePayload) { const channel = { + ...data, /** The raw channel data */ - raw: () => data, - /** The unique id of the channel */ - id: data.id, - /** The type of the channel. */ - type: () => data.type, - /** The id of the guild where this channel exists */ - guild_id: () => data.guild_id, + raw: data, /** The permission overwrites for this channel */ - permission_overwrites: () => - data.permission_overwrites - ? data.permission_overwrites.map(perm => ({ - ...perm, - allow: calculate_permissions(perm.allow), - deny: calculate_permissions(perm.deny) - })) - : [], + permissions: data.permission_overwrites + ? data.permission_overwrites.map((perm) => ({ + ...perm, + allow: calculatePermissions(perm.allow), + deny: calculatePermissions(perm.deny), + })) + : [], /** Whether this channel is nsfw or not */ - nsfw: () => data.nsfw || false, - /** A short collection of recently sent messages since bot started. */ - messages: new Map(), - /** The last message id in this channel */ - last_message_id: () => data.last_message_id, + nsfw: data.nsfw || false, + /** The mention of the channel */ + mention: `<#${data.id}>`, + /** Fetch a single message from the server. Requires VIEW_CHANNEL and READ_MESSAGE_HISTORY */ - get_message: async (id: string) => { + getMessage: async (id: string) => { if (data.guild_id) { - if (!bot_has_permission(data.guild_id, bot_id, [Permissions.VIEW_CHANNEL])) + if (!botHasPermission(data.guild_id, botID, [Permissions.VIEW_CHANNEL])) throw new Error(Errors.MISSING_VIEW_CHANNEL) - if (!bot_has_permission(data.guild_id, bot_id, [Permissions.READ_MESSAGE_HISTORY])) + if (!botHasPermission(data.guild_id, botID, [Permissions.READ_MESSAGE_HISTORY])) throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY) } - const result = await Request_Manager.get(endpoints.CHANNEL_MESSAGE(data.id, id)) - return create_message(result) + const result = await RequestManager.get(endpoints.CHANNEL_MESSAGE(data.id, id)) + return createMessage(result) }, /** Fetches between 2-100 messages. Requires VIEW_CHANNEL and READ_MESSAGE_HISTORY */ - get_messages: async (options?: Get_Messages_After | Get_Messages_Before | Get_Messages_Around | Get_Messages) => { + getMessages: async (options?: GetMessagesAfter | GetMessagesBefore | GetMessagesAround | GetMessages) => { if (data.guild_id) { - if (!bot_has_permission(data.guild_id, bot_id, [Permissions.VIEW_CHANNEL])) + if (!botHasPermission(data.guild_id, botID, [Permissions.VIEW_CHANNEL])) throw new Error(Errors.MISSING_VIEW_CHANNEL) - if (!bot_has_permission(data.guild_id, bot_id, [Permissions.READ_MESSAGE_HISTORY])) + if (!botHasPermission(data.guild_id, botID, [Permissions.READ_MESSAGE_HISTORY])) throw new Error(Errors.MISSING_READ_MESSAGE_HISTORY) } if (options?.limit && options.limit > 100) return - const result = (await Request_Manager.get( - endpoints.CHANNEL_MESSAGES(data.id), - options - )) as Message_Create_Options[] - return result.map(res => create_message(res)) + const result = (await RequestManager.get(endpoints.CHANNEL_MESSAGES(data.id), options)) as MessageCreateOptions[] + return result.map((res) => createMessage(res)) }, /** Get pinned messages in this channel. */ - get_pins: async () => { - const result = (await Request_Manager.get(endpoints.CHANNEL_PINS(data.id))) as Message_Create_Options[] - return result.map(res => create_message(res)) + getPins: async () => { + const result = (await RequestManager.get(endpoints.CHANNEL_PINS(data.id))) as MessageCreateOptions[] + return result.map((res) => createMessage(res)) }, /** Send a message to the channel. Requires SEND_MESSAGES permission. */ - send_message: async (content: string | MessageContent) => { + sendMessage: async (content: string | MessageContent) => { if (typeof content === "string") content = { content } if (data.guild_id) { - if (!bot_has_permission(data.guild_id, bot_id, [Permissions.SEND_MESSAGES])) + if (!botHasPermission(data.guild_id, botID, [Permissions.SEND_MESSAGES])) throw new Error(Errors.MISSING_SEND_MESSAGES) - if (content.tts && !bot_has_permission(data.guild_id, bot_id, [Permissions.SEND_TTS_MESSAGES])) + if (content.tts && !botHasPermission(data.guild_id, botID, [Permissions.SEND_TTS_MESSAGES])) throw new Error(Errors.MISSING_SEND_TTS_MESSAGE) } if (content.content && content.content.length > 2000) throw new Error(Errors.MESSAGE_MAX_LENGTH) - const result = await Request_Manager.post(endpoints.CHANNEL_MESSAGES(data.id), content) - return create_message(result) + const result = await RequestManager.post(endpoints.CHANNEL_MESSAGES(data.id), content) + return createMessage(result) }, - /** The position of the channel in the server. If this channel does not have a position for example DM channels, it will be -1 */ - position: () => { - return data.position || -1 - }, - /** The category id for this channel. */ - parent_id: () => data.parent_id, - /** The topic of the channel */ - topic: () => data.topic, - /** The mention of the channel */ - mention: () => `<#${data.id}>`, + /** Delete messages from the channel. 2-100. Requires the MANAGE_MESSAGES permission */ - delete_messages: (ids: string[], reason?: string) => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_MESSAGES])) + deleteMessages: (ids: string[], reason?: string) => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_MESSAGES])) throw new Error(Errors.MISSING_MANAGE_MESSAGES) if (ids.length < 2) throw new Error(Errors.DELETE_MESSAGES_MIN) @@ -113,32 +93,32 @@ export const create_channel = (data: Channel_Create_Payload) => { `This endpoint only accepts a maximum of 100 messages. Deleting the first 100 message ids provided.` ) - return Request_Manager.post(endpoints.CHANNEL_BULK_DELETE(data.id), { + return RequestManager.post(endpoints.CHANNEL_BULK_DELETE(data.id), { messages: ids.splice(0, 100), - reason + reason, }) }, /** Gets the invites for this channel. Requires MANAGE_CHANNEL */ - get_invites: () => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_CHANNELS])) + getInvites: () => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_CHANNELS])) throw new Error(Errors.MISSING_MANAGE_CHANNELS) - return Request_Manager.get(endpoints.CHANNEL_INVITES(data.id)) + return RequestManager.get(endpoints.CHANNEL_INVITES(data.id)) }, /** Creates a new invite for this channel. Requires CREATE_INSTANT_INVITE */ - create_invite: (options: Create_Invite_Options) => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.CREATE_INSTANT_INVITE])) + createInvite: (options: CreateInviteOptions) => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.CREATE_INSTANT_INVITE])) throw new Error(Errors.MISSING_CREATE_INSTANT_INVITE) - return Request_Manager.post(endpoints.CHANNEL_INVITES(data.id), options) + return RequestManager.post(endpoints.CHANNEL_INVITES(data.id), options) }, /** Gets the webhooks for this channel. Requires MANAGE_WEBHOOKS */ - get_webhooks: () => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_WEBHOOKS])) + getWebhooks: () => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_WEBHOOKS])) throw new Error(Errors.MISSING_MANAGE_WEBHOOKS) - return Request_Manager.get(endpoints.CHANNEL_WEBHOOKS(data.id)) + return RequestManager.get(endpoints.CHANNEL_WEBHOOKS(data.id)) + }, + edit: (options: ChannelEditOptions) => { + return RequestManager.patch(endpoints.GUILD_CHANNELS(data.id), options) }, - edit: (options: Channel_Edit_Options) => { - return Request_Manager.patch(endpoints.GUILD_CHANNELS(data.id), options) - } // TODO: after learning opus and stuff /** Join a voice channel. */ // join: () => {}, @@ -146,6 +126,8 @@ export const create_channel = (data: Channel_Create_Payload) => { // leave: () => {} } - cache.channels.set(data.id, channel) + updateChannelCache(data.id, channel) return channel } + +export type Channel = ReturnType diff --git a/structures/guild.ts b/structures/guild.ts index ad4c4e954..4d4b25ef6 100644 --- a/structures/guild.ts +++ b/structures/guild.ts @@ -1,357 +1,286 @@ -import { bot_id } from "../module/client.ts" +import { botID } from "../module/client.ts" import { endpoints } from "../constants/discord.ts" -import { format_image_url } from "../utils/cdn.ts" +import { formatImageURL } from "../utils/cdn.ts" import { - Create_Guild_Payload, + CreateGuildPayload, PrunePayload, - Position_Swap, - Get_Audit_Logs_Options, - Edit_Integration_Options, + PositionSwap, + GetAuditLogsOptions, + EditIntegrationOptions, BanOptions, - Guild_Edit_Options, - Create_Emojis_Options, - Edit_Emojis_Options, - Create_Role_Options + GuildEditOptions, + CreateEmojisOptions, + EditEmojisOptions, + CreateRoleOptions, } from "../types/guild.ts" -import { create_role } from "./role.ts" -import { create_member } from "./member.ts" -import { create_channel } from "./channel.ts" -import { Channel_Create_Options, Channel_Types, Channel_Create_Payload } from "../types/channel.ts" -import { Image_Size, Image_Formats } from "../types/cdn.ts" +import { createRole } from "./role.ts" +import { createMember } from "./member.ts" +import { createChannel } from "./channel.ts" +import { CreateChannelOptions, ChannelTypes, ChannelCreatePayload } from "../types/channel.ts" +import { ImageSize, ImageFormats } from "../types/cdn.ts" import { Permissions, Permission } from "../types/permission.ts" -import { bot_has_permission } from "../utils/permissions.ts" +import { botHasPermission } from "../utils/permissions.ts" import { Errors } from "../types/errors.ts" -import { Request_Manager } from "../module/request_manager.ts" -import { Role_Data } from "../types/role.ts" +import { RequestManager } from "../module/requestManager.ts" +import { RoleData } from "../types/role.ts" -export const create_guild = (data: Create_Guild_Payload) => { +export const createGuild = (data: CreateGuildPayload) => { const guild = { + ...data, /** The raw create guild payload data. */ - raw: () => data, - /** The guild id */ - id: () => data.id, - /** The guild name. 2-100 characters */ - name: () => data.name, - /** The guild icon image hash */ - icon: () => data.icon, - /** The guild splash image hash */ - splash: () => data.splash, - /** The id of the guild owner */ - owner_id: () => data.owner_id, - /** The voice region id for the guild */ - region: () => data.region, - /** The afk channel id */ - afk_channel_id: () => data.afk_channel_id, - /** The AFK timeout in seconds */ - afk_timeout: () => data.afk_timeout, - /** The verification level required for the guild */ - verification_level: () => data.verification_level, + raw: data, /** The roles in the guild */ - roles: () => new Map(data.roles.map(r => [r.id, create_role(r)])), - /** The custom guild emojis */ - emojis: () => data.emojis, - /** The enabled guild features. */ - features: () => data.features, - /** The required MFA level for the guild. */ - mfa_level: () => data.mfa_level, - /** The id of the channel to which system messages are sent. */ - system_channel_id: () => data.system_channel_id, + roles: new Map(data.roles.map((r) => [r.id, createRole(r)])), /** When this guild was joined at. */ - joined_at: Date.parse(data.joined_at), - /** Whether this is considered a large guild. */ - large: () => data.large, - /** Whether this guild is unavailable */ - unavailable: () => data.unavailable, - /** The total number of members in this guild. */ - member_count: () => data.member_count, - /** The current open voice states in the guild. */ - voice_states: () => data.voice_states, + joinedAt: Date.parse(data.joined_at), /** The users in this guild. */ - members: new Map(data.members.map(m => [m.user.id, create_member(m, data.id, data.roles, data.owner_id)])), + members: new Map(data.members.map((m) => [m.user.id, createMember(m, data.id, data.roles, data.owner_id)])), /** The channels in the guild */ - channels: new Map(data.channels.map(c => [c.id, create_channel(c)])), + channels: new Map(data.channels.map((c) => [c.id, createChannel(c)])), /** The presences of all the users in the guild. */ - presences: new Map(data.presences.map(p => [p.user.id, p])), - /** The maximum amount of presences for the guild(the default value, currently 5000 is in effect when null is returned.) */ - max_presences: () => data.max_presences, - /** The maximum amount of members for the guild */ - max_members: () => data.max_members, - /** The vanity url code for the guild */ - vanity_url_code: () => data.vanity_url_code, - /** The description for the guild */ - description: () => data.description, - /** The banner hash */ - banner: () => data.banner, - /** The current premium tier of the guild */ - premium_tier: () => data.premium_tier, - /** The total number of users currently boosting this server. */ - premium_subscription_count: () => data.premium_subscription_count, - /** The preferred locale of this guild only set if the guild has the DISCOVERABLE feature, defaults to en-US */ - preferred_locale: () => data.preferred_locale, - /** Gets an array of all the channels ids that are the children of this category. */ - category_children_ids: (id: string) => data.channels.filter(c => c.parent_id === id).map(c => c.id), - /** The full URL of the icon from Discords CDN. Undefined when no icon is set. */ - icon_url: (size: Image_Size = 128, format?: Image_Formats) => - data.icon ? format_image_url(endpoints.GUILD_ICON(data.id, data.icon), size, format) : undefined, - /** The full URL of the splash from Discords CDN. Undefined if no splash is set. */ - splash_url: (size: Image_Size = 128, format?: Image_Formats) => - data.splash ? format_image_url(endpoints.GUILD_SPLASH(data.id, data.splash), size, format) : undefined, - /** The full URL of the banner from Discords CDN. Undefined if no banner is set. */ - banner_url: (size: Image_Size = 128, format?: Image_Formats) => - data.banner ? format_image_url(endpoints.GUILD_BANNER(data.id, data.banner), size, format) : undefined, - /** Create a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */ - create_channel: async (name: string, options: Channel_Create_Options) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_CHANNELS])) - throw new Error(Errors.MISSING_MANAGE_CHANNELS) - const result = await Request_Manager.post(endpoints.GUILD_CHANNELS(data.id), { - name, - type: options.type ? Channel_Types[options.type] : undefined, - permission_overwrites: options?.permission_overwrites - ? options.permission_overwrites.map(perm => ({ - ...perm, - allow: perm.allow.map(p => Permissions[p]), - deny: perm.deny.map(p => Permissions[p]) - })) - : undefined, - ...options - }) as Channel_Create_Payload + presences: new Map(data.presences.map((p) => [p.user.id, p])), - const channel = create_channel(result) - guild.channels.set(result.id, channel) - return channel + /** Gets an array of all the channels ids that are the children of this category. */ + categoryChildrenIDs: (id: string) => data.channels.filter((c) => c.parent_id === id).map((c) => c.id), + /** The full URL of the icon from Discords CDN. Undefined when no icon is set. */ + iconURL: (size: ImageSize = 128, format?: ImageFormats) => + data.icon ? formatImageURL(endpoints.GUILD_ICON(data.id, data.icon), size, format) : undefined, + /** The full URL of the splash from Discords CDN. Undefined if no splash is set. */ + splashURL: (size: ImageSize = 128, format?: ImageFormats) => + data.splash ? formatImageURL(endpoints.GUILD_SPLASH(data.id, data.splash), size, format) : undefined, + /** The full URL of the banner from Discords CDN. Undefined if no banner is set. */ + bannerURL: (size: ImageSize = 128, format?: ImageFormats) => + data.banner ? formatImageURL(endpoints.GUILD_BANNER(data.id, data.banner), size, format) : undefined, + /** Create a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */ + createChannel: async (name: string, options: CreateChannelOptions) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_CHANNELS])) + throw new Error(Errors.MISSING_MANAGE_CHANNELS) + const result = (await RequestManager.post(endpoints.GUILD_CHANNELS(data.id), { + name, + type: options.type ? ChannelTypes[options.type] : undefined, + permission_overwrites: options?.permission_overwrites + ? options.permission_overwrites.map((perm) => ({ + ...perm, + allow: perm.allow.map((p) => Permissions[p]), + deny: perm.deny.map((p) => Permissions[p]), + })) + : undefined, + ...options, + })) as ChannelCreatePayload + + const channel = createChannel(result) + guild.channels.set(result.id, channel) + return channel }, /** Returns a list of guild channel objects. * * ⚠️ **If you need this, you are probably doing something wrong. This is not intended for use. Your channels will be cached in your guild.** */ - get_channels: () => { - return Request_Manager.get(endpoints.GUILD_CHANNELS(data.id)) + getChannels: () => { + return RequestManager.get(endpoints.GUILD_CHANNELS(data.id)) }, /** Modify the positions of channels on the guild. Requires MANAGE_CHANNELS permisison. */ - swap_channels: (channel_positions: Position_Swap[]) => { - if (channel_positions.length < 2) { + swapChannels: (channelPositions: PositionSwap[]) => { + if (channelPositions.length < 2) { throw "You must provide atleast two channels to be swapped." } - return Request_Manager.patch(endpoints.GUILD_CHANNELS(data.id), channel_positions) + return RequestManager.patch(endpoints.GUILD_CHANNELS(data.id), channelPositions) }, /** Returns a guild member object for the specified user. * * ⚠️ **If you need this, you are probably doing something wrong. This is not intended for use. Your members will be cached in your guild.** */ - get_member: (id: string) => { - return Request_Manager.get(endpoints.GUILD_MEMBER(data.id, id)) + getMember: (id: string) => { + return RequestManager.get(endpoints.GUILD_MEMBER(data.id, id)) }, /** 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. */ - create_emoji: (name: string, image: string, options: Create_Emojis_Options) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_EMOJIS])) - throw new Error(Errors.MISSING_MANAGE_EMOJIS) - return Request_Manager.post(endpoints.GUILD_EMOJIS(data.id), { + createEmoji: (name: string, image: string, options: CreateEmojisOptions) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_EMOJIS])) throw new Error(Errors.MISSING_MANAGE_EMOJIS) + return RequestManager.post(endpoints.GUILD_EMOJIS(data.id), { ...options, name, - image + image, }) }, /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. */ - edit_emoji: (id: string, options: Edit_Emojis_Options) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_EMOJIS])) - throw new Error(Errors.MISSING_MANAGE_EMOJIS) - return Request_Manager.patch(endpoints.GUILD_EMOJI(data.id, id), { + editEmoji: (id: string, options: EditEmojisOptions) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_EMOJIS])) throw new Error(Errors.MISSING_MANAGE_EMOJIS) + return RequestManager.patch(endpoints.GUILD_EMOJI(data.id, id), { name: options.name, - roles: options.roles + roles: options.roles, }) }, /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns 204 No Content on success. */ - delete_emoji: (id: string, reason?: string) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_EMOJIS])) - throw new Error(Errors.MISSING_MANAGE_EMOJIS) - return Request_Manager.delete(endpoints.GUILD_EMOJI(data.id, id), { reason }) + deleteEmoji: (id: string, reason?: string) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_EMOJIS])) throw new Error(Errors.MISSING_MANAGE_EMOJIS) + return RequestManager.delete(endpoints.GUILD_EMOJI(data.id, id), { reason }) }, /** Create a new role for the guild. Requires the MANAGE_ROLES permission. */ - create_role: async (options: Create_Role_Options, reason?: string) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_ROLES])) - throw new Error(Errors.MISSING_MANAGE_ROLES) - const role_data = await Request_Manager.post(endpoints.GUILD_ROLES(data.id), { + createRole: async (options: CreateRoleOptions, reason?: string) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) + const role_data = await RequestManager.post(endpoints.GUILD_ROLES(data.id), { ...options, - permissions: options.permissions?.map(perm => Permissions[perm]), - reason + permissions: options.permissions?.map((perm) => Permissions[perm]), + reason, }) - const role = create_role(role_data as Role_Data) - guild.roles().set(role_data.id, role) + const role = createRole(role_data as RoleData) + guild.roles.set(role_data.id, role) return role }, /** Edit a guild role. Requires the MANAGE_ROLES permission. */ - edit_role: (id: string, options: Create_Role_Options) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_ROLES])) - throw new Error(Errors.MISSING_MANAGE_ROLES) - return Request_Manager.patch(endpoints.GUILD_ROLE(data.id, id), options) + editRole: (id: string, options: CreateRoleOptions) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) + return RequestManager.patch(endpoints.GUILD_ROLE(data.id, id), options) }, /** Delete a guild role. Requires the MANAGE_ROLES permission. */ - delete_role: (id: string) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_ROLES])) - throw new Error(Errors.MISSING_MANAGE_ROLES) - return Request_Manager.delete(endpoints.GUILD_ROLE(data.id, id)) + deleteRole: (id: string) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) + return RequestManager.delete(endpoints.GUILD_ROLE(data.id, id)) }, /** Returns a list of role objects for the guild. * * ⚠️ **If you need this, you are probably doing something wrong. This is not intended for use. Your roles will be cached in your guild.** */ - get_roles: () => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_ROLES])) - throw new Error(Errors.MISSING_MANAGE_ROLES) - return Request_Manager.get(endpoints.GUILD_ROLES(data.id)) + getRoles: () => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) + return RequestManager.get(endpoints.GUILD_ROLES(data.id)) }, /** Modify the positions of a set of role objects for the guild. Requires the MANAGE_ROLES permission. */ - swap_roles: (rolePositons: Position_Swap) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_ROLES])) - throw new Error(Errors.MISSING_MANAGE_ROLES) - return Request_Manager.patch(endpoints.GUILD_ROLES(data.id), rolePositons) + swapRoles: (rolePositons: PositionSwap) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) + return RequestManager.patch(endpoints.GUILD_ROLES(data.id), rolePositons) }, /** Check how many members would be removed from the server in a prune operation. Requires the KICK_MEMBERS permission */ - get_prune_count: async (days: number) => { + getPruneCount: async (days: number) => { if (days < 1) throw new Error(Errors.PRUNE_MIN_DAYS) - if (!bot_has_permission(data.id, bot_id, [Permissions.KICK_MEMBERS])) - throw new Error(Errors.MISSING_KICK_MEMBERS) - const result = (await Request_Manager.get(endpoints.GUILD_PRUNE(data.id), { days })) as PrunePayload + if (!botHasPermission(data.id, botID, [Permissions.KICK_MEMBERS])) throw new Error(Errors.MISSING_KICK_MEMBERS) + const result = (await RequestManager.get(endpoints.GUILD_PRUNE(data.id), { days })) as PrunePayload return result.pruned }, /** Begin pruning all members in the given time period */ - prune_members: (days: number) => { + pruneMembers: (days: number) => { if (days < 1) throw new Error(Errors.PRUNE_MIN_DAYS) - if (!bot_has_permission(data.id, bot_id, [Permissions.KICK_MEMBERS])) - throw new Error(Errors.MISSING_KICK_MEMBERS) - return Request_Manager.post(endpoints.GUILD_PRUNE(data.id), { days }) + if (!botHasPermission(data.id, botID, [Permissions.KICK_MEMBERS])) throw new Error(Errors.MISSING_KICK_MEMBERS) + return RequestManager.post(endpoints.GUILD_PRUNE(data.id), { days }) }, // TODO: REQUEST THIS OVER WEBSOCKET WITH GET_GUILD_MEMBERS ENDPOINT // fetch_all_members: () => { // }, /** Returns the audit logs for the guild. Requires VIEW AUDIT LOGS permission */ - get_audit_logs: (options: Get_Audit_Logs_Options) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.VIEW_AUDIT_LOG])) + getAuditLogs: (options: GetAuditLogsOptions) => { + if (!botHasPermission(data.id, botID, [Permissions.VIEW_AUDIT_LOG])) throw new Error(Errors.MISSING_VIEW_AUDIT_LOG) - return Request_Manager.get(endpoints.GUILD_AUDIT_LOGS(data.id), { + return RequestManager.get(endpoints.GUILD_AUDIT_LOGS(data.id), { ...options, - limit: options.limit && options.limit >= 1 && options.limit <= 100 ? options.limit : 50 + limit: options.limit && options.limit >= 1 && options.limit <= 100 ? options.limit : 50, }) }, /** Returns the guild embed object. Requires the MANAGE_GUILD permission. */ - get_embed: () => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.get(endpoints.GUILD_EMBED(data.id)) + getEmbed: () => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.get(endpoints.GUILD_EMBED(data.id)) }, /** Modify a guild embed object for the guild. Requires the MANAGE_GUILD permission. */ - edit_embed: (enabled: boolean, channel_id?: string | null) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.patch(endpoints.GUILD_EMBED(data.id), { enabled, channel_id }) + editEmbed: (enabled: boolean, channel_id?: string | null) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.patch(endpoints.GUILD_EMBED(data.id), { enabled, channel_id }) }, /** Returns the code and uses of the vanity url for this server if it is enabled. Requires the MANAGE_GUILD permission. */ - get_vanity_url: () => { - return Request_Manager.get(endpoints.GUILD_VANITY_URL(data.id)) + getVanityURL: () => { + return RequestManager.get(endpoints.GUILD_VANITY_URL(data.id)) }, /** Returns a list of integrations for the guild. Requires the MANAGE_GUILD permission. */ - get_integrations: () => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.get(endpoints.GUILD_INTEGRATIONS(data.id)) + getIntegrations: () => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.get(endpoints.GUILD_INTEGRATIONS(data.id)) }, /** Modify the behavior and settings of an integration object for the guild. Requires the MANAGE_GUILD permission. */ - edit_integration: (id: string, options: Edit_Integration_Options) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.patch(endpoints.GUILD_INTEGRATION(data.id, id), options) + editIntegration: (id: string, options: EditIntegrationOptions) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.patch(endpoints.GUILD_INTEGRATION(data.id, id), options) }, /** Delete the attached integration object for the guild with this id. Requires MANAGE_GUILD permission. */ - delete_integration: (id: string) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.delete(endpoints.GUILD_INTEGRATION(data.id, id)) + deleteIntegration: (id: string) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.delete(endpoints.GUILD_INTEGRATION(data.id, id)) }, /** Sync an integration. Requires teh MANAGE_GUILD permission. */ - sync_integration: (id: string) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.post(endpoints.GUILD_INTEGRATION_SYNC(data.id, id)) + syncIntegration: (id: string) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.post(endpoints.GUILD_INTEGRATION_SYNC(data.id, id)) }, /** Returns a list of ban objects for the users banned from this guild. Requires the BAN_MEMBERS permission. */ - get_bans: () => { - if (!bot_has_permission(data.id, bot_id, [Permissions.BAN_MEMBERS])) - throw new Error(Errors.MISSING_BAN_MEMBERS) - return Request_Manager.get(endpoints.GUILD_BANS(data.id)) + getBans: () => { + if (!botHasPermission(data.id, botID, [Permissions.BAN_MEMBERS])) throw new Error(Errors.MISSING_BAN_MEMBERS) + return RequestManager.get(endpoints.GUILD_BANS(data.id)) }, /** Ban a user from the guild and optionally delete previous messages sent by the user. Requires teh BAN_MEMBERS permission. */ ban: (id: string, options: BanOptions) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.BAN_MEMBERS])) - throw new Error(Errors.MISSING_BAN_MEMBERS) - return Request_Manager.put(endpoints.GUILD_BAN(data.id, id), options) + if (!botHasPermission(data.id, botID, [Permissions.BAN_MEMBERS])) throw new Error(Errors.MISSING_BAN_MEMBERS) + return RequestManager.put(endpoints.GUILD_BAN(data.id, id), options) }, /** Remove the ban for a user. REquires BAN_MEMBERS permission */ unban: (id: string) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.BAN_MEMBERS])) - throw new Error(Errors.MISSING_BAN_MEMBERS) - return Request_Manager.delete(endpoints.GUILD_BAN(data.id, id)) + if (!botHasPermission(data.id, botID, [Permissions.BAN_MEMBERS])) throw new Error(Errors.MISSING_BAN_MEMBERS) + return RequestManager.delete(endpoints.GUILD_BAN(data.id, id)) }, /** Check whether a member has certain permissions in this channel. */ - channel_has_permissions: (channel_id: string, member_id: string, permissions: Permission[]) => { - if (member_id === data.owner_id) return true + channelHasPermissions: (channelID: string, memberID: string, permissions: Permission[]) => { + if (memberID === data.owner_id) return true - const member = guild.members.get(member_id) + const member = guild.members.get(memberID) if (!member) { throw "Invalid member id provided. This member was not found in the cache. Please fetch them with getMember on guild." } - const channel = guild.channels.get(channel_id) + const channel = guild.channels.get(channelID) if (!channel) { throw "Invalid channel id provided. This channel was not found in the cache." } - let permissionBits = member.roles().reduce((bits, role_id) => { - const role = guild.roles().get(role_id) + let permissionBits = member.roles.reduce((bits, roleID) => { + const role = guild.roles.get(roleID) if (!role) return bits - bits |= role.permissions() + bits |= role.permissions return bits }, 0) - // channel.permission_overwrites()?.forEach(overwrite => { - // permissionBits = (permissionBits & ~overwrite.deny) | overwrite.allow - // }) - if (permissionBits & Permissions.ADMINISTRATOR) return true - return permissions.every(permission => permissionBits & Permissions[permission]) + return permissions.every((permission) => permissionBits & Permissions[permission]) }, /** Modify a guilds settings. Requires the MANAGE_GUILD permission. */ - edit: (options: Guild_Edit_Options) => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.patch(endpoints.GUILD(data.id), options) + edit: (options: GuildEditOptions) => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.patch(endpoints.GUILD(data.id), options) }, /** Get all the invites for this guild. Requires MANAGE_GUILD permission */ - get_invites: () => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_GUILD])) - throw new Error(Errors.MISSING_MANAGE_GUILD) - return Request_Manager.get(endpoints.GUILD_INVITES(data.id)) + getInvites: () => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_GUILD])) throw new Error(Errors.MISSING_MANAGE_GUILD) + return RequestManager.get(endpoints.GUILD_INVITES(data.id)) }, /** Leave a guild */ leave: () => { - return Request_Manager.delete(endpoints.GUILD_LEAVE(data.id)) + return RequestManager.delete(endpoints.GUILD_LEAVE(data.id)) }, /** 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. */ - get_voice_regions: () => { - return Request_Manager.get(endpoints.GUILD_REGIONS(data.id)) + getVoiceRegions: () => { + return RequestManager.get(endpoints.GUILD_REGIONS(data.id)) }, /** Returns a list of guild webhooks objects. Requires the MANAGE_WEBHOOKs permission. */ - get_webhooks: () => { - if (!bot_has_permission(data.id, bot_id, [Permissions.MANAGE_WEBHOOKS])) + getWebhooks: () => { + if (!botHasPermission(data.id, botID, [Permissions.MANAGE_WEBHOOKS])) throw new Error(Errors.MISSING_MANAGE_WEBHOOKS) - return Request_Manager.get(endpoints.GUILD_WEBHOOKS(data.id)) - } + return RequestManager.get(endpoints.GUILD_WEBHOOKS(data.id)) + }, } return guild } + +export type Guild = ReturnType diff --git a/structures/member.ts b/structures/member.ts index 666253b3d..286937358 100644 --- a/structures/member.ts +++ b/structures/member.ts @@ -1,98 +1,75 @@ -import { bot_id } from "../module/client.ts" +import { botID } from "../module/client.ts" import { endpoints } from "../constants/discord.ts" -import { format_image_url } from "../utils/cdn.ts" -import { Member_Create_Payload, Edit_Member_Options } from "../types/member.ts" -import { Image_Size, Image_Formats } from "../types/cdn.ts" +import { formatImageURL } from "../utils/cdn.ts" +import { MemberCreatePayload, EditMemberOptions } from "../types/member.ts" +import { ImageSize, ImageFormats } from "../types/cdn.ts" import { Permission, Permissions } from "../types/permission.ts" -import { Role_Data } from "../types/role.ts" -import { member_has_permission, bot_has_permission } from "../utils/permissions.ts" +import { RoleData } from "../types/role.ts" +import { memberHasPermission, botHasPermission } from "../utils/permissions.ts" import { Errors } from "../types/errors.ts" -import { Request_Manager } from "../module/request_manager.ts" +import { RequestManager } from "../module/requestManager.ts" -export const create_member = ( - data: Member_Create_Payload, - guild_id: string, - role_data: Role_Data[], - owner_id: string -) => ({ +export const createMember = (data: MemberCreatePayload, guildID: string, roleData: RoleData[], ownerID: string) => ({ + ...data, /** The complete raw data from the member create payload */ - raw: () => data, - /** The unique user id */ - id: () => data.user.id, - /** The user's guild nickname if one is set. */ - roles: () => data.roles, - /** Array of role ids that the member has */ - nick: () => data.nick, + raw: data, /** When the user joined the guild */ - joined_at: () => Date.parse(data.joined_at), + joinedAt: Date.parse(data.joined_at), /** When the user used their nitro boost on the server. */ - premium_since: () => (data.premium_since ? Date.parse(data.premium_since) : undefined), - /** Whether the user is deafened in voice channels */ - deaf: () => data.deaf, - /** Whether the user is muted in voice channels */ - mute: () => data.mute, - /** The username of the this member. */ - username: () => data.user.username, - /** The 4 digit unique identifier */ - discriminator: () => data.user.discriminator, + premiumSince: data.premium_since ? Date.parse(data.premium_since) : undefined, /** The full username#discriminator */ - tag: () => `${data.user.username}#${data.user.discriminator}`, - /** The users custom avatar or the default avatar */ - avatar_url: (size: Image_Size = 128, format?: Image_Formats) => - data.user.avatar - ? format_image_url(endpoints.USER_AVATAR(data.user.id, data.user.avatar), size, format) - : endpoints.USER_DEFAULT_AVATAR(Number(data.user.discriminator) % 5), + tag: `${data.user.username}#${data.user.discriminator}`, /** The user mention with nickname if possible */ - mention: () => `<@!${data.user.id}>`, - /** Whether the member is a bot */ - bot: () => data.user.bot, + mention: `<@!${data.user.id}>`, + + /** The users custom avatar or the default avatar */ + avatarURL: (size: ImageSize = 128, format?: ImageFormats) => + data.user.avatar + ? formatImageURL(endpoints.USER_AVATAR(data.user.id, data.user.avatar), size, format) + : endpoints.USER_DEFAULT_AVATAR(Number(data.user.discriminator) % 5), /** Add a role to the member */ - add_role: (role_id: string, reason?: string) => { + addRole: (roleID: string, reason?: string) => { // TODO: check if the bots highest role is above this one - if (!bot_has_permission(guild_id, bot_id, [Permissions.MANAGE_ROLES])) - throw new Error(Errors.MISSING_MANAGE_ROLES) - return Request_Manager.put(endpoints.GUILD_MEMBER_ROLE(guild_id, data.user.id, role_id), { reason }) + if (!botHasPermission(guildID, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) + return RequestManager.put(endpoints.GUILD_MEMBER_ROLE(guildID, data.user.id, roleID), { reason }) }, /** Remove a role from the member */ - remove_role: (role_id: string, reason?: string) => { + remove_role: (roleID: string, reason?: string) => { // TODO: check if the bots highest role is above this role - if (!bot_has_permission(guild_id, bot_id, [Permissions.MANAGE_ROLES])) - throw new Error(Errors.MISSING_MANAGE_ROLES) - return Request_Manager.delete(endpoints.GUILD_MEMBER_ROLE(guild_id, data.user.id, role_id), { reason }) + if (!botHasPermission(guildID, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) + return RequestManager.delete(endpoints.GUILD_MEMBER_ROLE(guildID, data.user.id, roleID), { reason }) }, /** Kick a member from the server */ kick: (reason?: string) => { // TODO: Check if the bot is above the user so it is capable of kicking - if (!bot_has_permission(guild_id, bot_id, [Permissions.KICK_MEMBERS])) - throw new Error(Errors.MISSING_KICK_MEMBERS) - return Request_Manager.delete(endpoints.GUILD_MEMBER(guild_id, data.user.id), { reason }) + if (!botHasPermission(guildID, botID, [Permissions.KICK_MEMBERS])) throw new Error(Errors.MISSING_KICK_MEMBERS) + return RequestManager.delete(endpoints.GUILD_MEMBER(guildID, data.user.id), { reason }) }, /** Edit the member */ - edit: (options: Edit_Member_Options) => { + edit: (options: EditMemberOptions) => { if (options.nick) { if (options.nick.length > 32) throw new Error(Errors.NICKNAMES_MAX_LENGTH) - if (!bot_has_permission(guild_id, bot_id, [Permissions.MANAGE_NICKNAMES])) + if (!botHasPermission(guildID, botID, [Permissions.MANAGE_NICKNAMES])) throw new Error(Errors.MISSING_MANAGE_NICKNAMES) } - if (options.roles && !bot_has_permission(guild_id, bot_id, [Permissions.MANAGE_ROLES])) + if (options.roles && !botHasPermission(guildID, botID, [Permissions.MANAGE_ROLES])) throw new Error(Errors.MISSING_MANAGE_ROLES) if (options.mute) { // TODO: This should check if the member is in a voice channel - if (!bot_has_permission(guild_id, bot_id, [Permissions.MUTE_MEMBERS])) - throw new Error(Errors.MISSING_MUTE_MEMBERS) + if (!botHasPermission(guildID, botID, [Permissions.MUTE_MEMBERS])) throw new Error(Errors.MISSING_MUTE_MEMBERS) } - if (options.deaf && !bot_has_permission(guild_id, bot_id, [Permissions.DEAFEN_MEMBERS])) + if (options.deaf && !botHasPermission(guildID, botID, [Permissions.DEAFEN_MEMBERS])) throw new Error(Errors.MISSING_DEAFEN_MEMBERS) // TODO: if channel id is provided check if the bot has CONNECT and MOVE in channel and current channel - return Request_Manager.patch(endpoints.GUILD_MEMBER(guild_id, data.user.id), options) + return RequestManager.patch(endpoints.GUILD_MEMBER(guildID, data.user.id), options) }, /** Checks if the member has this permission. If the member is an owner or has admin perms it will always be true. */ - has_permissions: (permissions: Permission[]) => { - return member_has_permission(data.user.id, owner_id, role_data, data.roles, permissions) - } + hasPermissions: (permissions: Permission[]) => { + return memberHasPermission(data.user.id, ownerID, roleData, data.roles, permissions) + }, }) diff --git a/structures/message.ts b/structures/message.ts index f4170435c..783897d44 100644 --- a/structures/message.ts +++ b/structures/message.ts @@ -1,112 +1,91 @@ -import { Message_Create_Options } from "../types/message.ts" +import { MessageCreateOptions } from "../types/message.ts" import { endpoints } from "../constants/discord.ts" import { MessageContent } from "../types/channel.ts" -import { cache } from "../utils/cache.ts" -import { create_user } from "./user.ts" -import { User_Payload } from "../types/guild.ts" -import { Channel } from "../types/return-type.ts" -import { bot_has_permission } from "../utils/permissions.ts" +import { createUser } from "./user.ts" +import { UserPayload } from "../types/guild.ts" +import { botHasPermission } from "../utils/permissions.ts" import { Errors } from "../types/errors.ts" import { Permissions } from "../types/permission.ts" -import { Request_Manager } from "../module/request_manager.ts" -import { bot_id } from "../module/client.ts" +import { RequestManager } from "../module/requestManager.ts" +import { botID } from "../module/client.ts" +import { cache } from "../utils/cache.ts" -export const create_message = (data: Message_Create_Options) => ({ - raw: () => data, - author: () => create_user({ ...data.author, avatar: data.author.avatar || "" }), - id: () => data.id, - type: () => data.type, - timestamp: () => Date.parse(data.timestamp), - content: () => data.content, - reactions: () => data.reactions || [], - guild_id: () => data.guild_id, - webhook_id: () => data.webhook_id, - mentions_everyone: () => data.mentions_everyone, - mentions: () => data.mentions.map(m => m.member.id), - mention_roles: () => data.mention_roles, - mention_channels: () => data.mention_channels?.map(c => c.id) || [], - pinned: () => data.pinned, - edited_timestamp: () => (data.edited_timestamp ? Date.parse(data.edited_timestamp) : undefined), - tts: () => data.tts, - attachments: () => data.attachments, - embeds: () => data.embeds, - activity: () => data.activity, - applications: () => data.applications, - message_reference: () => ({ - channel_id: data.message_reference?.channel_id, - guild_id: data.message_reference?.guild_id, - message_id: data.message_reference?.message_id - }), - flags: () => data.flags || 0, - channel_id: () => data.channel_id, - channel: () => cache.channels.get(data.channel_id) as Channel, +export function createMessage(data: MessageCreateOptions) { + return { + ...data, + raw: data, + author: createUser({ ...data.author, avatar: data.author.avatar || "" }), + timestamp: Date.parse(data.timestamp), + editedTimestamp: data.edited_timestamp ? Date.parse(data.edited_timestamp) : undefined, + channel: cache.channels.get(data.channel_id), - /** Delete a message */ - delete: (reason?: string) => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_MESSAGES])) - throw new Error(Errors.MISSING_MANAGE_MESSAGES) - if (data.author.id !== bot_id) { - } + /** Delete a message */ + delete: (reason?: string) => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_MESSAGES])) + throw new Error(Errors.MISSING_MANAGE_MESSAGES) + if (data.author.id !== botID) { + } - Request_Manager.delete(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id), { reason }) - }, - /** Pin a message in a channel. Requires MANAGE_MESSAGES. Max pins allowed in a channel = 50. */ - pin: () => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_MESSAGES])) - throw new Error(Errors.MISSING_MANAGE_MESSAGES) - Request_Manager.put(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id)) - }, - unpin: () => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_MESSAGES])) - throw new Error(Errors.MISSING_MANAGE_MESSAGES) - Request_Manager.delete(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id)) - }, - /** Create a reaction for the message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. Requires READ_MESSAGE_HISTORY and ADD_REACTIONS */ - add_reaction: (reaction: string) => { - Request_Manager.put(endpoints.CHANNEL_MESSAGE_REACTION_ME(data.channel_id, data.id, reaction)) - }, - /** Removes a reaction from the bot on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ - remove_reaction: (reaction: string) => { - Request_Manager.delete(endpoints.CHANNEL_MESSAGE_REACTION_ME(data.channel_id, data.id, reaction)) - }, - /** Removes all reactions for all emojis on this message. */ - remove_all_reactions: () => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_MESSAGES])) - throw new Error(Errors.MISSING_MANAGE_MESSAGES) - Request_Manager.delete(endpoints.CHANNEL_MESSAGE_REACTIONS(data.channel_id, data.id)) - }, - /** Removes all reactions for a single emoji on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ - remove_reaction_emoji: (reaction: string) => { - if (data.guild_id && !bot_has_permission(data.guild_id, bot_id, [Permissions.MANAGE_MESSAGES])) - throw new Error(Errors.MISSING_MANAGE_MESSAGES) - Request_Manager.delete(endpoints.CHANNEL_MESSAGE_REACTION(data.channel_id, data.id, reaction)) - }, - /** Get a list of users that reacted with this emoji. */ - get_reactions: async (reaction: string) => { - const result = (await Request_Manager.get( - endpoints.CHANNEL_MESSAGE_REACTION(data.channel_id, data.id, reaction) - )) as User_Payload[] - return result.map(res => create_user(res)) - }, - /** Edit the message. */ - edit: async (content: string | MessageContent) => { - if (data.author.id !== bot_id) throw "You can only edit a message that was sent by the bot." + RequestManager.delete(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id), { reason }) + }, + /** Pin a message in a channel. Requires MANAGE_MESSAGES. Max pins allowed in a channel = 50. */ + pin: () => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_MESSAGES])) + throw new Error(Errors.MISSING_MANAGE_MESSAGES) + RequestManager.put(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id)) + }, + unpin: () => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_MESSAGES])) + throw new Error(Errors.MISSING_MANAGE_MESSAGES) + RequestManager.delete(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id)) + }, + /** Create a reaction for the message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. Requires READ_MESSAGE_HISTORY and ADD_REACTIONS */ + addReaction: (reaction: string) => { + RequestManager.put(endpoints.CHANNEL_MESSAGE_REACTION_ME(data.channel_id, data.id, reaction)) + }, + /** Removes a reaction from the bot on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ + removeReaction: (reaction: string) => { + RequestManager.delete(endpoints.CHANNEL_MESSAGE_REACTION_ME(data.channel_id, data.id, reaction)) + }, + /** Removes all reactions for all emojis on this message. */ + removeAllReactions: () => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_MESSAGES])) + throw new Error(Errors.MISSING_MANAGE_MESSAGES) + RequestManager.delete(endpoints.CHANNEL_MESSAGE_REACTIONS(data.channel_id, data.id)) + }, + /** Removes all reactions for a single emoji on this message. Reaction takes the form of **name:id** for custom guild emoji, or Unicode characters. */ + removeReactionEmoji: (reaction: string) => { + if (data.guild_id && !botHasPermission(data.guild_id, botID, [Permissions.MANAGE_MESSAGES])) + throw new Error(Errors.MISSING_MANAGE_MESSAGES) + RequestManager.delete(endpoints.CHANNEL_MESSAGE_REACTION(data.channel_id, data.id, reaction)) + }, + /** Get a list of users that reacted with this emoji. */ + getReactions: async (reaction: string) => { + const result = (await RequestManager.get( + endpoints.CHANNEL_MESSAGE_REACTION(data.channel_id, data.id, reaction) + )) as UserPayload[] + return result.map((res) => createUser(res)) + }, + /** Edit the message. */ + edit: async (content: string | MessageContent) => { + if (data.author.id !== botID) throw "You can only edit a message that was sent by the bot." - if (typeof content === "string") content = { content } + if (typeof content === "string") content = { content } - if (data.guild_id) { - if (!bot_has_permission(data.guild_id, bot_id, [Permissions.SEND_MESSAGES])) - throw new Error(Errors.MISSING_SEND_MESSAGES) + if (data.guild_id) { + if (!botHasPermission(data.guild_id, botID, [Permissions.SEND_MESSAGES])) + throw new Error(Errors.MISSING_SEND_MESSAGES) - if (content.tts && !bot_has_permission(data.guild_id, bot_id, [Permissions.SEND_TTS_MESSAGES])) - throw new Error(Errors.MISSING_SEND_TTS_MESSAGE) - } + if (content.tts && !botHasPermission(data.guild_id, botID, [Permissions.SEND_TTS_MESSAGES])) + throw new Error(Errors.MISSING_SEND_TTS_MESSAGE) + } - if (content.content && content.content.length > 2000) throw new Error(Errors.MESSAGE_MAX_LENGTH) + if (content.content && content.content.length > 2000) throw new Error(Errors.MESSAGE_MAX_LENGTH) - const result = await Request_Manager.patch(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id), content) - return create_message(result) + const result = await RequestManager.patch(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id), content) + return createMessage(result) + }, } -}) +} -export type Message = ReturnType +export type Message = ReturnType diff --git a/structures/queue.ts b/structures/queue.ts deleted file mode 100644 index eae35db1d..000000000 --- a/structures/queue.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { DiscordPayload } from "../types/discord.ts"; -import Gateway from "../module/gateway.ts"; - -export abstract class ActionQueue { - protected actions: Action[] = []; - - push (action: Action) { - if (this.shouldDispatchImmediately(action)) { - this.dispatch(action); - } else { - this.actions.push(action); - } - } - - async dispatchAll () { - let index = 0; - for (const action of this.actions) { - if (this.shouldDispatchImmediately(action)) { - this.actions.splice(index, 1); - await this.dispatch(action); - index++; - } - } - } - - abstract dispatch (action: Action): void | Promise; - abstract shouldDispatchImmediately (action: Action): boolean; -} - -export interface RatelimitDetails { - /** The number of requests that can be made */ - limit: number; - - /** The number of remaining requests that can be made */ - remaining: number; - - /** Epoch time (seconds since 00:00:00 UTC on January 1, 1970) at which the rate limit resets */ - reset: number; - - /** A unique string denoting the rate limit being encountered (non-inclusive of major parameters in the route path) */ - bucket: string; - - /** Total time (in seconds) of when the current rate limit bucket will reset. */ - resetAfter: number; -} - -export class RatelimitedActionQueue extends ActionQueue { - protected lastRatelimitDetails?: RatelimitDetails; - - constructor (protected gateway: Gateway) { - super(); - } - - dispatch (action: DiscordPayload) { - this.gateway.sendObject(action); - } - - shouldDispatchImmediately () { - return this.lastRatelimitDetails?.limit !== 0; - } -} diff --git a/structures/role.ts b/structures/role.ts index 030050379..ef290d336 100644 --- a/structures/role.ts +++ b/structures/role.ts @@ -1,26 +1,11 @@ -import { Role_Data } from '../types/role.ts' +import { RoleData } from "../types/role.ts" -export const create_role = (data: Role_Data) => ({ +export const createRole = (data: RoleData) => ({ + ...data, /** The entire raw Role data */ - raw: () => data, - /** role id */ - id: () => data.id, - /** role name */ - name: () => data.name, - /** integer representation of hexadecimal color code */ - color: () => data.color, - /** if this role is pinned in the user listing */ - hoist: () => data.hoist, - /** position of this role */ - position: () => data.position, - /** permission bit set */ - permissions: () => data.permissions, - /** whether this role is managed by an integration */ - managed: () => data.managed, - /** whether this role is mentionable */ - mentionable: () => data.mentionable, + raw: data, /** The @ mention of the role in a string. */ - mention: () => `<@&${data.id}>` + mention: `<@&${data.id}>`, }) -export type Role = ReturnType +export type Role = ReturnType diff --git a/structures/user.ts b/structures/user.ts index fdd66e9dd..171c1b9a6 100644 --- a/structures/user.ts +++ b/structures/user.ts @@ -1,29 +1,21 @@ -import { format_image_url } from '../utils/cdn.ts' -import { endpoints } from '../constants/discord.ts' -import { Image_Size, Image_Formats } from '../types/cdn.ts' -import { User_Payload } from '../types/guild.ts' +import { formatImageURL } from "../utils/cdn.ts" +import { endpoints } from "../constants/discord.ts" +import { ImageSize, ImageFormats } from "../types/cdn.ts" +import { UserPayload } from "../types/guild.ts" export const enum PremiumType { NitroClassic = 1, - Nitro + Nitro, } -export const create_user = (data: User_Payload) => ({ - id: () => data.id, - mention: () => `<@!${data.id}>`, - username: () => data.username, - discriminator: () => data.discriminator, - tag: () => `${data.username}#${data.discriminator}`, - avatar: () => data.avatar, - avatar_url: (size: Image_Size = 128, format?: Image_Formats) => +export const createUser = (data: UserPayload) => ({ + ...data, + mention: `<@!${data.id}>`, + tag: `${data.username}#${data.discriminator}`, + avatarURL: (size: ImageSize = 128, format?: ImageFormats) => data.avatar - ? format_image_url(endpoints.USER_AVATAR(data.id, data.avatar), size, format) + ? formatImageURL(endpoints.USER_AVATAR(data.id, data.avatar), size, format) : endpoints.USER_DEFAULT_AVATAR(Number(data.discriminator) % 5), - bot: () => data.bot, - system: () => data.system, - mfa_enabled: () => data.mfa_enabled, - flags: () => data.flags, - premium_type: () => data.premium_type }) -export type User = ReturnType +export type User = ReturnType diff --git a/types/activity.ts b/types/activity.ts index e1a492fc2..540c05966 100644 --- a/types/activity.ts +++ b/types/activity.ts @@ -1,20 +1,17 @@ -import { Timestamps } from "../types/discord.ts"; +import { Timestamps } from "../types/discord.ts" export interface ActivityPayload { - /** The activity's name */ - name: string; - - /** */ - type: number; - url?: string; - created_at: number; - timestamps: Timestamps; - details?: string; + name: string + type: number + url?: string + created_at: number + timestamps: Timestamps + details?: string } export enum ActivityType { - Game, - Streaming, - Listening, - Custom = 4 -} \ No newline at end of file + Game, + Streaming, + Listening, + Custom = 4, +} diff --git a/types/cdn.ts b/types/cdn.ts index 53f878e8e..ac8716db2 100644 --- a/types/cdn.ts +++ b/types/cdn.ts @@ -1,2 +1,2 @@ -export type Image_Size = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 -export type Image_Formats = 'jpg' | 'jpeg' | 'png' | 'webp' | 'gif' +export type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 +export type ImageFormats = "jpg" | "jpeg" | "png" | "webp" | "gif" diff --git a/types/channel.ts b/types/channel.ts index 22d7a3014..94a287201 100644 --- a/types/channel.ts +++ b/types/channel.ts @@ -1,7 +1,7 @@ import { Raw_Overwrite, Overwrite } from "./guild.ts" import { Embed } from "./message.ts" -export interface Channel_Edit_Options { +export interface ChannelEditOptions { /** 2-100 character channel name. All */ name?: string /** the position of the channel in the left-hand listing All */ @@ -47,7 +47,7 @@ export interface Base_Channel_Create { last_pin_timestamp?: string } -export interface Channel_Create_Payload extends Base_Channel_Create { +export interface ChannelCreatePayload extends Base_Channel_Create { /** The id of this channel */ id: string /** The type of the channel */ @@ -56,16 +56,16 @@ export interface Channel_Create_Payload extends Base_Channel_Create { permission_overwrites?: Raw_Overwrite[] } -export interface Channel_Create_Options extends Base_Channel_Create { +export interface CreateChannelOptions extends Base_Channel_Create { /** The type of the channel */ - type: Channel_Types + type: ChannelTypes /** Explicit permission overwrites for members and roles */ permission_overwrites?: Overwrite[] } export type Channel_Type = 0 | 1 | 2 | 4 | 5 | 6 -export enum Channel_Types { +export enum ChannelTypes { /** A text channel within a server */ GUILD_TEXT, /** A direct message between users */ @@ -79,7 +79,7 @@ export enum Channel_Types { /** A channel that users can follow and crosspost into their own server. */ GUILD_NEWS, /** A channel in which game developers can sell their game on Discord. */ - GUILD_STORE + GUILD_STORE, } // export interface File_Content { @@ -102,27 +102,27 @@ export interface MessageContent { payload_json?: string } -export interface Get_Messages { +export interface GetMessages { /** Max number of messages to return(1-100). Defaults to 50. */ limit?: number } -export interface Get_Messages_After extends Get_Messages { +export interface GetMessagesAfter extends GetMessages { /** Get messages after this message id */ after: string } -export interface Get_Messages_Before extends Get_Messages { +export interface GetMessagesBefore extends GetMessages { /** Get messages before this message id */ before: string } -export interface Get_Messages_Around extends Get_Messages { +export interface GetMessagesAround extends GetMessages { /** Get messages around this message id. */ around: string } -export interface Create_Invite_Options { +export interface CreateInviteOptions { /** Duration of invite in seconds before expiry, or 0 for never. Defaults to 86400 (24 hours) */ max_age: number /** Max number of uses or 0 for unlimited. Default 0 */ diff --git a/types/discord.ts b/types/discord.ts index c0e7e8664..be346a3e8 100644 --- a/types/discord.ts +++ b/types/discord.ts @@ -1,7 +1,7 @@ import { Activity } from "./message.ts" import { Client_Status_Payload } from "./presence.ts" import { Partial_User } from "./guild.ts" -import { Member_Create_Payload } from "./member.ts" +import { MemberCreatePayload } from "./member.ts" export interface DiscordPayload { /** OP code for the payload */ @@ -192,12 +192,12 @@ export interface Status { status: StatusType } -export interface Webhook_Update_Payload { +export interface WebhookUpdatePayload { channel_id: string guild_id: string } -export interface Presence_Update_Payload { +export interface PresenceUpdatePayload { /** The user presence is being updated for. */ user: Partial_User /** The roles this user is in */ @@ -218,7 +218,7 @@ export interface Presence_Update_Payload { nick?: string | null } -export interface Typing_Start_Payload { +export interface TypingStartPayload { /** The id of the channel */ channel_id: string /** The id of the guild */ @@ -228,10 +228,10 @@ export interface Typing_Start_Payload { /** The unix time in seconds of when the user started typing */ timestamp: number /** The member who started typing if this happened in a guild */ - member?: Member_Create_Payload + member?: MemberCreatePayload } -export interface Voice_State_Update_Payload { +export interface VoiceStateUpdatePayload { /** The guild id this voice state is for */ guild_id?: string /** The channel id this user is connected to */ @@ -239,7 +239,7 @@ export interface Voice_State_Update_Payload { /** The user id this voice state is for */ user_id: string /** The guild member this voice state is for */ - member?: Member_Create_Payload + member?: MemberCreatePayload /** The session id for this voice state */ session_id: string /** Whether this user is deafened by the server */ diff --git a/types/guild.ts b/types/guild.ts index 5ca83c960..f54e4020f 100644 --- a/types/guild.ts +++ b/types/guild.ts @@ -1,67 +1,67 @@ import { Emoji, StatusType } from "./discord.ts" import { User } from "../structures/user.ts" import { Permission } from "./permission.ts" -import { Role_Data } from "./role.ts" -import { Member_Create_Payload } from "./member.ts" +import { RoleData } from "./role.ts" +import { MemberCreatePayload } from "./member.ts" import { Activity } from "./message.ts" import { Client_Status_Payload } from "./presence.ts" -import { Channel_Create_Payload } from "./channel.ts" +import { ChannelCreatePayload } from "./channel.ts" -export interface Guild_Role_Payload { +export interface GuildRolePayload { /** The id of the guild */ guild_id: string /** The role object of the role created, deleted, or updated */ - role: Role_Data + role: RoleData } -export interface Guild_Member_Chunk_Payload { +export interface GuildMemberChunkPayload { /** The id of the guild */ guild_id: string /** The set of guild members */ - members: Member_Create_Payload[] + members: MemberCreatePayload[] /** if passing an invalid id, it will be found here */ not_found?: string[] /** if passing true, presences of the members will be here */ presences?: Presence[] } -export interface Guild_Member_Update_Payload { +export interface GuildMemberUpdatePayload { /** The id of the guild */ guild_id: string /** The user's role ids */ roles: string[] /** The user */ - user: User_Payload + user: UserPayload /** The nickname of the user in the guild */ nick: string /** When the user used their nitro boost on the guild. */ premium_since: string | null } -export interface Guild_Member_Add_Payload extends Member_Create_Payload { +export interface GuildMemberAddPayload extends MemberCreatePayload { guild_id: string } -export interface Guild_Emojis_Update_Payload { +export interface GuildEmojisUpdatePayload { guild_id: string emojis: Emoji[] } -export interface Guild_Ban_Payload { +export interface GuildBanPayload { /** The id of the guild */ guild_id: string /** The banned user. Not a member as you can ban users outside of your guild. */ - user: User_Payload + user: UserPayload } -export interface Guild_Delete_Payload { +export interface GuildDeletePayload { /** The id of the guild */ id: string /** Whether this guild went unavailable. */ unavailable?: boolean } -export interface Create_Guild_Payload { +export interface CreateGuildPayload { /** The guild id */ id: string /** The guild name 2-100 characters */ @@ -85,7 +85,7 @@ export interface Create_Guild_Payload { /** The verification level required for the guild */ verification_level: number /** The roles in the guild */ - roles: Role_Data[] + roles: RoleData[] /** The custom guild emojis */ emojis: Emoji[] /** Enabled guild features */ @@ -101,12 +101,12 @@ export interface Create_Guild_Payload { /** Whether this guild is unavailable */ unavailable: boolean /** Total number of members in this guild */ - member_count: number + memberCount: number voice_states: Voice_State[] /** Users in the guild */ - members: Member_Create_Payload[] + members: MemberCreatePayload[] /** Channels in the guild */ - channels: Channel_Create_Payload[] + channels: ChannelCreatePayload[] presences: Presence[] /** The maximum amount of presences for the guild(the default value, currently 5000 is in effect when null is returned.) */ max_presences?: number | null @@ -169,14 +169,14 @@ export interface BannedUser { user: User } -export interface Position_Swap { +export interface PositionSwap { /** The unique id */ id: string /** The sorting position number. */ position: number } -export interface Guild_Edit_Options { +export interface GuildEditOptions { /** The guild name */ name?: string /** The guild voice region id */ @@ -203,7 +203,7 @@ export interface Guild_Edit_Options { system_channel_id?: string } -export interface Edit_Integration_Options { +export interface EditIntegrationOptions { /** The behavior when an integration subscription lapses. */ expire_behavior: number /** The period in seconds where the integration will ignore lapsed subscriptions */ @@ -230,7 +230,7 @@ export interface Guild_Integration { /** The grace period before expiring subscribers */ expire_grace_period: number /** The user for this integration */ - user: User_Payload + user: UserPayload /** The integration account information */ account: Account /** When this integration was last synced */ @@ -244,7 +244,7 @@ export interface Account { name: string } -export interface User_Payload { +export interface UserPayload { /** The user's id */ id: string /** the user's username, not unique across the platform */ @@ -309,12 +309,12 @@ export enum User_Flags { HOUSE_BALANCE = 1 << 8, EARLY_SUPPORTER = 1 << 9, TEAM_USER = 1 << 10, - SYSTEM = 1 << 12 + SYSTEM = 1 << 12, } export enum Nitro_Types { NITRO_CLASSIC = 1, - NITRO + NITRO, } export interface Vanity_Invite { @@ -327,7 +327,7 @@ export interface Guild_Embed { enabled: boolean } -export interface Get_Audit_Logs_Options { +export interface GetAuditLogsOptions { /** Filter the logs for actions made by this user. */ user_id?: string /** The type of audit log. */ @@ -410,7 +410,7 @@ export enum AuditLogs { MESSAGE_UNPIN, INTEGRATION_CREATE = 80, INTEGRATION_UPDATE, - INTEGRATION_DELETE + INTEGRATION_DELETE, } export type ChannelType = "text" | "dm" | "news" | "voice" | "category" | "store" @@ -460,21 +460,21 @@ export interface ChannelCreate_Options { reason?: string } -export interface Create_Emojis_Options { +export interface CreateEmojisOptions { /** The roles for which this emoji will be whitelisted. Only the users with one of these roles can use this emoji. */ roles: string[] /** The reason to have in the Audit Logs. */ reason: string } -export interface Edit_Emojis_Options { +export interface EditEmojisOptions { /** The name of the emoji */ name: string /** The roles for which this emoji will be whitelisted. Only the users with one of these roles can use this emoji. */ roles: string[] } -export interface Create_Role_Options { +export interface CreateRoleOptions { name?: string permissions?: Permission[] color?: number @@ -494,7 +494,7 @@ export interface Voice_State { /** the user id this voice state is for */ user_id: string /** the guild member this voice state is for */ - member?: Member_Create_Payload + member?: MemberCreatePayload /** the session id for this voice state */ session_id: string /** whether this user is deafened by the server */ @@ -513,7 +513,7 @@ export interface Voice_State { export interface Presence { /** The user presence is being updated for */ - user: User_Payload + user: UserPayload /** The roles this user is in */ roles: string[] /** null, or the user's current activity */ diff --git a/types/member.ts b/types/member.ts index 4bfe313d7..8be10a889 100644 --- a/types/member.ts +++ b/types/member.ts @@ -1,7 +1,7 @@ -import { create_member } from "../structures/member.ts" -import { User_Payload } from "./guild.ts" +import { createMember } from "../structures/member.ts" +import { UserPayload } from "./guild.ts" -export interface Edit_Member_Options { +export interface EditMemberOptions { /** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */ nick?: string /** Array of role ids the member is assigned. Requires MANAGE_ROLES permission. */ @@ -14,9 +14,9 @@ export interface Edit_Member_Options { channel_id?: string | null } -export interface Member_Create_Payload { +export interface MemberCreatePayload { /** The user this guild member represents */ - user: User_Payload + user: UserPayload /** The user's guild nickname if one is set. */ nick?: string /** Array of role ids that the member has */ @@ -31,4 +31,4 @@ export interface Member_Create_Payload { mute: boolean } -export type Member = ReturnType +export type Member = ReturnType diff --git a/types/message.ts b/types/message.ts index 861307829..e2a06e4f9 100644 --- a/types/message.ts +++ b/types/message.ts @@ -1,7 +1,7 @@ -import { ChannelType, User_Payload } from './guild.ts' -import { User } from '../structures/user.ts' -import { Member, Member_Create_Payload } from './member.ts' -import { Channel } from './return-type.ts' +import { ChannelType, UserPayload } from "./guild.ts" +import { User } from "../structures/user.ts" +import { Member, MemberCreatePayload } from "./member.ts" +import { Channel } from "../structures/channel.ts" export interface MentionedUser extends User { member: Member @@ -65,12 +65,12 @@ export interface Embed { } export interface Embed_Footer { - /** The text of the footer */ - text: string - /** The url of the footer icon. Only supports http(s) and attachments */ - icon_url?: string - /** A proxied url of footer icon */ - proxy_icon_url?: string + /** The text of the footer */ + text: string + /** The url of the footer icon. Only supports http(s) and attachments */ + iconURL?: string + /** A proxied url of footer icon */ + proxy_icon_url?: string } export interface Embed_Image { @@ -117,7 +117,7 @@ export interface Embed_Author { /** The url of the author */ url?: string /** The url of the author icon (supports http(s) and attachments) */ - icon_url?: string + iconURL?: string /** A proxied url of author icon */ proxy_icon_url?: string } @@ -160,7 +160,7 @@ export enum Activity_Types { JOIN = 1, SPECTATE, LISTEN, - JOIN_REQUEST = 5 + JOIN_REQUEST = 5, } export interface Activity { @@ -197,7 +197,7 @@ export enum Message_Flags { IS_CROSSPOST = 1 << 1, SUPPRESS_EMBEDS = 1 << 2, SOURCE_MESSAGE_DELETED = 1 << 3, - URGENT = 1 << 4 + URGENT = 1 << 4, } export interface Emoji { @@ -226,7 +226,7 @@ export interface Reaction_Payload { animated?: boolean } -export interface Message_Create_Options { +export interface MessageCreateOptions { /** The id of the message */ id: string /** The id of the channel the message was sent in */ @@ -234,7 +234,7 @@ export interface Message_Create_Options { /** The id of the guild the message was sent in */ guild_id?: string /** The author of this message (not guaranteed to be a valid user such as a webhook.) */ - author: User_Payload + author: UserPayload /** The member properties for this message's author. Can be partial. */ member?: Member /** The contents of the message */ @@ -284,25 +284,24 @@ export interface Base_Message_Delete_Payload { guild_id?: string } -export interface Message_Delete_Payload extends Base_Message_Delete_Payload { +export interface MessageDeletePayload extends Base_Message_Delete_Payload { /** The id of the message */ id: string } -export interface Message_Delete_Bulk_Payload extends Base_Message_Delete_Payload { +export interface MessageDeleteBulkPayload extends Base_Message_Delete_Payload { /** The ids of the messages */ ids: string[] } -export interface Message_Update_Payload { +export interface MessageUpdatePayload { /** The message id */ id: string /** The channel id */ channel_id: string } -export interface Base_Message_Reaction_Payload { - +export interface BaseMessageReactionPayload { /** The id of the channel */ channel_id: string /** The id of the message */ @@ -311,21 +310,21 @@ export interface Base_Message_Reaction_Payload { guild_id?: string } -export interface Message_Reaction_Payload extends Base_Message_Reaction_Payload { +export interface MessageReactionPayload extends BaseMessageReactionPayload { /** The id of the user */ user_id: string /** The member who reacted if this happened in a guild. Not available for MESSAGE_REACTION_REMOVE */ - member?: Member_Create_Payload + member?: MemberCreatePayload /** The emoji used to react */ emoji: Reaction_Payload } -export interface Message_Reaction_Remove_Emoji_Payload extends Base_Message_Reaction_Payload { +export interface MessageReactionRemoveEmojiPayload extends BaseMessageReactionPayload { /** The emoji that was removed. */ emoji: Reaction_Payload } export interface Partial_Message { - id: string, + id: string channel: Channel } diff --git a/types/options.ts b/types/options.ts index a758ae457..1d676ebc9 100644 --- a/types/options.ts +++ b/types/options.ts @@ -2,22 +2,23 @@ import { Properties, Emoji, DiscordPayload, - Presence_Update_Payload, - Typing_Start_Payload, - Voice_State_Update_Payload + PresenceUpdatePayload, + TypingStartPayload, + VoiceStateUpdatePayload, } from "./discord.ts" -import { Channel, Guild } from "./return-type.ts" import { User } from "../structures/user.ts" import { Member } from "./member.ts" import { Role } from "../structures/role.ts" import { Message } from "../structures/message.ts" import { Partial_Message, - Message_Reaction_Payload, + MessageReactionPayload, Reaction_Payload, - Base_Message_Reaction_Payload, - Message_Reaction_Remove_Emoji_Payload + BaseMessageReactionPayload, + MessageReactionRemoveEmojiPayload, } from "./message.ts" +import { Channel } from "../structures/channel.ts" +import { Guild } from "../structures/guild.ts" export interface Fulfilled_Client_Options { token: string @@ -26,51 +27,51 @@ export interface Fulfilled_Client_Options { intents: number } -export interface Client_Options { +export interface ClientOptions { token: string properties?: Properties compress?: boolean - bot_id: string + botID: string intents: Intents[] - event_handlers?: Event_Handlers + eventHandlers?: EventHandlers } -export interface Event_Handlers { - bot_update?: (user: User, cached_user?: User) => unknown - channel_create?: (channel: Channel) => unknown - channel_update?: (channel: Channel, cached_channel: Channel) => unknown - channel_delete?: (channel: Channel) => unknown - guild_ban_add?: (guild: Guild, user: User) => unknown - guild_ban_remove?: (guild: Guild, user: User) => unknown - guild_create?: (guild: Guild) => unknown - guild_update?: (guild: Guild, cached_guild: Guild) => unknown - guild_delete?: (guild: Guild) => unknown - guild_emojis_update?: (guild: Guild, emojis: Emoji[], cached_emojis: Emoji[]) => unknown - guild_member_add?: (guild: Guild, member: Member) => unknown - guild_member_remove?: (guild: Guild, member: Member | User) => unknown - guild_member_update?: (guild: Guild, member: Member, cached_member?: Member) => unknown +export interface EventHandlers { + botUpdate?: (user: User, cachedUser?: User) => unknown + channelCreate?: (channel: Channel) => unknown + channel_update?: (channel: Channel, cachedChannel: Channel) => unknown + channelDelete?: (channel: Channel) => unknown + guildBanAdd?: (guild: Guild, user: User) => unknown + guildBanRemove?: (guild: Guild, user: User) => unknown + guildCreate?: (guild: Guild) => unknown + guildUpdate?: (guild: Guild, cachedGuild: Guild) => unknown + guildDelete?: (guild: Guild) => unknown + guildEmojisUpdate?: (guild: Guild, emojis: Emoji[], cachedEmojis: Emoji[]) => unknown + guildMemberAdd?: (guild: Guild, member: Member) => unknown + guildMemberRemove?: (guild: Guild, member: Member | User) => unknown + guild_member_update?: (guild: Guild, member: Member, cachedMember?: Member) => unknown heartbeat?: () => unknown - message_create?: (message: Message) => unknown + messageCreate?: (message: Message) => unknown message_delete?: (message: Message | Partial_Message) => unknown - nickname_update?: (guild: Guild, member: Member, nickname: string, old_nickname?: string) => unknown - presence_update?: (data: Presence_Update_Payload) => unknown + nicknameUpdate?: (guild: Guild, member: Member, nickname: string, old_nickname?: string) => unknown + presenceUpdate?: (data: PresenceUpdatePayload) => unknown raw?: (data: DiscordPayload) => unknown ready?: () => unknown - reaction_add?: (message: Message | Message_Reaction_Payload, emoji: Reaction_Payload, user_id: string) => unknown - reaction_remove?: (message: Message | Message_Reaction_Payload, emoji: Reaction_Payload, user_id: string) => unknown - reaction_remove_all?: (data: Base_Message_Reaction_Payload) => unknown - reaction_remove_emoji?: (data: Message_Reaction_Remove_Emoji_Payload) => unknown - role_create?: (guild: Guild, role: Role) => unknown - role_delete?: (guild: Guild, role: Role) => unknown - role_update?: (guild: Guild, role: Role, cached_role: Role) => unknown + reactionAdd?: (message: Message | MessageReactionPayload, emoji: Reaction_Payload, user_id: string) => unknown + reactionRemove?: (message: Message | MessageReactionPayload, emoji: Reaction_Payload, user_id: string) => unknown + reactionRemoveAll?: (data: BaseMessageReactionPayload) => unknown + reactionRemoveEmoji?: (data: MessageReactionRemoveEmojiPayload) => unknown + roleCreate?: (guild: Guild, role: Role) => unknown + roleDelete?: (guild: Guild, role: Role) => unknown + roleUpdate?: (guild: Guild, role: Role, cached_role: Role) => unknown role_gained?: (guild: Guild, member: Member, role_id: string) => unknown role_lost?: (guild: Guild, member: Member, role_id: string) => unknown - typing_start?: (data: Typing_Start_Payload) => unknown - voice_channel_join?: (member: Member, channel_id: string) => unknown - voice_channel_leave?: (member: Member, channel_id: string) => unknown - voice_channel_switch?: (member: Member, channel_id: string, old_channel_id: string) => unknown - voice_state_update?: (member: Member, voice_state: Voice_State_Update_Payload) => unknown - webhooks_update?: (channel_id: string, guild_id: string) => unknown + typingStart?: (data: TypingStartPayload) => unknown + voiceChannelJoin?: (member: Member, channel_id: string) => unknown + voiceChannelLeave?: (member: Member, channel_id: string) => unknown + voiceChannelSwitch?: (member: Member, channel_id: string, old_channel_id: string) => unknown + voiceStateUpdate?: (member: Member, voice_state: VoiceStateUpdatePayload) => unknown + webhooksUpdate?: (channel_id: string, guild_id: string) => unknown } export enum Intents { @@ -157,5 +158,5 @@ export enum Intents { /** Enables the following events: * - TYPING_START */ - DIRECT_MESSAGE_TYPING = 1 << 14 + DIRECT_MESSAGE_TYPING = 1 << 14, } diff --git a/types/queue.ts b/types/queue.ts deleted file mode 100644 index 61058a790..000000000 --- a/types/queue.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { DiscordPayload } from "./discord.ts"; -import Gateway from "../module/gateway.ts"; - -export abstract class ActionQueue { - protected actions: Action[] = []; - - push (action: Action) { - if (this.shouldDispatchImmediately(action)) { - this.dispatch(action); - } else { - this.actions.push(action); - } - } - - dispatchAll () { - let index = 0; - for (const action of this.actions) { - this.actions.splice(index, 1); - this.dispatch(action); - index++; - } - } - - abstract dispatch (action: Action): void; - abstract shouldDispatchImmediately (action: Action): boolean; -} - -export class GatewayActionQueue extends ActionQueue { - constructor (protected gateway: Gateway) { - super(); - } - - dispatch (action: DiscordPayload) { - this.gateway.sendObject(action); - } - - shouldDispatchImmediately () -} diff --git a/types/return-type.ts b/types/return-type.ts deleted file mode 100644 index a51bcd3fa..000000000 --- a/types/return-type.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { create_guild } from "../structures/guild.ts"; -import { create_channel } from "../structures/channel.ts"; - -export type Guild = ReturnType; -export type Channel = ReturnType diff --git a/types/role.ts b/types/role.ts index c442169c8..808f8c4a6 100644 --- a/types/role.ts +++ b/types/role.ts @@ -1,4 +1,4 @@ -export interface Role_Data { +export interface RoleData { /** role id */ id: string /** role name */ diff --git a/utils/cache.ts b/utils/cache.ts index 13b834d5f..206e4d6fd 100644 --- a/utils/cache.ts +++ b/utils/cache.ts @@ -1,11 +1,20 @@ -import { User } from "../structures/user.ts"; -import { Guild, Channel } from "../types/return-type.ts"; -import { Message } from "../structures/message.ts"; +import { User } from "../structures/user.ts" +import { Message } from "../structures/message.ts" +import { Guild } from "../structures/guild.ts" +import { Channel } from "../structures/channel.ts" -export const cache = { - guilds: new Map(), - users: new Map(), - channels: new Map(), - messages: new Map(), - unavailableGuilds: new Map() +export interface CacheData { + guilds: Map + users: Map + channels: Map + messages: Map + unavailableGuilds: Map +} + +export const cache: CacheData = { + guilds: new Map(), + users: new Map(), + channels: new Map(), + messages: new Map(), + unavailableGuilds: new Map(), } diff --git a/utils/cdn.ts b/utils/cdn.ts index 1251142a2..fa0556e83 100644 --- a/utils/cdn.ts +++ b/utils/cdn.ts @@ -1,5 +1,5 @@ -import { Image_Size, Image_Formats } from "../types/cdn.ts" +import { ImageSize, ImageFormats } from "../types/cdn.ts" -export const format_image_url = (url: string, size: Image_Size = 128, format?: Image_Formats) => { - return `${url}.${format || url.includes('/a_') ? 'gif' : 'jpg'}/?size=${size}` +export const formatImageURL = (url: string, size: ImageSize = 128, format?: ImageFormats) => { + return `${url}.${format || url.includes("/a_") ? "gif" : "jpg"}/?size=${size}` } diff --git a/utils/logger.ts b/utils/logger.ts index 989329f7e..8250f1acc 100644 --- a/utils/logger.ts +++ b/utils/logger.ts @@ -15,18 +15,18 @@ export const getTime = () => { return `${hour >= 10 ? hour : `0${hour}`}:${minute >= 10 ? minute : `0${minute}`} ${amOrPm}` } -export const logGreen = (text: string) => { - console.log(green(`[${getTime()}] => ${text}`)) +export const logGreen = (text: unknown) => { + console.log(green(`[${getTime()}] => ${JSON.stringify(text)}`)) } -export const logBlue = (text: string) => { - console.log(blue(`[${getTime()}] => ${text}`)) +export const logBlue = (text: unknown) => { + console.log(blue(`[${getTime()}] => ${JSON.stringify(text)}`)) } -export const logRed = (text: string) => { - console.log(red(`[${getTime()}] => ${text}`)) +export const logRed = (text: unknown) => { + console.log(red(`[${getTime()}] => ${JSON.stringify(text)}`)) } -export const logYellow = (text: string) => { - console.log(yellow(`[${getTime()}] => ${text}`)) +export const logYellow = (text: unknown) => { + console.log(yellow(`[${getTime()}] => ${JSON.stringify(text)}`)) } diff --git a/utils/permissions.ts b/utils/permissions.ts index 0f6654d41..570e32daa 100644 --- a/utils/permissions.ts +++ b/utils/permissions.ts @@ -1,18 +1,18 @@ import { Permission, Permissions } from "../types/permission.ts" -import { Role_Data } from "../types/role.ts" +import { RoleData } from "../types/role.ts" import { cache } from "./cache.ts" -export const member_has_permission = ( +export const memberHasPermission = ( member_id: string, owner_id: string, - role_data: Role_Data[], + role_data: RoleData[], member_role_ids: string[], permissions: Permission[] ) => { if (member_id === owner_id) return true const permissionBits = role_data - .filter(role => member_role_ids.includes(role.id)) + .filter((role) => member_role_ids.includes(role.id)) .reduce((bits, data) => { bits |= data.permissions @@ -21,19 +21,19 @@ export const member_has_permission = ( if (permissionBits & Permissions.ADMINISTRATOR) return true - return permissions.every(permission => permissionBits & Permissions[permission]) + return permissions.every((permission) => permissionBits & Permissions[permission]) } -export const bot_has_permission = (guild_id: string, bot_id: string, permissions: Permissions[]) => { +export const botHasPermission = (guild_id: string, botID: string, permissions: Permissions[]) => { const guild = cache.guilds.get(guild_id) if (!guild) return false - const member = guild.members.get(bot_id) + const member = guild.members.get(botID) if (!member) return false - const permissionBits = [...guild.roles().values()] - .map(role => role.raw()) - .filter(role => member.roles().includes(role.id)) + const permissionBits = [...guild.roles.values()] + .map((role) => role.raw) + .filter((role) => member.roles.includes(role.id)) .reduce((bits, data) => { bits |= data.permissions @@ -42,11 +42,11 @@ export const bot_has_permission = (guild_id: string, bot_id: string, permissions if (permissionBits & Permissions.ADMINISTRATOR) return true - return permissions.every(permission => permissionBits & permission) + return permissions.every((permission) => permissionBits & permission) } -export const calculate_permissions = (permission_bits: number) => { - return Object.keys(Permissions).filter(perm => { +export const calculatePermissions = (permission_bits: number) => { + return Object.keys(Permissions).filter((perm) => { return permission_bits & Permissions[perm as Permission] }) }