From 039c10afa78438bb887546c6e651c9f6247d8413 Mon Sep 17 00:00:00 2001 From: Skillz Date: Wed, 19 Feb 2020 12:11:35 -0500 Subject: [PATCH] work work work --- README.md | 27 ++- structures/channel.ts | 12 +- structures/guild.ts | 444 ++++++++++++++++++++++++++---------------- structures/member.ts | 136 ++++--------- structures/message.ts | 14 +- structures/role.ts | 32 ++- structures/user.ts | 68 ++++--- types/channel.ts | 48 +++-- types/emoji.ts | 2 + types/general.ts | 2 + types/guild.ts | 210 +------------------- types/member.ts | 31 +++ types/message.ts | 5 +- types/permission.ts | 64 ++++++ types/role.ts | 21 -- utils/cache.ts | 4 +- utils/cdn.ts | 2 +- 17 files changed, 572 insertions(+), 550 deletions(-) create mode 100644 types/general.ts create mode 100644 types/member.ts create mode 100644 types/permission.ts diff --git a/README.md b/README.md index 1f668b577..c133a7bca 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,29 @@ Discord API library wrapper in Deno ## TODO - [Review compression of payloads with GZIP](https://discordapp.com/developers/docs/topics/gateway#sending-payloads-example-gateway-dispatch) -- +- + +## Motivations/Features + +This project began out of the desire to want to learn and enhance my developer skills. As I was building it, I encountered so many issues that other libraries have that I wanted to change in my library. + +- **TYPESCRIPT:** + - First class support for Typescript! +- **SECURITY:** + - Check all permissions necessary before sending a request to the API. + - Prevent supporting self-bots and abusive behavior. +- **Functional API:** + - This will overall make a cleaner and more performant API, while removing the headaches of extending built-in classes, and inheritance. + - Avoid as many headaches and issues related to `class` and `this` + - Avoid EventEmitter to not have potential of memory leaks or bot crashes because of too many listeners or other silly issues. + - Avoid for loops, while loops etc... +- **MINIMALISTIC:** + - Prevent as many "options" for the sake of customizability. Prefer defaults that Discord recommends. +- **DOCUMENTATION:** + - All of Discord API Documentation available inside your VSC while you code. + - The entire libraries documentation is automatically available to you throw intellisense. +- **LATEST AND GREATEST JAVASCRIPT:** + - Backwards compatibility is the death of code. It causes clutter and uglyness to pile up and makes developers lazier. + - There will be no such thing as backwards compatibility reasons in Discordeno. + - We will always support the latest and greatest of JS. The end! + - That said, we don't expect many things to be changing drastically after v1. As you can imagine Typescript allows the latest and greatest of JS so we will be ahead of the curve for years to come. diff --git a/structures/channel.ts b/structures/channel.ts index 7c352a466..1e17511f3 100644 --- a/structures/channel.ts +++ b/structures/channel.ts @@ -1,8 +1,10 @@ import { Channel_Create_Options, Channel_Types, Get_Messages_After, Get_Messages_Around, Get_Messages, Get_Messages_Before, MessageContent, Create_Invite_Options } from '../types/channel' -import { Guild, Permission, Permissions } from '../types/guild' +import { Permission, Permissions } from '../types/guild' import Client from '../module/client' import { endpoints } from '../constants/discord' -import { create_message } from './message' +import { create_message, Message } from './message' +import { Guild } from './guild' +import { Message_Create_Options } from '../types/message' export const create_channel = (data: Channel_Create_Options, guild: Guild, client: Client) => { const base_channel = { @@ -30,12 +32,12 @@ export const create_channel = (data: Channel_Create_Options, guild: Guild, clien // TODO: check if the user has VIEW_CHANNEL and READ_MESSAGE_HISTORY if (options?.limit && options.limit > 100) return - const result = await client.RequestManager.get(endpoints.CHANNEL_MESSAGES(data.id), options) + const result = await client.RequestManager.get(endpoints.CHANNEL_MESSAGES(data.id), options) as Message_Create_Options[] return result.map(res => create_message(res, client)) }, /** Get pinned messages in this channel. */ get_pins: async () => { - const result = await client.RequestManager.get(endpoints.CHANNEL_PINS(data.id)) + const result = await client.RequestManager.get(endpoints.CHANNEL_PINS(data.id)) as Message_Create_Options[] return result.map(res => create_message(res, client)) }, /** Send a message to the channel. Requires SEND_MESSAGES permission. */ @@ -163,3 +165,5 @@ export const create_channel = (data: Channel_Create_Options, guild: Guild, clien mention: () => `<#${data.id}>` } } + +export type Channel = ReturnType diff --git a/structures/guild.ts b/structures/guild.ts index 003241d60..501a967ba 100644 --- a/structures/guild.ts +++ b/structures/guild.ts @@ -1,176 +1,286 @@ import Client from '../module/client' import { endpoints } from '../constants/discord' -import { formatImageURL } from '../utils/cdn' -import { Guild, CreateGuildPayload, ChannelTypes, Permissions, PrunePayload } from '../types/guild' +import { format_image_url } from '../utils/cdn' +import { + Create_Guild_Payload, + ChannelTypes, + Permissions, + PrunePayload, + Image_Size, + Image_Formats, + Position_Swap, + Get_Audit_Logs_Options, + Edit_Integration_Options, + BanOptions, + Guild_Edit_Options, + Create_Emojis_Options, + Edit_Emojis_Options, + Create_Role_Options +} from '../types/guild' import { create_role } from './role' import { create_member } from './member' import { create_channel } from './channel' +import { Channel_Create_Options } from '../types/channel' -export const createGuild = (data: CreateGuildPayload, client: Client) => { - const guild: Guild = { - ...data, - roles: new Map(data.roles.map(r => [r.id, create_role(r)])), - emojis: data.emojis, - joined_at: Date.parse(data.joined_at), - voice_states: new Map(data.voice_states.map(vs => [vs.id, create_voice_state(vs)])), - members: new Map(data.members.map(m => [m.id, create_member(m)])), - channels: new Map(data.channels.map(c => [c.id, create_channel(c, data, client)])), - presences: new Map(data.presences.map(p => [p.id, create_presence(p)])), - icon_url: (size, format) => - data.icon ? formatImageURL(endpoints.GUILD_ICON(data.id, data.icon), size, format) : undefined, - splash_url: (size, format) => - data.splash ? formatImageURL(endpoints.GUILD_SPLASH(data.id, data.splash), size, format) : undefined, - banner_url: (size, format) => - data.banner ? formatImageURL(endpoints.GUILD_BANNER(data.id, data.banner), size, format) : undefined, - create_channel: (name, options) => { - // TODO: Check if the bot has `MANAGE_CHANNELS` permission before making a channel - return client.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 - }) - }, - get_channels: () => { - return client.RequestManager.get(endpoints.GUILD_CHANNELS(data.id)) - }, - swap_channels: channel_positions => { - if (channel_positions.length < 2) throw 'You must provide atleast two channels to be swapped.' - return client.RequestManager.patch(endpoints.GUILD_CHANNELS(data.id), channel_positions) - }, - get_member: id => { - return client.RequestManager.get(endpoints.GUILD_MEMBER(data.id, id)) - }, - create_emoji: (name, image, options) => { - // TODO: Check if the bot has `MANAGE_EMOJIS` permission - return client.RequestManager.post(endpoints.GUILD_EMOJIS(data.id), { - ...options, - name, - image - }) - }, - edit_emoji: (id, options) => { - // TODO: check if the bot has `MANAGE_EMOJIS` permission - return client.RequestManager.patch(endpoints.GUILD_EMOJI(data.id, id), { - name: options.name, - roles: options.roles - }) - }, - delete_emoji: (id, reason) => { - // TODO: check if the bot has `MANAGE_EMOJIS` permission - return client.RequestManager.delete(endpoints.GUILD_EMOJI(data.id, id), { reason }) - }, - create_role: async options => { - // TODO: check if the bot has the `MANAGE_ROLES` permission. - const role = await client.RequestManager.post(endpoints.GUILD_ROLES(data.id), { - ...options, - permissions: options.permissions?.map(perm => Permissions[perm]) - }) - // TODO: cache this role +export const create_guild = (data: Create_Guild_Payload, client: Client) => ({ + /** 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, + /** 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, + /** 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: new Map(data.voice_states.map(vs => [vs.id, create_voice_state(vs)])), + /** The users in this guild. */ + members: new Map(data.members.map(m => [m.id, create_member(m)])), + /** The channels in the guild */ + channels: new Map(data.channels.map(c => [c.id, create_channel(c, data, client)])), + /** The presences of all the users in the guild. */ + presences: new Map(data.presences.map(p => [p.id, create_presence(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, + /** 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: (name: string, options: Channel_Create_Options) => { + // TODO: Check if the bot has `MANAGE_CHANNELS` permission before making a channel + return client.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 + }) + }, + /** 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 client.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) throw 'You must provide atleast two channels to be swapped.' + return client.RequestManager.patch(endpoints.GUILD_CHANNELS(data.id), channel_positions) + }, + /** 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 client.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) => { + // TODO: Check if the bot has `MANAGE_EMOJIS` permission + return client.RequestManager.post(endpoints.GUILD_EMOJIS(data.id), { + ...options, + name, + image + }) + }, + /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. */ + edit_emoji: (id: string, options: Edit_Emojis_Options) => { + // TODO: check if the bot has `MANAGE_EMOJIS` permission + return client.RequestManager.patch(endpoints.GUILD_EMOJI(data.id, id), { + name: options.name, + roles: options.roles + }) + }, + /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns 204 No Content on success. */ + delete_emoji: (id: string, reason?: string) => { + // TODO: check if the bot has `MANAGE_EMOJIS` permission + return client.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) => { + // TODO: check if the bot has the `MANAGE_ROLES` permission. + const role = await client.RequestManager.post(endpoints.GUILD_ROLES(data.id), { + ...options, + permissions: options.permissions?.map(perm => Permissions[perm]) + }) + // TODO: cache this role - return role - }, - edit_role: (id, options) => { - // TODO: check if the bot has the `MANAGE_ROLES` permission. - return client.RequestManager.patch(endpoints.GUILD_ROLE(data.id, id), options) - }, - delete_role: id => { - // TODO: check if the bot has the `MANAGE_ROLES` permission. - return client.RequestManager.delete(endpoints.GUILD_ROLE(data.id, id)) - }, - get_roles: () => { - // TODO: check if the bot has the `MANAGE_ROLES` permission. - return client.RequestManager.get(endpoints.GUILD_ROLES(data.id)) - }, - swap_roles: rolePositons => { - // TODO: check if the bot has the `MANAGE_ROLES` permission. - return client.RequestManager.patch(endpoints.GUILD_ROLES(data.id), rolePositons) - }, - get_prune_count: async days => { - if (days < 1) throw `The number of days to count prune for must be 1 or more.` - // TODO: check if the bot has `KICK_MEMBERS` permission - const result = (await client.RequestManager.get(endpoints.GUILD_PRUNE(data.id), { days })) as PrunePayload - return result.pruned - }, - prune_members: days => { - if (days < 1) throw `The number of days must be 1 or more.` - // TODO: check if the bot has `KICK_MEMBERS` permission. - return client.RequestManager.post(endpoints.GUILD_PRUNE(data.id), { days }) - }, - // TODO: REQUEST THIS OVER WEBSOCKET WITH GET_GUILD_MEMBERS ENDPOINT - // fetch_all_members: () => { - // }, - get_audit_logs: options => { - // TODO: check if the bot has VIEW_AUDIT_LOGS permission - return client.RequestManager.get(endpoints.GUILD_AUDIT_LOGS(data.id), { - ...options, - limit: options.limit && options.limit >= 1 && options.limit <= 100 ? options.limit : 50 - }) - }, - get_embed: () => { - // TODO: check if the bot has the MANAGE_GUILD permission - return client.RequestManager.get(endpoints.GUILD_EMBED(data.id)) - }, - edit_embed: (enabled, channel_id) => { - // TODO: Requires the MANAGE_GUILD permission. - return client.RequestManager.patch(endpoints.GUILD_EMBED(data.id), { enabled, channel_id }) - }, - get_vanity_url: () => { - return client.RequestManager.get(endpoints.GUILD_VANITY_URL(data.id)) - }, - get_integrations: () => { - // TODO: requires the MANAGE_GUILD permission - return client.RequestManager.get(endpoints.GUILD_INTEGRATIONS(data.id)) - }, - edit_integration: (id, options) => { - // TODO: requires the MANAGE_GUILD permission - return client.RequestManager.patch(endpoints.GUILD_INTEGRATION(data.id, id), options) - }, - delete_integration: id => { - // TODO: requires the MANAGE_GUILD permission - return client.RequestManager.delete(endpoints.GUILD_INTEGRATION(data.id, id)) - }, - sync_integration: id => { - // TODO: requires MANAGE_GUILD - return client.RequestManager.post(endpoints.GUILD_INTEGRATION_SYNC(data.id, id)) - }, - get_bans: () => { - // TODO: requires the BAN_MEMBERS permission - return client.RequestManager.get(endpoints.GUILD_BANS(data.id)) - }, - ban: (id, options) => { - // TODO: requires the BAN_MEMBERS permission - return client.RequestManager.put(endpoints.GUILD_BAN(data.id, id), options) - }, - unban: id => { - // TODO: requires the BAN_MEMBERS permission - return client.RequestManager.delete(endpoints.GUILD_BAN(data.id, id)) - }, - edit: options => { - // TODO: requires the MANAGE_GUILD permission - return client.RequestManager.patch(endpoints.GUILD(data.id), options) - }, - get_invites: () => { - // TODO: requires MANAGE_GUILD permission - return client.RequestManager.get(endpoints.GUILD_INVITES(data.id)) - }, - leave: () => { - return client.RequestManager.delete(endpoints.GUILD_LEAVE(data.id)) - }, - get_voice_regions: () => { - return client.RequestManager.get(endpoints.GUILD_REGIONS(data.id)) - }, - get_webhooks: () => { - // TODO: requires MANAGE_WEBHOOKS - return client.RequestManager.get(endpoints.GUILD_WEBHOOKS(data.id)) - } + return role + }, + /** Edit a guild role. Requires the MANAGE_ROLES permission. */ + edit_role: (id: string, options: Create_Role_Options) => { + // TODO: check if the bot has the `MANAGE_ROLES` permission. + return client.RequestManager.patch(endpoints.GUILD_ROLE(data.id, id), options) + }, + /** Delete a guild role. Requires the MANAGE_ROLES permission. */ + delete_role: (id: string) => { + // TODO: check if the bot has the `MANAGE_ROLES` permission. + return client.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: () => { + // TODO: check if the bot has the `MANAGE_ROLES` permission. + return client.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) => { + // TODO: check if the bot has the `MANAGE_ROLES` permission. + return client.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) => { + if (days < 1) throw `The number of days to count prune for must be 1 or more.` + // TODO: check if the bot has `KICK_MEMBERS` permission + const result = (await client.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) => { + if (days < 1) throw `The number of days must be 1 or more.` + // TODO: check if the bot has `KICK_MEMBERS` permission. + return client.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) => { + // TODO: check if the bot has VIEW_AUDIT_LOGS permission + return client.RequestManager.get(endpoints.GUILD_AUDIT_LOGS(data.id), { + ...options, + limit: options.limit && options.limit >= 1 && options.limit <= 100 ? options.limit : 50 + }) + }, + /** Returns the guild embed object. Requires the MANAGE_GUILD permission. */ + get_embed: () => { + // TODO: check if the bot has the MANAGE_GUILD permission + return client.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) => { + // TODO: Requires the MANAGE_GUILD permission. + return client.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 client.RequestManager.get(endpoints.GUILD_VANITY_URL(data.id)) + }, + /** Returns a list of integrations for the guild. Requires the MANAGE_GUILD permission. */ + get_integrations: () => { + // TODO: requires the MANAGE_GUILD permission + return client.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) => { + // TODO: requires the MANAGE_GUILD permission + return client.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) => { + // TODO: requires the MANAGE_GUILD permission + return client.RequestManager.delete(endpoints.GUILD_INTEGRATION(data.id, id)) + }, + /** Sync an integration. Requires teh MANAGE_GUILD permission. */ + sync_integration: (id: string) => { + // TODO: requires MANAGE_GUILD + return client.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: () => { + // TODO: requires the BAN_MEMBERS permission + return client.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) => { + // TODO: requires the BAN_MEMBERS permission + return client.RequestManager.put(endpoints.GUILD_BAN(data.id, id), options) + }, + /** Remove the ban for a user. REquires BAN_MEMBERS permission */ + unban: (id: string) => { + // TODO: requires the BAN_MEMBERS permission + return client.RequestManager.delete(endpoints.GUILD_BAN(data.id, id)) + }, + /** Modify a guilds settings. Requires the MANAGE_GUILD permission. */ + edit: (options: Guild_Edit_Options) => { + // TODO: requires the MANAGE_GUILD permission + return client.RequestManager.patch(endpoints.GUILD(data.id), options) + }, + /** Get all the invites for this guild. Requires MANAGE_GUILD permission */ + et_invites: () => { + // TODO: requires MANAGE_GUILD permission + return client.RequestManager.get(endpoints.GUILD_INVITES(data.id)) + }, + /** Leave a guild */ + leave: () => { + return client.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 client.RequestManager.get(endpoints.GUILD_REGIONS(data.id)) + }, + /** Returns a list of guild webhooks objects. Requires the MANAGE_WEBHOOKs permission. */ + get_webhooks: () => { + // TODO: requires MANAGE_WEBHOOKS + return client.RequestManager.get(endpoints.GUILD_WEBHOOKS(data.id)) } +}) - return guild -} +export type Guild = ReturnType diff --git a/structures/member.ts b/structures/member.ts index 15019c71e..2e1ed7b5a 100644 --- a/structures/member.ts +++ b/structures/member.ts @@ -1,118 +1,67 @@ import Client from '../module/client' import { endpoints } from '../constants/discord' -import { Guild, Image_Size, Image_Formats, Permissions, Permission } from '../types/guild' -import { formatImageURL } from '../utils/cdn' +import { format_image_url } from '../utils/cdn' +import { Member_Create_Payload, Edit_Member_Options } from '../types/member' +import { Image_Size, Image_Formats } from '../types/general' +import { Permission, Permissions } from '../types/permission' +import { cache } from '../utils/cache' -export interface Edit_Member_Options { - /** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */ - nick?: string - /** Array of role ids the member is assigned. Requires MANAGE_ROLES permission. */ - roles?: string[] - /** Whether the user is muted in voice channels. Requires MUTE_MEMBERS permission. */ - mute?: boolean - /** Whether the user is deafened in voice channels. Requires DEAFEN_MEMBERS permission. */ - deaf?: boolean - /** The id of the channel to move user to if they are connected to voice. To kick the user from their current channel, set to null. Requires MOVE_MEMBERS permission. When moving members to channels, must have permissions to both CONNECT to the channel and have the MOVE_MEMBER permission. */ - channel_id?: string | null -} - -export interface Member { - /** The unique user id */ - id: string - /** The user's guild nickname if one is set. */ - nick(): string | undefined - /** Array of role ids that the member has */ - roles(): string[] - /** When the user joined the guild. */ - joined_at(): number - /** When the user used their nitro boost on the server. */ - premium_since(): number | undefined - /** Whether the user is deafened in voice channels */ - deaf(): boolean - /** Whether the user is muted in voice channels */ - mute(): boolean - edit(options: Edit_Member_Options): Promise - /** The username of the this member. */ - username(): string - /** The 4 digit unique identifier */ - discriminator(): string - /** The full username#discriminator */ - tag(): string - /** The users custom avatar or the default avatar */ - avatarURL(size: Image_Size, format: Image_Formats): string - /** The user mention with nickname if possible */ - mention(): string - /** Whether the member is a bot */ - bot(): boolean - /** When the user created their account */ - created_at(): number - /** Add a role to the member */ - addRole(role_id: string, reason: string): Promise - /** Remove a role from the member */ - removeRole(role_id: string, reason: string): Promise - /** Kick a member from the server */ - kick(reason: string): Promise - /** Ban a member from the server */ - ban(delete_message_days?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7, reason?: string): Promise - has_permissions(permissions: Permission[]): boolean -} - -export interface Member_Create_Payload { - /** The user this guild member represents */ - user: User - /** The user's guild nickname if one is set. */ - nick?: string - /** Array of role ids that the member has */ - roles: string[] - /** When the user joined the guild. */ - joined_at: string - /** When the user used their nitro boost on the server. */ - premium_since?: string - /** Whether the user is deafened in voice channels */ - deaf: boolean - /** Whether the user is muted in voice channels */ - mute: boolean -} - -export const create_member = (data: Member_Create_Payload, guild: Guild, client: Client) => { - const member: Member = { - id: data.user.id, +export const create_member = (data: Member_Create_Payload, guild_id: string, client: Client) => { + const guild = cache.guilds.get(guild_id) + + return { + /** 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, + /** When the user joined the guild. */ joined_at: () => 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, + /** The full username#discriminator */ tag: () => `${data.user.username}#${data.user.discriminator}`, - game: () => data.game, - status: () => data.status, - client_status: () => data.client_status, - activities: () => data.activites, - avatarURL: (size, format) => + /** The users custom avatar or the default avatar */ + avatar_url: (size: Image_Size = 128, format?: Image_Formats) => data.user.avatar - ? formatImageURL(endpoints.USER_AVATAR(data.user.id, data.user.avatar), size, format) - : endpoints.USER_DEFAULT_AVATAR(data.user.discriminator % 5), + ? format_image_url(endpoints.USER_AVATAR(data.user.id, data.user.avatar), size, format) + : endpoints.USER_DEFAULT_AVATAR(Number(data.user.discriminator) % 5), + /** The user mention with nickname if possible */ mention: () => `<@!${data.user.id}>`, + /** Whether the member is a bot */ bot: () => data.user.bot, - created_at: () => data.user.created_at, - addRole: (role_id, reason) => { + /** Add a role to the member */ + add_role: (role_id: string, reason?: string) => { // TODO: check if the bot has MANAGE_ROLE and its highest role is above this one return client.RequestManager.put(endpoints.GUILD_MEMBER_ROLE(guild.id, data.user.id, role_id), { reason }) }, - removeRole: (role_id, reason) => { + /** Remove a role from the member */ + remove_role: (role_id: string, reason?: string) => { // TODO: check if the bot has MANAGE_ROLE permissions and its highest role is above this role return client.RequestManager.delete(endpoints.GUILD_MEMBER_ROLE(guild.id, data.user.id, role_id), { reason }) }, - kick: reason => { + /** Kick a member from the server */ + kick: (reason?: string) => { // TODO: check if bot has KICK_MEMBER permissions return client.RequestManager.delete(endpoints.GUILD_MEMBER(guild.id, data.user.id), { reason }) }, - ban: (delete_message_days = 0, reason) => { + /** Ban a member from the server */ + ban: (delete_message_days = 0, reason?: string) => { return guild.ban(data.user.id, { delete_message_days, reason }) }, - has_permissions: permissions => { + /** 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[]) => { if (data.user.id === guild.owner_id) return true const permissionBits = data.roles.reduce((bits, role_id) => { @@ -126,7 +75,8 @@ export const create_member = (data: Member_Create_Payload, guild: Guild, client: return permissions.every(permission => permissionBits & Permissions[permission]) }, - edit: options => { + /** Edit the member */ + edit: (options: Edit_Member_Options) => { // TODO: check if has MANAGE_NICKNAME Permission // TODO: check if it is a valid nickname like 32 characters options.nick = undefined @@ -142,9 +92,9 @@ export const create_member = (data: Member_Create_Payload, guild: Guild, client: // TODO: if channel id is provided check if the bot has CONNECT and MOVE in channel and current channel options.channel_id = undefined - return client.RequestManager.patch(endpoints.GUILD_MEMBER(guild.id, data.id), options) + return client.RequestManager.patch(endpoints.GUILD_MEMBER(guild.id, data.user.id), options) } } - - return member } + +export type Member = ReturnType diff --git a/structures/message.ts b/structures/message.ts index 9bf53234b..19bc03976 100644 --- a/structures/message.ts +++ b/structures/message.ts @@ -3,6 +3,7 @@ import { Message_Create_Options } from '../types/message' import { endpoints } from '../constants/discord' import { Channel_Types, MessageContent } from '../types/channel' import { cache } from '../utils/cache' +import { create_user, User_Payload } from './user' export const create_message = (data: Message_Create_Options, client: Client) => { const base_message = { @@ -31,11 +32,11 @@ export const create_message = (data: Message_Create_Options, client: Client) => }), flags: () => data.flags || 0, channel_id: () => data.channel_id, - channel: () => client.channels.get(data.channel_id), + channel: () => cache.channels.get(data.channel_id), delete: (reason: string) => { // TODO: Requires MANAGE_MESSAGES - if (data.author.id !== client.bot_id) checkPermission() + if (data.author.id !== client.bot_id) {} client.RequestManager.delete(endpoints.CHANNEL_MESSAGE(data.channel_id, data.id), { reason }) }, @@ -67,8 +68,9 @@ export const create_message = (data: Message_Create_Options, client: Client) => client.RequestManager.delete(endpoints.CHANNEL_MESSAGE_REACTION(data.channel_id, data.id, reaction)) }, /** Get a list of users that reacted with this emoji. */ - get_reactions: (reaction: string) => { - return client.RequestManager.get(endpoints.CHANNEL_MESSAGE_REACTION(data.channel_id, data.id, reaction)) as User[] + get_reactions: async (reaction: string) => { + const result = await client.RequestManager.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) => { @@ -92,7 +94,7 @@ export const create_message = (data: Message_Create_Options, client: Client) => if (!data.guild_id) { return { ...base_message, - author: create_user(data.author, client) + author: create_user({ ...data.author, avatar: data.author.avatar || '' }) } } @@ -104,3 +106,5 @@ export const create_message = (data: Message_Create_Options, client: Client) => member: () => data.member } } + +export type Message = ReturnType diff --git a/structures/role.ts b/structures/role.ts index 4c05dd72a..d2e217b6a 100644 --- a/structures/role.ts +++ b/structures/role.ts @@ -1,10 +1,26 @@ -import { Role, Role_Data } from "../types/role" +import { Role_Data } from '../types/role' -export const create_role = (data: Role_Data) => { - const role: Role = { - ...data, - mention: () => `<@&${data.id}>` - } +export const create_role = (data: Role_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, + /** The @ mention of the role in a string. */ + mention: () => `<@&${data.id}>` +}) - return role -} +export type Role = ReturnType diff --git a/structures/user.ts b/structures/user.ts index f9d884fe8..983620fd1 100644 --- a/structures/user.ts +++ b/structures/user.ts @@ -1,34 +1,58 @@ -export interface UserPayload { - /** The user's id */ - id: string; +import { Image_Formats, Image_Size } from '../types/guild' +import { format_image_url } from '../utils/cdn' +import { endpoints } from '../constants/discord' - /** The user's username, not unique across the platform */ - username: string; +export interface User_Payload { + /** The user's id */ + id: string - /** The user's 4-digit discord-tag */ - discriminator: string; + /** The user's username, not unique across the platform */ + username: string - /** The user's avatar hash */ - avatar: string; + /** The user's 4-digit discord-tag */ + discriminator: string - /** Whether the user belongs to an OAuth2 application */ - bot?: boolean; + /** The user's avatar hash */ + avatar: string - /** Whether the user is an Official Discord System user (part of the urgent message system) */ - system?: boolean; + /** Whether the user belongs to an OAuth2 application */ + bot?: boolean - /** Whether the user has two factor enabled on their account */ - mfa_enabled?: boolean; + /** Whether the user is an Official Discord System user (part of the urgent message system) */ + system?: boolean - // Types with "email" scope intentionally left out. - /** The flags on a user's account */ - flags?: number; + /** Whether the user has two factor enabled on their account */ + mfa_enabled?: boolean - /** The type of Nitro subscription on a user's account */ - premium_type?: PremiumType; + // Types with "email" scope intentionally left out. + /** The flags on a user's account */ + flags?: number + + /** The type of Nitro subscription on a user's account */ + premium_type?: PremiumType } export const enum PremiumType { - NitroClassic = 1, - Nitro + NitroClassic = 1, + 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, format: Image_Formats) => + data.avatar + ? format_image_url(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 diff --git a/types/channel.ts b/types/channel.ts index 488955c29..9ce091d31 100644 --- a/types/channel.ts +++ b/types/channel.ts @@ -1,6 +1,6 @@ -import { Raw_Overwrite } from './guild' +import { Raw_Overwrite, Overwrite } from './guild' -export interface Channel_Create_Options { +export interface Base_Channel_Create { /** The id of this channel */ id: string /** The type of the channel */ @@ -9,26 +9,34 @@ export interface Channel_Create_Options { guild_id?: string /** Sorting position of the channel */ position?: number + /** The name of the channel (2-100 characters) */ + name?: string + /** The channel topic (0-1024 characters) */ + topic?: string + /** Whether the channel is nsfw */ + nsfw?: boolean + /** The id of the last message sent in this channel (may not point to an existing or valid message) */ + last_message_id?: string | null + /** The bitrate (in bits) of the voice channel */ + bitrate?: number + /** The user limit of the voice channel */ + user_limit?: number + /** Amount of seconds a user has to wait before sending another message (0-21600) Bots and users with the permission MANAGE_MESSAGES or MANAGE_CHANNEL are unaffected. */ + rate_limit_per_user?: number + /** The parent category id */ + parent_id?: string | null + /** When the last pinned message was pinned */ + last_pin_timestamp?: string +} + +export interface Channel_Create_Payload extends Base_Channel_Create { /** Explicit permission overwrites for members and roles */ permission_overwrites?: Raw_Overwrite[] - /** The name of the channel (2-100 characters) */ - name?: string - /** The channel topic (0-1024 characters) */ - topic?: string - /** Whether the channel is nsfw */ - nsfw?: boolean - /** The id of the last message sent in this channel (may not point to an existing or valid message) */ - last_message_id?: string | null - /** The bitrate (in bits) of the voice channel */ - bitrate?: number - /** The user limit of the voice channel */ - user_limit?: number - /** Amount of seconds a user has to wait before sending another message (0-21600) Bots and users with the permission MANAGE_MESSAGES or MANAGE_CHANNEL are unaffected. */ - rate_limit_per_user?: number - /** The parent category id */ - parent_id?: string | null - /** When the last pinned message was pinned */ - last_pin_timestamp?: string +} + +export interface Channel_Create_Options extends Base_Channel_Create { + /** Explicit permission overwrites for members and roles */ + permission_overwrites?: Overwrite[] } export type Channel_Type = 0 | 1 | 2 | 4 | 5 | 6 diff --git a/types/emoji.ts b/types/emoji.ts index 9240e7cda..b717060c9 100644 --- a/types/emoji.ts +++ b/types/emoji.ts @@ -1,3 +1,5 @@ +import { User } from "../structures/user"; + export interface Emoji { /** emoji id. It will be null for default discord emojis. */ id: string | null diff --git a/types/general.ts b/types/general.ts new file mode 100644 index 000000000..53f878e8e --- /dev/null +++ b/types/general.ts @@ -0,0 +1,2 @@ +export type Image_Size = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 +export type Image_Formats = 'jpg' | 'jpeg' | 'png' | 'webp' | 'gif' diff --git a/types/guild.ts b/types/guild.ts index 7f45b3bb0..67d5dfbf6 100644 --- a/types/guild.ts +++ b/types/guild.ts @@ -1,8 +1,11 @@ -import { Role } from './role' import { Emoji } from './discord' import { Member } from '../structures/member' +import { User } from '../structures/user' +import { Permission } from './permission' +import { Role } from '../structures/role' +import { Channel } from '../structures/channel' -export interface CreateGuildPayload { +export interface Create_Guild_Payload { /** The guild id */ id: string /** The guild name 2-100 characters */ @@ -67,142 +70,6 @@ export interface CreateGuildPayload { preferred_locale: string } -export interface Guild { - /** The guild id */ - id: string - /** The guild name 2-100 characters */ - name: string - /** The guild icon image hash */ - icon: string | null - /** The guild splash image hash */ - splash: string | null - /** The id of the owner */ - owner_id: string - /** The voice region id for the guild */ - region: string - /** The afk channel id */ - afk_channel_id: string | null - /** AFK Timeout in seconds. */ - afk_timeout: number - /** The verification level required for the guild */ - verification_level: number - /** The roles in the guild */ - roles: Map - /** The custom guild emojis */ - emojis: Emoji[] - /** Enabled guild features */ - features: Guild_Features[] - /** Required MFA level for the guild */ - mfa_level: number - /** The id of the channel to which system mesages are sent */ - system_channel_id: string | null - /** When this guild was joined at */ - joined_at: number - /** Whether this is considered a large guild */ - large: boolean - /** Whether this guild is unavailable */ - unavailable: boolean - /** Total number of members in this guild */ - member_count: number - voice_states: Map - /** Users in the guild */ - members: Map - /** Channels in the guild */ - channels: Map - presences: Map - /** The maximum amount of presences for the guild(the default value, currently 5000 is in effect when null is returned.) */ - max_presences?: number | null - /** The maximum amount of members for the guild */ - max_members?: number - /** The vanity url code for the guild */ - vanity_url_code: string | null - /** The description for the guild */ - description: string | null - /** The banner hash */ - banner: string | null - /** The premium tier */ - premium_tier: number - /** The total number of users currently boosting this server. */ - premium_subscription_count: number - /** The preferred local of this guild only set if guild has the DISCOVERABLE feature, defaults to en-US */ - preferred_locale: string - /** The full URL of the icon from Discords CDN. Undefined when no icon is set. */ - icon_url(size?: Image_Size, format?: Image_Formats): string | undefined - /** The full URL of the splash from Discords CDN. Undefined if no splash is set. */ - splash_url(size?: Image_Size, format?: Image_Formats): string | undefined - /** The full URL of the banner from Discords CDN. Undefined if no banner is set. */ - banner_url(size?: Image_Size, format?: Image_Formats): string | undefined - /** Create a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */ - create_channel(name: string, options: ChannelCreate_Options): Promise - /** 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(): Promise - /** Modify the positions of channels on the guild. Requires MANAGE_CHANNELS permisison. */ - swap_channels(channel_positions: Position_Swap[]): Promise - /** 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): Promise - /** 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): Promise - /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. */ - edit_emoji(id: string, options: Edit_Emojis_Options): Promise - /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns 204 No Content on success. */ - delete_emoji(id: string, reason?: string): Promise - /** Create a new role for the guild. Requires the MANAGE_ROLES permission. */ - create_role(options: Create_Role_Options): Promise - /** Edi a guild role. Requires the MANAGE_ROLES permission. */ - edit_role(id: string, options: Create_Role_Options): Promise - /** Delete a guild role. Requires the MANAGE_ROLES permission. */ - delete_role(id: string): Promise - /** 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(): Promise - /** Modify the positions of a set of role objects for the guild. Requires the MANAGE_ROLES permission. */ - swap_roles(role_positions: Position_Swap): Promise - /** Check how many members would be removed from the server in a prune operation. Requires the KICK_MEMBERS permission */ - get_prune_count(days: number): Promise - /** Begin pruning all members in the given time period */ - prune_members(days: number): Promise - /** Returns the audit logs for the guild. Requires VIEW AUDIT LOGS permission */ - get_audit_logs(options: Get_Audit_Logs_Options): Promise - /** Returns the guild embed object. Requires the MANAGE_GUILD permission. */ - get_embed(): Promise - /** Modify a guild embed object for the guild. Requires the MANAGE_GUILD permission. */ - edit_embed(enabled: boolean, channel_id?: string | null): Promise - /** Returns the code and uses of the vanity url for this server if it is enabled. Requires the MANAGE_GUILD permission. */ - get_vanity_url(): Promise - /** Returns a list of integrations for the guild. Requires the MANAGE_GUILD permission. */ - get_integrations(): Promise - /** 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): Promise - /** Delete the attached integration object for the guild with this id. Requires MANAGE_GUILD permission. */ - delete_integration(id: string): Promise - /** Sync an integration. Requires teh MANAGE_GUILD permission. */ - sync_integration(id: string): Promise - /** Returns a list of ban objects for the users banned from this guild. Requires the BAN_MEMBERS permission. */ - get_bans(): Promise - /** 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): Promise - /** Remove the ban for a user. REquires BAN_MEMBERS permission */ - unban(id: string): Promise - /** Modify a guilds settings. Requires the MANAGE_GUILD permission. */ - edit(options: Guild_Edit_Options): Promise - /** Get all the invites for this guild. Requires MANAGE_GUILD permission */ - get_invites(): Promise - /** Leave a guild */ - leave(): Promise - /** 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(): Promise - /** Returns a list of guild webhooks objects. Requires the MANAGE_WEBHOOKs permission. */ - get_webhooks(): Promise -} - export type Guild_Features = | `INVITE_SPLASH` | `VIP_REGIONS` @@ -456,42 +323,8 @@ export enum AuditLogs { INTEGRATION_DELETE } -export type Image_Size = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 -export type Image_Formats = 'jpg' | 'jpeg' | 'png' | 'webp' | 'gif' export type ChannelType = 'text' | 'dm' | 'news' | 'voice' | 'category' | 'store' -export type Permission = - | `CREATE_INSTANT_INVITE` - | `KICK_MEMBERS` - | `BAN_MEMBERS` - | `ADMINISTRATOR` - | `MANAGE_CHANNELS` - | `MANAGE_GUILD` - | `ADD_REACTIONS` - | `VIEW_AUDIT_LOG` - | `VIEW_CHANNEL` - | `SEND_MESSAGES` - | `SEND_TTS_MESSAGES` - | `MANAGE_MESSAGES` - | `EMBED_LINKS` - | `ATTACH_FILES` - | `READ_MESSAGE_HISTORY` - | `MENTION_EVERYONE` - | `USE_EXTERNAL_EMOJIS` - | `CONNECT` - | `SPEAK` - | `MUTE_MEMBERS` - | `DEAFEN_MEMBERS` - | `MOVE_MEMBERS` - | `USE_VAD` - | `PRIORITY_SPEAKER` - | `STREAM` - | `CHANGE_NICKNAME` - | `MANAGE_NICKNAMES` - | `MANAGE_ROLES` - | `MANAGE_WEBHOOKS` - | `MANAGE_EMOJIS` - export interface Overwrite { /** The role or user id */ id: string @@ -523,39 +356,6 @@ export enum ChannelTypes { store } -export enum Permissions { - CREATE_INSTANT_INVITE = 0x00000001, - KICK_MEMBERS = 0x00000002, - BAN_MEMBERS = 0x00000004, - ADMINISTRATOR = 0x00000008, - MANAGE_CHANNELS = 0x00000010, - MANAGE_GUILD = 0x00000020, - ADD_REACTIONS = 0x00000040, - VIEW_AUDIT_LOG = 0x00000080, - VIEW_CHANNEL = 0x00000400, - SEND_MESSAGES = 0x00000800, - SEND_TTS_MESSAGES = 0x00001000, - MANAGE_MESSAGES = 0x00002000, - EMBED_LINKS = 0x00004000, - ATTACH_FILES = 0x00008000, - READ_MESSAGE_HISTORY = 0x00010000, - MENTION_EVERYONE = 0x00020000, - USE_EXTERNAL_EMOJIS = 0x00040000, - CONNECT = 0x00100000, - SPEAK = 0x00200000, - MUTE_MEMBERS = 0x00400000, - DEAFEN_MEMBERS = 0x00800000, - MOVE_MEMBERS = 0x01000000, - USE_VAD = 0x02000000, - PRIORITY_SPEAKER = 0x00000100, - STREAM = 0x00000200, - CHANGE_NICKNAME = 0x04000000, - MANAGE_NICKNAMES = 0x08000000, - MANAGE_ROLES = 0x10000000, - MANAGE_WEBHOOKS = 0x20000000, - MANAGE_EMOJIS = 0x40000000 -} - export interface ChannelCreate_Options { /** The type of the channel */ type?: ChannelType diff --git a/types/member.ts b/types/member.ts new file mode 100644 index 000000000..5d841ecd7 --- /dev/null +++ b/types/member.ts @@ -0,0 +1,31 @@ +import { User_Payload } from "../structures/user"; + +export interface Edit_Member_Options { + /** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */ + nick?: string + /** Array of role ids the member is assigned. Requires MANAGE_ROLES permission. */ + roles?: string[] + /** Whether the user is muted in voice channels. Requires MUTE_MEMBERS permission. */ + mute?: boolean + /** Whether the user is deafened in voice channels. Requires DEAFEN_MEMBERS permission. */ + deaf?: boolean + /** The id of the channel to move user to if they are connected to voice. To kick the user from their current channel, set to null. Requires MOVE_MEMBERS permission. When moving members to channels, must have permissions to both CONNECT to the channel and have the MOVE_MEMBER permission. */ + channel_id?: string | null +} + +export interface Member_Create_Payload { + /** The user this guild member represents */ + user: User_Payload + /** The user's guild nickname if one is set. */ + nick?: string + /** Array of role ids that the member has */ + roles: string[] + /** When the user joined the guild. */ + joined_at: string + /** When the user used their nitro boost on the server. */ + premium_since?: string + /** Whether the user is deafened in voice channels */ + deaf: boolean + /** Whether the user is muted in voice channels */ + mute: boolean +} diff --git a/types/message.ts b/types/message.ts index 099a7a95a..f1b1ef4b6 100644 --- a/types/message.ts +++ b/types/message.ts @@ -1,5 +1,6 @@ import { Member } from '../structures/member' -import { ChannelType } from './guild' +import { ChannelType, User_Data } from './guild' +import { User } from '../structures/user' export interface MentionedUser extends User { member: Member @@ -223,7 +224,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 + author: User_Data /** The member properties for this message's author. Can be partial. */ member?: Member /** The contents of the message */ diff --git a/types/permission.ts b/types/permission.ts new file mode 100644 index 000000000..559e880b6 --- /dev/null +++ b/types/permission.ts @@ -0,0 +1,64 @@ +export type Permission = + | `CREATE_INSTANT_INVITE` + | `KICK_MEMBERS` + | `BAN_MEMBERS` + | `ADMINISTRATOR` + | `MANAGE_CHANNELS` + | `MANAGE_GUILD` + | `ADD_REACTIONS` + | `VIEW_AUDIT_LOG` + | `VIEW_CHANNEL` + | `SEND_MESSAGES` + | `SEND_TTS_MESSAGES` + | `MANAGE_MESSAGES` + | `EMBED_LINKS` + | `ATTACH_FILES` + | `READ_MESSAGE_HISTORY` + | `MENTION_EVERYONE` + | `USE_EXTERNAL_EMOJIS` + | `CONNECT` + | `SPEAK` + | `MUTE_MEMBERS` + | `DEAFEN_MEMBERS` + | `MOVE_MEMBERS` + | `USE_VAD` + | `PRIORITY_SPEAKER` + | `STREAM` + | `CHANGE_NICKNAME` + | `MANAGE_NICKNAMES` + | `MANAGE_ROLES` + | `MANAGE_WEBHOOKS` + | `MANAGE_EMOJIS` + +export enum Permissions { + CREATE_INSTANT_INVITE = 0x00000001, + KICK_MEMBERS = 0x00000002, + BAN_MEMBERS = 0x00000004, + ADMINISTRATOR = 0x00000008, + MANAGE_CHANNELS = 0x00000010, + MANAGE_GUILD = 0x00000020, + ADD_REACTIONS = 0x00000040, + VIEW_AUDIT_LOG = 0x00000080, + VIEW_CHANNEL = 0x00000400, + SEND_MESSAGES = 0x00000800, + SEND_TTS_MESSAGES = 0x00001000, + MANAGE_MESSAGES = 0x00002000, + EMBED_LINKS = 0x00004000, + ATTACH_FILES = 0x00008000, + READ_MESSAGE_HISTORY = 0x00010000, + MENTION_EVERYONE = 0x00020000, + USE_EXTERNAL_EMOJIS = 0x00040000, + CONNECT = 0x00100000, + SPEAK = 0x00200000, + MUTE_MEMBERS = 0x00400000, + DEAFEN_MEMBERS = 0x00800000, + MOVE_MEMBERS = 0x01000000, + USE_VAD = 0x02000000, + PRIORITY_SPEAKER = 0x00000100, + STREAM = 0x00000200, + CHANGE_NICKNAME = 0x04000000, + MANAGE_NICKNAMES = 0x08000000, + MANAGE_ROLES = 0x10000000, + MANAGE_WEBHOOKS = 0x20000000, + MANAGE_EMOJIS = 0x40000000 +} diff --git a/types/role.ts b/types/role.ts index b9628be43..c442169c8 100644 --- a/types/role.ts +++ b/types/role.ts @@ -16,24 +16,3 @@ export interface Role_Data { /** whether this role is mentionable */ mentionable: boolean } - -export interface Role { - /** role id */ - id: string - /** role name */ - name: string - /** integer representation of hexadecimal color code */ - color: number - /** if this role is pinned in the user listing */ - hoist: boolean - /** position of this role */ - position: number - /** permission bit set */ - permissions: number - /** whether this role is managed by an integration */ - managed: boolean - /** whether this role is mentionable */ - mentionable: boolean - /** The @ mention of the role in a string. */ - mention(): string -} diff --git a/utils/cache.ts b/utils/cache.ts index e0d66532d..22ad15263 100644 --- a/utils/cache.ts +++ b/utils/cache.ts @@ -1,4 +1,6 @@ -import { Guild } from "../types/guild"; +import { User } from "../structures/user"; +import { Channel } from "../structures/channel"; +import { Guild } from "../structures/guild"; export const cache = { guilds: new Map(), diff --git a/utils/cdn.ts b/utils/cdn.ts index ae221007f..0e8ab4425 100644 --- a/utils/cdn.ts +++ b/utils/cdn.ts @@ -1,5 +1,5 @@ import { ImageSize, ImageFormats } from '../structures/guild' -export const formatImageURL = (url: string, size: ImageSize = 128, format?: ImageFormats) => { +export const format_image_url = (url: string, size: ImageSize = 128, format?: ImageFormats) => { return `${url}.${format || url.includes('/a_') ? 'gif' : 'jpg'}/?size=${size}` }