├── esm └── index.mjs ├── .github ├── FUNDING.yml └── workflows │ ├── tests.yml │ ├── docs.yml │ └── npm-publish.yml ├── src ├── Client │ ├── Managers │ │ ├── RolesManager.ts │ │ ├── UsersManager.ts │ │ ├── EmojisManager.ts │ │ ├── MessagesManager.ts │ │ ├── GuildsManager.ts │ │ └── ChannelsManger.ts │ ├── ClientOptions.ts │ ├── Websocket │ │ ├── Handlers │ │ │ ├── USER_UPDATE.ts │ │ │ ├── VOICE_SERVER_UPDATE.ts │ │ │ ├── INVITE_CREATE.ts │ │ │ ├── INVITE_DELETE.ts │ │ │ ├── PRESENCE_UPDATE.ts │ │ │ ├── WEBHOOKS_UPDATE.ts │ │ │ ├── VOICE_STATE_UPDATE.ts │ │ │ ├── GUILD_UPDATE.ts │ │ │ ├── MESSAGE_REACTION_ADD.ts │ │ │ ├── MESSAGE_REACTION_REMOVE.ts │ │ │ ├── MESSAGE_REACTION_REMOVE_ALL.ts │ │ │ ├── CHANNEL_DELETE.ts │ │ │ ├── MESSAGE_REACTION_REMOVE_EMOJI.ts │ │ │ ├── TYPING_START.ts │ │ │ ├── GUILD_CREATE.ts │ │ │ ├── MESSAGE_DELETE.ts │ │ │ ├── MESSAGE_UPDATE.ts │ │ │ ├── GUILD_DELETE.ts │ │ │ ├── GUILD_ROLE_UPDATE.ts │ │ │ ├── GUILD_INTEGRATIONS_UPDATE.ts │ │ │ ├── CHANNEL_PINS_UPDATE.ts │ │ │ ├── GUILD_ROLE_DELETE.ts │ │ │ ├── CHANNEL_CREATE.ts │ │ │ ├── GUILD_BAN_ADD.ts │ │ │ ├── GUILD_BAN_REMOVE.ts │ │ │ ├── GUILD_ROLE_CREATE.ts │ │ │ ├── MESSAGE_DELETE_BULK.ts │ │ │ ├── CHANNEL_UPDATE.ts │ │ │ ├── GUILD_MEMBER_REMOVE.ts │ │ │ ├── GUILD_MEMBER_ADD.ts │ │ │ ├── MESSAGE_CREATE.ts │ │ │ ├── GUILD_MEMBER_UPDATE.ts │ │ │ ├── GUILD_EMOJIS_UPDATE.ts │ │ │ ├── GUILD_MEMBERS_CHUNK.ts │ │ │ └── READY.ts │ │ ├── ShardManager.ts │ │ ├── Voice │ │ │ └── VoiceGateway.ts │ │ ├── Websocket.ts │ │ └── Gateway.ts │ ├── Events │ │ ├── ChannelEvents.ts │ │ ├── GuildEvents.ts │ │ ├── GuildIntegrationEvents.ts │ │ ├── MessageReactionEvents.ts │ │ ├── MessageEvents.ts │ │ ├── BaseEvent.ts │ │ ├── GuildBanEvents.ts │ │ ├── GuildRoleEvents.ts │ │ ├── GuildEmojiEvents.ts │ │ ├── GuildMemberEvents.ts │ │ └── GuildMembersChunkEvents.ts │ ├── RestAPI │ │ ├── DiscordRejection.ts │ │ ├── RestAPI.ts │ │ └── RestAPIHandler.ts │ ├── ClientUser.ts │ ├── EvolveClient.ts │ └── EvolveBuilder.ts ├── Interfaces │ ├── OverwriteOptions.ts │ ├── MessageReactionOptions.ts │ ├── VoiceRegionOptions.ts │ ├── DMChannelOptions.ts │ ├── RoleOptions.ts │ ├── CategoryChannelOptions.ts │ ├── GuildMemberOptions.ts │ ├── EmojiOptions.ts │ ├── WebhookOptions.ts │ ├── Integration.ts │ ├── GroupChannelOptions.ts │ ├── VoiceChannelOptions.ts │ ├── StoreChannelOptions.ts │ ├── InviteOptions.ts │ ├── PresenceUpdateOptions.ts │ ├── VoiceStateOptions.ts │ ├── NewsChannelOptions.ts │ ├── TextChannelOptions.ts │ ├── UserOptions.ts │ ├── Interfaces.ts │ ├── MessageOptions.ts │ ├── ActivityOptions.ts │ └── GuildOptions.ts ├── Decorators │ ├── Events.ts │ └── Builder.ts ├── Structures │ ├── Channel │ │ ├── Channel.ts │ │ ├── Overwrite.ts │ │ ├── DMChannel.ts │ │ ├── CategoryChannel.ts │ │ ├── StoreChannel.ts │ │ ├── VoiceChannel.ts │ │ ├── GroupChannel.ts │ │ ├── NewsChannel.ts │ │ └── TextChannel.ts │ ├── Miscs │ │ └── ClientStatus.ts │ ├── Guild │ │ ├── Role.ts │ │ ├── GuildMember.ts │ │ ├── Webhook.ts │ │ ├── Emoji.ts │ │ ├── Invite.ts │ │ ├── VoiceState.ts │ │ └── Guild.ts │ ├── Message │ │ ├── MessageReaction.ts │ │ └── Message.ts │ ├── User │ │ ├── User.ts │ │ ├── PresenceUpdate.ts │ │ └── Activity.ts │ └── Structures.ts ├── Utils │ ├── Embed │ │ ├── MessageEmbed.ts │ │ ├── EmbedProvider.ts │ │ ├── EmbedField.ts │ │ ├── EmbedVideo.ts │ │ ├── EmbedFooter.ts │ │ ├── EmbedImage.ts │ │ ├── EmbedAuthor.ts │ │ ├── EmbedThumbnail.ts │ │ └── EmbedBuilder.ts │ ├── Collectors │ │ ├── BaseCollector.ts │ │ ├── MessageReactionCollector.ts │ │ └── MessageCollector.ts │ ├── AsyncronousQueue.ts │ ├── EventListener.ts │ ├── Endpoints.ts │ └── Constants.ts ├── Oauth2 │ └── Oauth2.ts └── index.ts ├── .npmignore ├── .gitignore ├── tests ├── package.json ├── src │ ├── decorator.ts │ └── builder.ts └── tsconfig.json ├── tsconfig.json ├── package.json ├── scripts ├── nodetodeno.js └── gendocs.js └── README.md /esm/index.mjs: -------------------------------------------------------------------------------- 1 | export * from "./dist/index.js"; 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://paypal.me/roahgaming 2 | -------------------------------------------------------------------------------- /src/Client/Managers/RolesManager.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { Role } from "../../Structures/Guild/Role"; 3 | 4 | export class RolesManager extends Objex {} 5 | -------------------------------------------------------------------------------- /src/Client/Managers/UsersManager.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { User } from "../../Structures/User/User"; 3 | 4 | export class UsersManager extends Objex {} 5 | -------------------------------------------------------------------------------- /src/Client/Managers/EmojisManager.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { Emoji } from "../../Structures/Guild/Emoji"; 3 | 4 | export class EmojisManager extends Objex {} 5 | -------------------------------------------------------------------------------- /src/Client/Managers/MessagesManager.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { Message } from "../../Structures/Message/Message"; 3 | 4 | export class MessagesManager extends Objex {} 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | .gitignore 3 | test.js 4 | .npmignore 5 | tsconfig.json 6 | tsconfig.buildinfo 7 | node_modules 8 | .github 9 | .idea 10 | .vscode 11 | package-lock.json 12 | docs.json 13 | eslintrc.json 14 | tests -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | TestBot/ 2 | test.js 3 | test.ts 4 | tsconfig.tsbuildinfo 5 | 6 | package-lock.json 7 | yarn.lock 8 | docs.json 9 | dist/ 10 | node_modules/ 11 | 12 | .idea/ 13 | .vscode/ 14 | 15 | config.ts 16 | 17 | deno/ 18 | *.log -------------------------------------------------------------------------------- /src/Client/ClientOptions.ts: -------------------------------------------------------------------------------- 1 | export interface ClientOptions { 2 | enableGuildCache: boolean; 3 | enableChannelCache: boolean; 4 | enableEmojiCache: boolean; 5 | enableUsersCache: boolean; 6 | enableMessageCache: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /src/Interfaces/OverwriteOptions.ts: -------------------------------------------------------------------------------- 1 | export interface IOverwrite { 2 | id: string; // Role or user ID 3 | type: "role" | "member"; // Either "role" or "member" 4 | allow: number; // Permission bit set 5 | deny: number; // Permission bit set 6 | } 7 | -------------------------------------------------------------------------------- /tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tests", 3 | "version": "1.0.0", 4 | "description": "tests of evolvejs", 5 | "main": "dist/builder.js", 6 | "scripts": { 7 | "test": "node ." 8 | }, 9 | "author": "echo-3-1", 10 | "license": "AGPL-3.0-or-later" 11 | } 12 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/USER_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, User } from "../../.."; 2 | 3 | export default class { 4 | constructor(client: EvolveClient, payload: Payload, shard: number) { 5 | client.emit(EVENTS.USER_UPDATE, new User(payload.d), shard); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/VOICE_SERVER_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload } from "../../.."; 2 | 3 | export default class { 4 | constructor(client: EvolveClient, payload: Payload, shard: number) { 5 | client.emit(EVENTS.VOICE_SERVER_UPDATE, payload, shard); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/INVITE_CREATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Invite } from "../../.."; 2 | 3 | export default class { 4 | constructor(client: EvolveClient, payload: Payload, shard: number) { 5 | const invite = new Invite(payload.d, client); 6 | client.emit(EVENTS.INVITE_CREATE, invite, shard); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/INVITE_DELETE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Invite } from "../../.."; 2 | 3 | export default class { 4 | constructor(client: EvolveClient, payload: Payload, shard: number) { 5 | const invite = new Invite(payload.d, client); 6 | client.emit(EVENTS.INVITE_DELETE, invite, shard); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/PRESENCE_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, PresenceUpdate } from "../../.."; 2 | 3 | export default class { 4 | constructor(client: EvolveClient, payload: Payload, shard: number) { 5 | const presence = new PresenceUpdate(payload.d, client); 6 | client.emit(EVENTS.PRESENCE_UPDATE, presence, shard); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/WEBHOOKS_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload } from "../../.."; 2 | import { Webhook } from "../../../Structures/Guild/Webhook"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | client.emit(EVENTS.WEBHOOKS_UPDATE, new Webhook(payload.d, client), shard); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Interfaces/MessageReactionOptions.ts: -------------------------------------------------------------------------------- 1 | import { 2 | IGuild, 3 | IGuildMember, 4 | IUser, 5 | ITextChannel, 6 | IEmoji, 7 | IMessage, 8 | } from "../"; 9 | 10 | export interface IMessageReaction { 11 | guild: IGuild; 12 | member: IGuildMember; 13 | user: IUser; 14 | channel: ITextChannel; 15 | emoji: IEmoji; 16 | message: IMessage; 17 | } 18 | -------------------------------------------------------------------------------- /src/Client/Events/ChannelEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { Channel } from "../../Structures/Channel/Channel"; 4 | 5 | export class ChannelEvents extends BaseEvent { 6 | constructor(client: EvolveClient, public channel: Channel, shard: number) { 7 | super(shard, client); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/VOICE_STATE_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload } from "../../.."; 2 | import { VoiceState } from "../../../Structures/Guild/VoiceState"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | client.emit( 7 | EVENTS.VOICE_STATE_UPDATE, 8 | new VoiceState(payload.d, client), 9 | shard 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Client/Events/GuildEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { Guild } from "../../Structures/Guild/Guild"; 4 | 5 | export class GuildEvents extends BaseEvent { 6 | constructor(client: EvolveClient, public guild: Guild, shard: number) { 7 | super(shard, client); 8 | 9 | this.guild = new (this.client.structures.get("Guild"))(guild.data, client); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Client/RestAPI/DiscordRejection.ts: -------------------------------------------------------------------------------- 1 | export default class DiscordRejection extends Error { 2 | raw; 3 | constructor(struct: { 4 | msg: string; 5 | code: number; 6 | http: number; 7 | path: string; 8 | }) { 9 | super(); 10 | this.name = "DiscordRejection"; 11 | this.message = `API call rejected with status ${struct?.http}. Message: ${struct?.msg}. Endpoint path: ${struct?.path}. Code: ${struct?.code}`; 12 | this.raw = struct; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Client/Events/GuildIntegrationEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { Guild } from "../../Structures/Guild/Guild"; 4 | 5 | export class GuildIntegrationEvents extends BaseEvent { 6 | constructor(client: EvolveClient, public guild: Guild, shard: number) { 7 | super(shard, client); 8 | 9 | this.guild = new (this.client.structures.get("Guild"))(guild.data, client); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Interfaces/VoiceRegionOptions.ts: -------------------------------------------------------------------------------- 1 | export interface IVoiceRegion { 2 | id: string; // Unique ID for the region 3 | name: string; // Name of the region 4 | vip: boolean; // Whether this is a vip-only server 5 | optimal: boolean; // Whether this is closest to the current user's client 6 | deprecated: boolean; // Whether this is a deprecated voice region (avoid switching to these) 7 | custom: boolean; // Whether this is a custom voice region (used for events/etc) 8 | } 9 | -------------------------------------------------------------------------------- /src/Interfaces/DMChannelOptions.ts: -------------------------------------------------------------------------------- 1 | import { CHANNELTYPES } from ".."; 2 | import { IUser } from "./UserOptions"; 3 | 4 | export interface IDMChannel { 5 | id: string; // The ID of this channel 6 | type: CHANNELTYPES.Direct; // The type of channel 7 | last_message_id?: string | null; // The id of the last message sent in this channel 8 | recipients: IUser[]; // The recipients of the DM 9 | last_pin_timestamp?: number; // Timestamp of the last pinned message 10 | } 11 | -------------------------------------------------------------------------------- /src/Interfaces/RoleOptions.ts: -------------------------------------------------------------------------------- 1 | export interface IRole { 2 | id: string; // Role ID 3 | name: string; // Role name 4 | color: number; // Integer representation of hexadecimal color code 5 | hoist: boolean; // Whether the role is separately hoisted 6 | position: number; // Position of this role 7 | permissions: number; // Permission bit set 8 | managed: boolean; // Whether this role is managed by an integration 9 | mentionable: boolean; // Whether this role is mentionable 10 | } 11 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Run Tests 2 | on: 3 | pull_request: 4 | branches: [development] 5 | push: 6 | branches: [development] 7 | jobs: 8 | Tests: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@master 13 | with: 14 | node-version: 15 15 | - name: Tests 16 | run: yarn && tsc && cd tests && tsc && node dist/builder 17 | env: 18 | DISCORD_TOKEN: ${{secrets.BOT_TOKEN}} 19 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Guild } from "../../.."; 2 | import { GuildEvents } from "../../Events/GuildEvents"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | let guild = payload.d; 7 | guild = new Guild(guild, client); 8 | if (client.options.enableGuildCache) client.guilds.set(guild.id, guild); 9 | client.emit(EVENTS.GUILD_UPDATE, new GuildEvents(client, guild, shard)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Decorators/Events.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { EvolveClient } from "../Client/EvolveClient"; 3 | 4 | export const listeners = new Objex, EvolveClient>(); 5 | 6 | export function Event(eventName?: string) { 7 | return ( 8 | target: EvolveClient, 9 | propertyKey: string, 10 | propertyDescriptor: PropertyDescriptor 11 | ): void => { 12 | if (propertyDescriptor.writable) 13 | listeners.set([eventName ?? propertyKey, propertyKey], target); 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/Client/ClientUser.ts: -------------------------------------------------------------------------------- 1 | import { User } from "../Structures/User/User"; 2 | 3 | export class ClientUser extends User { 4 | constructor( 5 | public name: string, 6 | public discriminator: string, 7 | public verfied: boolean, 8 | public id: string, 9 | public flags: number, 10 | public email: string, 11 | public bot: boolean, 12 | public avatar: string 13 | ) { 14 | super({ 15 | id, 16 | avatar, 17 | username: name, 18 | discriminator, 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Interfaces/CategoryChannelOptions.ts: -------------------------------------------------------------------------------- 1 | import { CHANNELTYPES } from ".."; 2 | import { IOverwrite } from "./OverwriteOptions"; 3 | 4 | export interface ICategoryChannel { 5 | id: string; // The ID of this channel 6 | type: CHANNELTYPES.Category; // The type of channel 7 | guild_id: string; // The ID of the guild 8 | position: number; // Sorting position of the channel 9 | permission_overwrites: IOverwrite[]; // Explicit permission overwrites for members and roles 10 | name: string; // The name of the channel 11 | } 12 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_REACTION_ADD.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, MessageReaction } from "../../.."; 2 | import { MessageReactionEvents } from "../../Events/MessageReactionEvents"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | client.emit( 7 | EVENTS.MESSAGE_REACTION_ADD, 8 | new MessageReactionEvents( 9 | client, 10 | new MessageReaction(payload.d, client), 11 | shard 12 | ) 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_REACTION_REMOVE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, MessageReaction } from "../../.."; 2 | import { MessageReactionEvents } from "../../Events/MessageReactionEvents"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | client.emit( 7 | EVENTS.MESSAGE_REACTION_REMOVE, 8 | new MessageReactionEvents( 9 | client, 10 | new MessageReaction(payload.d, client), 11 | shard 12 | ) 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_REACTION_REMOVE_ALL.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, MessageReaction } from "../../.."; 2 | import { MessageReactionEvents } from "../../Events/MessageReactionEvents"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | client.emit( 7 | EVENTS.MESSAGE_REACTION_REMOVE_All, 8 | new MessageReactionEvents( 9 | client, 10 | new MessageReaction(payload.d, client), 11 | shard 12 | ) 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/CHANNEL_DELETE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload } from "../../.."; 2 | import { ChannelEvents } from "../../Events/ChannelEvents"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | (async () => { 7 | const o = await client.channels.resolve(payload.d.id); 8 | if (client.options.enableChannelCache) 9 | client.channels.delete(o!!.id, true); 10 | client.emit(EVENTS.CHANNEL_DELETE, new ChannelEvents(client, o!!, shard)); 11 | })(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_REACTION_REMOVE_EMOJI.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, MessageReaction } from "../../.."; 2 | import { MessageReactionEvents } from "../../Events/MessageReactionEvents"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | client.emit( 7 | EVENTS.MESSAGE_REACTION_REMOVE_EMOJI, 8 | new MessageReactionEvents( 9 | client, 10 | new MessageReaction(payload.d, client), 11 | shard 12 | ) 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Structures/Channel/Channel.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient } from "../../Client/EvolveClient"; 2 | import { CHANNELTYPES } from "../../Utils/Constants"; 3 | 4 | export class Channel { 5 | public client!: EvolveClient; 6 | public id: string; 7 | public type: CHANNELTYPES; 8 | 9 | constructor(id: string, type: CHANNELTYPES, client: EvolveClient) { 10 | Object.defineProperty(this, "client", { 11 | value: client, 12 | enumerable: false, 13 | writable: false, 14 | }); 15 | this.id = id; 16 | this.type = type; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Interfaces/GuildMemberOptions.ts: -------------------------------------------------------------------------------- 1 | import { IUser } from "./UserOptions"; 2 | 3 | export interface IGuildMember { 4 | user?: IUser; // The member's user object 5 | nick: string | null; // This users guild nickname 6 | roles: string[]; // Array of role IDs 7 | joined_at: number; // Timestamp when the user joined the guild 8 | premium_since?: number | null; // Timestamp when the user started boosting the guild 9 | deaf: boolean; // Whether the user is deafened in voice channels 10 | mute: boolean; // Whether the user is muted in voice channels 11 | } 12 | -------------------------------------------------------------------------------- /src/Client/Managers/GuildsManager.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { Guild } from "../../Structures/Guild/Guild"; 3 | import { Endpoints } from "../../Utils/Endpoints"; 4 | import { EvolveClient } from "../EvolveClient"; 5 | 6 | export class GuildsManager extends Objex { 7 | constructor(public client: EvolveClient) { 8 | super(); 9 | } 10 | 11 | public async resolve(id: string): Promise { 12 | return new Guild( 13 | await this.client.rest.endpoint(Endpoints.GUILD).get(id), 14 | this.client 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Utils/Embed/MessageEmbed.ts: -------------------------------------------------------------------------------- 1 | import { 2 | IEmbedFooter, 3 | IEmbedImage, 4 | IEmbedVideo, 5 | IEmbedProvider, 6 | IEmbedAuthor, 7 | IEmbedField, 8 | } from "../.."; 9 | 10 | export interface MessageEmbed { 11 | title: string; 12 | type: string; 13 | description: string; 14 | url: string; 15 | timestamp: number; 16 | color: number; 17 | footer: IEmbedFooter; 18 | image: IEmbedImage; 19 | thumnail: IEmbedImage; 20 | video: IEmbedVideo; 21 | provider: IEmbedProvider; 22 | author: IEmbedAuthor; 23 | fields: Array; 24 | } 25 | -------------------------------------------------------------------------------- /src/Client/Events/MessageReactionEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { MessageReaction } from "../../Structures/Message/MessageReaction"; 4 | 5 | export class MessageReactionEvents extends BaseEvent { 6 | constructor( 7 | client: EvolveClient, 8 | public reaction: MessageReaction, 9 | shard: number 10 | ) { 11 | super(shard, client); 12 | 13 | this.reaction = new (client.structures.get("MessageReaction"))( 14 | reaction.data, 15 | client 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Client/Events/MessageEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { Message } from "../../Structures/Message/Message"; 4 | import { Objex } from "@evolvejs/objex"; 5 | import { Guild } from "../../Structures/Guild/Guild"; 6 | import { TextChannel } from "../../Structures/Channel/TextChannel"; 7 | 8 | export class MessageEvents< 9 | K = Message | Objex 10 | > extends BaseEvent { 11 | constructor(client: EvolveClient, public message: K, shard: number) { 12 | super(shard, client); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/TYPING_START.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, GuildMember } from "../../.."; 2 | 3 | export default class { 4 | constructor(client: EvolveClient, payload: Payload, shard: number) { 5 | const { channel_id, guild_id, user_id, timestamp, member } = payload.d; 6 | (async () => 7 | client.emit( 8 | EVENTS.TYPING_START, 9 | await client.channels.resolve(channel_id), 10 | client.guilds.get(guild_id), 11 | client.users.get(user_id), 12 | timestamp, 13 | new GuildMember(member), 14 | shard 15 | ))(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Interfaces/EmojiOptions.ts: -------------------------------------------------------------------------------- 1 | import { IRole } from "./RoleOptions"; 2 | import { IUser } from "./UserOptions"; 3 | 4 | export interface IEmoji { 5 | id: string | null; // ID of the emoji 6 | name: string | null; // Name of the emoji 7 | roles?: IRole[]; // Roles the emoji is available to 8 | user: IUser; // User who added the emoji 9 | require_colons?: boolean; // Whether it needs to be wrapped in colons 10 | managed?: boolean; // Whether it is managed 11 | animated?: boolean; // Whether the emoji is animated 12 | available?: boolean; // May be false due to loss of Server Boosts 13 | } 14 | -------------------------------------------------------------------------------- /src/Client/Events/BaseEvent.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient } from "../EvolveClient"; 2 | import { EvolveSocket } from "../Websocket/Websocket"; 3 | 4 | export class BaseEvent { 5 | constructor(private _shard: number, private _client: EvolveClient) {} 6 | 7 | get shard(): EvolveSocket { 8 | const shardConnection = this._client.sharder.connections.get(this._shard); 9 | if (!shardConnection) { 10 | throw this.client.transformer.error( 11 | "Internal Error (Shard Websocket Not Found)" 12 | ); 13 | } 14 | return shardConnection; 15 | } 16 | 17 | get client(): EvolveClient { 18 | return this._client; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Client/Events/GuildBanEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { User } from "../../Structures/User/User"; 3 | import { Guild } from "../../Structures/Guild/Guild"; 4 | import { EvolveClient } from "../EvolveClient"; 5 | 6 | export class GuildBanEvents extends BaseEvent { 7 | constructor( 8 | client: EvolveClient, 9 | public user: User, 10 | public guild: Guild, 11 | shard: number 12 | ) { 13 | super(shard, client); 14 | this.guild = new (this.client.structures.get("Guild"))(guild.data, client); 15 | this.user = new (this.client.structures.get("User"))(user.data); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/src/decorator.ts: -------------------------------------------------------------------------------- 1 | import { Builder, EvolveClient, Event } from "../../dist"; 2 | import { argv } from "process"; 3 | 4 | @Builder({ 5 | token: argv[2] ?? process.env.DISCORD_TOKEN, 6 | useDefaultSetting: true, 7 | }) 8 | class _ extends EvolveClient { 9 | @Event() 10 | public clientReady() { 11 | console.log("[Client: EvolveClient] => Ready"); 12 | this.sharder.destroyAll(0); 13 | } 14 | 15 | @Event() 16 | public shardSpawn(id: string) { 17 | console.log(`[Shard: ${id}] => Spawned`); 18 | } 19 | 20 | @Event() 21 | public shardDestroy(id: string) { 22 | console.log(`[Shard: ${id}] => Destroyed`); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "./dist", 6 | "rootDir": "./src/", 7 | "lib": ["es6", "ESNext"], 8 | "declaration": false, 9 | "experimentalDecorators": true, 10 | "emitDecoratorMetadata": true, 11 | "strict": true, 12 | "strictNullChecks": true, 13 | "noImplicitThis": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "skipDefaultLibCheck": true, 17 | "esModuleInterop": true, 18 | "rootDirs": ["./src/"] 19 | }, 20 | "include": ["./src/"], 21 | "exclude": ["node_modules", "dist"] 22 | } 23 | -------------------------------------------------------------------------------- /src/Interfaces/WebhookOptions.ts: -------------------------------------------------------------------------------- 1 | import { WEBHOOKTYPE } from ".."; 2 | import { IUser } from "./UserOptions"; 3 | 4 | export interface IWebhook { 5 | id: string; // The ID of the webhook 6 | type: WEBHOOKTYPE; // The type of the webhook 7 | guild_id?: string; // The guild ID this webhook is for 8 | channel_id: string; // The channel ID this webhook is for 9 | user?: IUser; // The user this webhook was created by 10 | name: string | null; // The default name of the webhook 11 | avatar: string | null; // The default avatar of the webhook 12 | token?: string; // The secure token of the webhook (returned for Incoming Webhooks) 13 | } 14 | -------------------------------------------------------------------------------- /src/Client/Events/GuildRoleEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { Role } from "../../Structures/Guild/Role"; 4 | import { Guild } from "../../Structures/Guild/Guild"; 5 | 6 | export class GuildRoleEvents extends BaseEvent { 7 | constructor( 8 | client: EvolveClient, 9 | public role: Role | undefined, 10 | public guild: Guild, 11 | shard: number 12 | ) { 13 | super(shard, client); 14 | 15 | if (role) this.role = new (this.client.structures.get("Role"))(role.data); 16 | this.guild = new (this.client.structures.get("Guild"))(guild.data, client); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedProvider.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | import { URL } from "url"; 3 | 4 | export interface IEmbedProvider { 5 | name: string; 6 | url: string; 7 | } 8 | 9 | export class EmbedProviderBuilder { 10 | private name!: string; 11 | private url!: string; 12 | 13 | public setName(name: string): EmbedProviderBuilder { 14 | this.name = name; 15 | return this; 16 | } 17 | 18 | public setURL(url: URL): EmbedProviderBuilder { 19 | this.url = url.toString(); 20 | return this; 21 | } 22 | 23 | public build(): IEmbedProvider { 24 | return { 25 | name: this.name, 26 | url: this.url, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_CREATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Guild } from "../../.."; 2 | import { GuildEvents } from "../../Events/GuildEvents"; 3 | 4 | export default class { 5 | constructor(client: EvolveClient, payload: Payload, shard: number) { 6 | const guild = payload.d; 7 | if (client.guilds.has(guild.id)) { 8 | return; 9 | } else { 10 | const newGuild = new Guild(guild, client); 11 | if (client.options.enableGuildCache) 12 | client.guilds.set(newGuild.id, newGuild); 13 | 14 | client.emit( 15 | EVENTS.GUILD_CREATE, 16 | new GuildEvents(client, newGuild, shard) 17 | ); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Interfaces/Integration.ts: -------------------------------------------------------------------------------- 1 | import { IUser } from "./UserOptions"; 2 | 3 | enum expire_behavior { 4 | Remove_role, 5 | Kick, 6 | } 7 | interface IGuildIntegrationAccount { 8 | id: string; 9 | name: string; 10 | } 11 | export interface ICreateGuildIntegration { 12 | id: string; 13 | type: string; 14 | } 15 | export interface IGuildIntegration { 16 | id: string; 17 | name: string; 18 | type: string; 19 | enabled: boolean; 20 | syncing: boolean; 21 | role_id: string; 22 | enable_emoticons?: boolean; 23 | expire_behavior: expire_behavior; 24 | expire_grace_period: number; 25 | user: IUser; 26 | account: IGuildIntegrationAccount; 27 | synced_at: string; 28 | } 29 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "./dist", 6 | "rootDir": "./src/", 7 | "lib": ["es6", "ESNext"], 8 | "declaration": true, 9 | "experimentalDecorators": true, 10 | "emitDecoratorMetadata": true, 11 | "strict": true, 12 | "strictNullChecks": true, 13 | "noImplicitThis": true, 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "skipDefaultLibCheck": true, 17 | "esModuleInterop": true, 18 | "rootDirs": [ 19 | "./src/" 20 | ] 21 | }, 22 | "include": [ 23 | "./src/", 24 | ], 25 | "exclude": [ 26 | "node_modules", 27 | "dist", 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_DELETE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload } from "../../.."; 2 | import { TextChannel } from "../../../Structures/Channel/TextChannel"; 3 | import { MessageEvents } from "../../Events/MessageEvents"; 4 | 5 | export default class { 6 | constructor(client: EvolveClient, payload: Payload, shard: number) { 7 | const { id, guild_id, channel_id } = payload.d; 8 | const message = client.messages.get(id); 9 | const guild = client.guilds.get(guild_id); 10 | if (client.options.enableMessageCache) client.messages.delete(id); 11 | (async () => 12 | client.emit( 13 | EVENTS.MESSAGE_DELETE, 14 | new MessageEvents(client, message, shard) 15 | ))(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Structures/Miscs/ClientStatus.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | import { IClientStatus } from "../../"; 3 | 4 | export class ClientStatus { 5 | public desktop?: string; 6 | public mobile?: string; 7 | public web?: string; 8 | public data!: IClientStatus; 9 | constructor(data: IClientStatus) { 10 | Object.defineProperty(this, "data", { 11 | value: data, 12 | enumerable: false, 13 | writable: false, 14 | }); 15 | this._handle(); 16 | } 17 | 18 | private _handle() { 19 | if (!this.data) return; 20 | this.desktop = this.data.desktop; 21 | this.mobile = this.data.mobile; 22 | this.web = this.data.web; 23 | return this; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Interfaces/GroupChannelOptions.ts: -------------------------------------------------------------------------------- 1 | import { CHANNELTYPES } from ".."; 2 | import { IUser } from "./UserOptions"; 3 | 4 | export interface IGroupChannel { 5 | id: string; // The ID of this channel 6 | type: CHANNELTYPES.Group; // The type of channel 7 | name?: string; // The name of the channel 8 | last_message_id?: string | null; // The id of the last message sent in this channel 9 | recipients: IUser[]; // The recipients of the DM 10 | icon?: string | null; // Icon hash 11 | owner_id: string; // ID of the DM creator 12 | application_id?: string; // Application id of the group DM creator if it is bot-created 13 | last_pin_timestamp?: number; // Timestamp when the last pinned message was pinned 14 | } 15 | -------------------------------------------------------------------------------- /src/Interfaces/VoiceChannelOptions.ts: -------------------------------------------------------------------------------- 1 | import { CHANNELTYPES } from ".."; 2 | import { IOverwrite } from "./OverwriteOptions"; 3 | 4 | export interface IVoiceChannel { 5 | id: string; // The ID of this channel 6 | type: CHANNELTYPES.Voice; // The type of channel 7 | guild_id: string; // The ID of the guild 8 | position: number; // Sorting position of the channel 9 | permission_overwrites: IOverwrite[]; // Explicit permission overwrites for members and roles 10 | name: string; // The name of the channel 11 | bitrate: number; // The bitrate (in bits) of the voice channel 12 | user_limit: number; // The user limit of the voice channel 13 | parent_id?: string | null; // ID of the parent category for a channel 14 | } 15 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EvolveClient, 3 | EVENTS, 4 | Payload, 5 | Message, 6 | Guild, 7 | Endpoints, 8 | IGuild, 9 | ITextChannel, 10 | TextChannel, 11 | } from "../../.."; 12 | import { MessageEvents } from "../../Events/MessageEvents"; 13 | 14 | export default class { 15 | constructor(client: EvolveClient, payload: Payload, shard: number) { 16 | let message: Message; 17 | async () => { 18 | message = new Message(payload.d, client); 19 | if (client.options.enableMessageCache) 20 | client.messages.set(message.id, message); 21 | client.emit( 22 | EVENTS.MESSAGE_UPDATE, 23 | new MessageEvents(client, message, shard) 24 | ); 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_DELETE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Endpoints } from "../../.."; 2 | import { IGuild } from "../../../Interfaces/GuildOptions"; 3 | import { Guild } from "../../../Structures/Guild/Guild"; 4 | import { GuildEvents } from "../../Events/GuildEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | const o = new Guild( 10 | await client.rest.endpoint(Endpoints.GUILD).get(payload.d), 11 | client 12 | ); 13 | if (client.options.enableGuildCache) client.guilds.delete(o.id); 14 | client.emit(EVENTS.GUILD_DELETE, new GuildEvents(client, o, shard)); 15 | })(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Structures/Channel/Overwrite.ts: -------------------------------------------------------------------------------- 1 | import { IOverwrite } from "../../Interfaces/OverwriteOptions"; 2 | 3 | export class Overwrite { 4 | public id!: string; 5 | public type!: IOverwrite["type"]; 6 | public allow!: number; 7 | public deny!: number; 8 | public data!: IOverwrite; 9 | 10 | constructor(data: IOverwrite) { 11 | Object.defineProperty(this, "data", { 12 | value: data, 13 | enumerable: false, 14 | writable: false, 15 | }); 16 | this._handle(); 17 | } 18 | 19 | private _handle() { 20 | if (!this.data) return; 21 | this.id = this.data.id; 22 | this.type = this.data.type; 23 | this.allow = this.data.allow; 24 | this.deny = this.data.deny; 25 | 26 | return this; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Interfaces/StoreChannelOptions.ts: -------------------------------------------------------------------------------- 1 | import { CHANNELTYPES } from ".."; 2 | import { IOverwrite } from "./OverwriteOptions"; 3 | 4 | export interface IStoreChannel { 5 | id: string; // The ID of this channel 6 | type: CHANNELTYPES.Store; // The type of channel 7 | guild_id: string; // The ID of the guild 8 | position: number; // Sorting position of the channel 9 | permission_overwrites: IOverwrite[]; // Explicit permission overwrites for members and roles 10 | name: string; // The name of the channel 11 | nsfw: boolean; // wWhether the channel is nsfw 12 | rate_limit_per_user: number; // Amount of seconds a user has to wait before sending another message (0-21600) 13 | parent_id?: string | null; // ID of the parent category for a channel 14 | } 15 | -------------------------------------------------------------------------------- /src/Interfaces/InviteOptions.ts: -------------------------------------------------------------------------------- 1 | import { ChannelResolvable } from ".."; 2 | import { IGuild } from "./GuildOptions"; 3 | import { IUser } from "./UserOptions"; 4 | 5 | export interface IInvite { 6 | code: string; // The invite code (unique ID) 7 | guild?: IGuild; // The guild this invite is for 8 | channel: ChannelResolvable; // The channel this invite is for 9 | inviter?: IUser; // The user who created the invite 10 | target_user?: IUser; // The target user for this invite 11 | target_user_type?: number; // The type of user target for this invite 12 | approximate_presence_count?: number; // Approximate count of online members (only present when target_user is set) 13 | approximate_member_count?: number; // Approximate count of total members 14 | } 15 | -------------------------------------------------------------------------------- /tests/src/builder.ts: -------------------------------------------------------------------------------- 1 | import { EvolveBuilder, EvolveClient, EVENTS } from "../../dist"; 2 | import { argv } from "process"; 3 | 4 | const client: EvolveClient = new EvolveBuilder() 5 | .setToken(argv[2] ?? process.env.DISCORD_TOKEN ?? "...") 6 | .build(); 7 | 8 | client.sharder.on("shardSpawn", (id: number) => { 9 | console.log(`[Shard: ${id}] => Spawned`); 10 | }); 11 | 12 | client.sharder.on("shardDestroy", (id: number) => { 13 | console.log(`[Shard: ${id}] => Destroyed`); 14 | }); 15 | 16 | client.on("clientReady", () => { 17 | console.log("[Client: EvolveClient] => Ready"); 18 | for (const [k, _] of client.guilds) { 19 | client.logger.debug(client.sharder.getguildShardId(k).toString()); 20 | } 21 | }); 22 | 23 | client.on(EVENTS.MESSAGE_CREATE, console.log); 24 | -------------------------------------------------------------------------------- /src/Utils/Collectors/BaseCollector.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | /* eslint-disable @typescript-eslint/ban-types */ 3 | import { EvolveClient, Message } from "../../"; 4 | import { Objex } from "@evolvejs/objex"; 5 | import { MessageReaction } from "../../Structures/Message/MessageReaction"; 6 | import { EventListener } from "../EventListener"; 7 | 8 | export class BaseCollector extends EventListener { 9 | public listener!: (...args: any[]) => void; 10 | 11 | private _collected: Objex = new Objex(); 12 | constructor(public client: EvolveClient, public filter: Function) { 13 | super(); 14 | } 15 | 16 | get collected(): Objex { 17 | return this._collected; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Client/Events/GuildEmojiEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { Emoji } from "../../Structures/Guild/Emoji"; 4 | import { Guild } from "../../Structures/Guild/Guild"; 5 | import { Objex } from "@evolvejs/objex"; 6 | 7 | export class GuildEmojiEvents extends BaseEvent { 8 | constructor( 9 | client: EvolveClient, 10 | public emoji: Objex, 11 | public guild: Guild, 12 | shard: number 13 | ) { 14 | super(shard, client); 15 | 16 | this.guild = new (this.client.structures.get("Guild"))(guild.data, client); 17 | for (const [k, v] of emoji) { 18 | this.emoji.delete(k); 19 | 20 | this.emoji.set(k, new (this.client.structures.get("Emoji"))(v.data)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_ROLE_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EvolveClient, 3 | EVENTS, 4 | Payload, 5 | Role, 6 | Endpoints, 7 | IGuild, 8 | } from "../../.."; 9 | import { Guild } from "../../../Structures/Guild/Guild"; 10 | import { GuildRoleEvents } from "../../Events/GuildRoleEvents"; 11 | 12 | export default class { 13 | constructor(client: EvolveClient, payload: Payload, shard: number) { 14 | (async () => { 15 | const { guild_id, role } = payload.d; 16 | const guild = new Guild( 17 | await client.rest.endpoint(Endpoints.GUILD).get(guild_id), 18 | client 19 | ); 20 | 21 | client.emit( 22 | EVENTS.GUILD_ROLE_UPDATE, 23 | new GuildRoleEvents(client, new Role(role), guild, shard) 24 | ); 25 | })(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_INTEGRATIONS_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Endpoints } from "../../.."; 2 | import { IGuild } from "../../../Interfaces/GuildOptions"; 3 | import { Guild } from "../../../Structures/Guild/Guild"; 4 | import { GuildIntegrationEvents } from "../../Events/GuildIntegrationEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | const guild = new Guild( 10 | await client.rest 11 | .endpoint(Endpoints.GUILD) 12 | .get(payload.d.guild), 13 | client 14 | ); 15 | client.emit( 16 | EVENTS.GUILD_INTEGRATIONS_UPDATE, 17 | new GuildIntegrationEvents(client, guild, shard) 18 | ); 19 | })(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/CHANNEL_PINS_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload } from "../../.."; 2 | import { ChannelResolver } from "../../../Utils/Constants"; 3 | import { Endpoints } from "../../../Utils/Endpoints"; 4 | import { ChannelEvents } from "../../Events/ChannelEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | const { channel_id } = payload.d(async () => { 9 | const channel = await client.rest 10 | .endpoint(Endpoints.CHANNEL) 11 | .get(channel_id); 12 | client.emit( 13 | EVENTS.CHANNEL_PINS_UPDATE, 14 | new ChannelEvents( 15 | client, 16 | new ChannelResolver[channel.type](channel, client), 17 | shard 18 | ) 19 | ); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_ROLE_DELETE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Endpoints } from "../../.."; 2 | import { IGuild } from "../../../Interfaces/GuildOptions"; 3 | import { Guild } from "../../../Structures/Guild/Guild"; 4 | import { GuildRoleEvents } from "../../Events/GuildRoleEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | const { guild_id, role_id } = payload.d; 10 | const guild = await client.rest 11 | .endpoint(Endpoints.GUILD) 12 | .get(guild_id); 13 | const role = client.roles.get(role_id); 14 | 15 | client.emit( 16 | EVENTS.GUILD_ROLE_DELETE, 17 | new GuildRoleEvents(client, role, new Guild(guild, client), shard) 18 | ); 19 | })(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/CHANNEL_CREATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload } from "../../.."; 2 | import { ChannelResolver } from "../../../Utils/Constants"; 3 | import { Endpoints } from "../../../Utils/Endpoints"; 4 | import { ChannelEvents } from "../../Events/ChannelEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | const o = await client.rest 10 | .endpoint(Endpoints.CHANNEL) 11 | .get(payload.d.id); 12 | if (client.options.enableChannelCache) 13 | client.channels.set(o.id, new ChannelResolver[o.type](o, client)); 14 | client.emit( 15 | EVENTS.CHANNEL_CREATE, 16 | new ChannelEvents(client, new ChannelResolver[o.type](o, client), shard) 17 | ); 18 | })(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedField.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | export interface IEmbedField { 3 | name: string; 4 | value: string; 5 | inline: boolean; 6 | } 7 | 8 | export class EmbedFieldBuilder { 9 | private name!: string; 10 | private value!: string; 11 | private inline = false; 12 | 13 | public setName(name: string): EmbedFieldBuilder { 14 | this.name = name; 15 | return this; 16 | } 17 | 18 | public setValue(value: string): EmbedFieldBuilder { 19 | this.value = value; 20 | return this; 21 | } 22 | 23 | public enableInline(inline: boolean): EmbedFieldBuilder { 24 | this.inline = inline; 25 | return this; 26 | } 27 | 28 | public build(): IEmbedField { 29 | return { 30 | name: this.name, 31 | value: this.value, 32 | inline: this.inline, 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Client/Events/GuildMemberEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { GuildMember } from "../../Structures/Guild/GuildMember"; 4 | import { Guild } from "../../Structures/Guild/Guild"; 5 | import { User } from "../../Structures/User/User"; 6 | 7 | export class GuildMemberEvent extends BaseEvent { 8 | constructor( 9 | client: EvolveClient, 10 | public member: GuildMember | User, 11 | public guild: Guild, 12 | shard: number 13 | ) { 14 | super(shard, client); 15 | 16 | if (member instanceof GuildMember) { 17 | this.member = new (this.client.structures.get("GuildMember"))( 18 | member.data 19 | ); 20 | } else if (member instanceof User) { 21 | this.member = new (this.client.structures.get("User"))(member.data); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_BAN_ADD.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EvolveClient, 3 | EVENTS, 4 | Payload, 5 | User, 6 | Endpoints, 7 | Guild, 8 | } from "../../.."; 9 | import { IGuild } from "../../../Interfaces/GuildOptions"; 10 | import { GuildBanEvents } from "../../Events/GuildBanEvents"; 11 | 12 | export default class { 13 | constructor(client: EvolveClient, payload: Payload, shard: number) { 14 | (async () => { 15 | // eslint-disable-next-line prefer-const 16 | let { guild_id, user } = payload.d; 17 | const guild = new Guild( 18 | await client.rest.endpoint(Endpoints.GUILD).get(guild_id), 19 | client 20 | ); 21 | user = new User(user); 22 | client.emit( 23 | EVENTS.GUILD_BAN_ADD, 24 | new GuildBanEvents(client, user, guild, shard) 25 | ); 26 | })(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_BAN_REMOVE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, User, Endpoints } from "../../.."; 2 | import { IGuild } from "../../../Interfaces/GuildOptions"; 3 | import { Guild } from "../../../Structures/Guild/Guild"; 4 | import { GuildBanEvents } from "../../Events/GuildBanEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | // eslint-disable-next-line prefer-const 10 | let { guild_id, user } = payload.d; 11 | const guild = await client.rest 12 | .endpoint(Endpoints.GUILD) 13 | .get(guild_id); 14 | user = new User(user); 15 | client.emit( 16 | EVENTS.GUILD_BAN_REMOVE, 17 | new GuildBanEvents(client, user, new Guild(guild, client), shard) 18 | ); 19 | })(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_ROLE_CREATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Role, Endpoints } from "../../.."; 2 | import { IGuild } from "../../../Interfaces/GuildOptions"; 3 | import { Guild } from "../../../Structures/Guild/Guild"; 4 | import { GuildRoleEvents } from "../../Events/GuildRoleEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | const { guild_id, role } = payload.d; 10 | const guild = await client.rest 11 | .endpoint(Endpoints.GUILD) 12 | .get(guild_id); 13 | 14 | client.emit( 15 | EVENTS.GUILD_ROLE_CREATE, 16 | new GuildRoleEvents( 17 | client, 18 | new Role(role), 19 | new Guild(guild, client), 20 | shard 21 | ) 22 | ); 23 | })(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_DELETE_BULK.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Message } from "../../.."; 2 | import { Objex } from "@evolvejs/objex"; 3 | import { MessageEvents } from "../../Events/MessageEvents"; 4 | import { TextChannel } from "../../../Structures/Channel/TextChannel"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | const { ids, channel_id, guild_id } = payload.d; 9 | const messageObjex: Objex = new Objex(); 10 | for (const id of ids) { 11 | messageObjex.set(id, client.messages.get(id)); 12 | if (client.options.enableMessageCache) client.messages.delete(id); 13 | } 14 | 15 | (async () => { 16 | client.emit( 17 | EVENTS.MESSAGE_DELETE_BULK, 18 | new MessageEvents(client, messageObjex, shard) 19 | ); 20 | })(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Utils/Collectors/MessageReactionCollector.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-types */ 2 | import { BaseCollector } from "./BaseCollector"; 3 | import { Objex } from "@evolvejs/objex"; 4 | import { Message, MessageReaction } from "../.."; 5 | 6 | export class MessageReactionCollector extends BaseCollector { 7 | constructor(public message: Message, public filter: Function) { 8 | super(message["client"], filter); 9 | this.message["client"].on( 10 | "reactionAdd", 11 | (this.listener = (msg: MessageReaction) => { 12 | filter(msg); 13 | }) 14 | ); 15 | } 16 | 17 | public end(): Objex { 18 | this.message["client"].off("reactionAdd", this.listener); 19 | return this.collected; 20 | } 21 | 22 | public handle(reaction: MessageReaction): void { 23 | this.collected.set(reaction.message.id, reaction); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedVideo.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | import { URL } from "url"; 3 | 4 | export interface IEmbedVideo { 5 | url: string; 6 | height: number; 7 | width: number; 8 | } 9 | 10 | export class EmbedVideoBuilder { 11 | private url!: string; 12 | private height!: number; 13 | private width!: number; 14 | 15 | public setURL(url: URL): EmbedVideoBuilder { 16 | this.url = url.toString(); 17 | return this; 18 | } 19 | 20 | public setHeight(height: number): EmbedVideoBuilder { 21 | this.height = height; 22 | return this; 23 | } 24 | 25 | public setWidth(width: number): EmbedVideoBuilder { 26 | this.width = width; 27 | return this; 28 | } 29 | 30 | public build(): IEmbedVideo { 31 | return { 32 | url: this.url, 33 | height: this.height, 34 | width: this.width, 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/CHANNEL_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Channel } from "../../.."; 2 | import { ChannelResolver } from "../../../Utils/Constants"; 3 | import { Endpoints } from "../../../Utils/Endpoints"; 4 | import { ChannelEvents } from "../../Events/ChannelEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | const channel = await client.rest 10 | .endpoint(Endpoints.CHANNEL) 11 | .get(payload.d.channel.id); 12 | if (client.options.enableChannelCache) 13 | client.channels.set( 14 | channel.id, 15 | new ChannelResolver[channel.type](channel, client) 16 | ); 17 | client.emit( 18 | EVENTS.CHANNEL_UPDATE, 19 | new ChannelEvents(client, channel, shard) 20 | ); 21 | })(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Interfaces/PresenceUpdateOptions.ts: -------------------------------------------------------------------------------- 1 | import { Visibility } from ".."; 2 | import { IActivity } from "./ActivityOptions"; 3 | import { IUser } from "./UserOptions"; 4 | 5 | export interface IPresenceUpdate { 6 | user: IUser; // The user presence is being updated for 7 | roles: string[]; // Roles this user is in 8 | game: IActivity | null; // The user's current activity 9 | guild_id: string; // ID of the guild 10 | status: Visibility; // The visibility status 11 | activities: []; // User's current activities 12 | client_status: IClientStatus; // User's platform-dependent status 13 | premium_since?: number | null; // When the user started boosting the guild 14 | nick?: string | null; // Guild nickname 15 | } 16 | 17 | export interface IClientStatus { 18 | desktop?: Visibility; // Desktop platform status 19 | mobile?: Visibility; // Mobile platform status 20 | web?: Visibility; // Web browser status 21 | } 22 | -------------------------------------------------------------------------------- /src/Structures/Channel/DMChannel.ts: -------------------------------------------------------------------------------- 1 | import { User, IDMChannel, EvolveClient, CHANNELTYPES } from "../.."; 2 | import { Objex } from "@evolvejs/objex"; 3 | import { Channel } from "./Channel"; 4 | 5 | export class DMChannel extends Channel { 6 | public recipients: Objex = new Objex(); 7 | 8 | public lastMessage?: string; 9 | public lastPin?: number; 10 | public data!: IDMChannel; 11 | 12 | constructor(data: IDMChannel, client: EvolveClient) { 13 | super(data.id, CHANNELTYPES.Direct, client); 14 | Object.defineProperty(this, "data", { 15 | value: data, 16 | enumerable: false, 17 | writable: false, 18 | }); 19 | 20 | this._handle(); 21 | } 22 | 23 | private _handle() { 24 | if (!this.data) return; 25 | this.lastMessage = this.data.last_message_id || undefined; 26 | this.lastPin = this.data.last_pin_timestamp; 27 | 28 | return this; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_MEMBER_REMOVE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, User, Endpoints } from "../../.."; 2 | import { IGuild } from "../../../Interfaces/GuildOptions"; 3 | import { Guild } from "../../../Structures/Guild/Guild"; 4 | import { GuildMemberEvent } from "../../Events/GuildMemberEvents"; 5 | 6 | export default class { 7 | constructor(client: EvolveClient, payload: Payload, shard: number) { 8 | (async () => { 9 | const guild = await client.rest 10 | .endpoint(Endpoints.GUILD) 11 | .get(payload.d.guild_id); 12 | if (client.options.enableUsersCache) 13 | client.users.delete(payload.d.user.id); 14 | client.emit( 15 | EVENTS.GUILD_MEMBER_REMOVE, 16 | new GuildMemberEvent( 17 | client, 18 | new User(payload.d.user), 19 | new Guild(guild, client), 20 | shard 21 | ) 22 | ); 23 | })(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Interfaces/VoiceStateOptions.ts: -------------------------------------------------------------------------------- 1 | import { IGuildMember } from "./GuildMemberOptions"; 2 | 3 | export interface IVoiceState { 4 | guild_id?: string; // The guild ID this voice state is for 5 | channel_id: string | null; // The channel ID this user is connected to 6 | user_id: string; // The user ID this voice state is for 7 | member?: IGuildMember; // The guild member this voice state is for 8 | session_id: string; // The session ID for this voice state 9 | deaf: boolean; // Whether this user is deafened by the server 10 | mute: boolean; // Whether this user is muted by the server 11 | self_deaf: boolean; // Whether this user is locally deafened 12 | self_mute: boolean; // Whether this user is locally muted 13 | self_stream?: boolean; // Whether this user is streaming using "Go Live" 14 | self_video: boolean; // Whether this user's camera is enabled 15 | suppress: boolean; // Whether this user is muted by the current user 16 | } 17 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedFooter.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | import { URL } from "url"; 3 | 4 | export interface IEmbedFooter { 5 | text: string; 6 | icon_url: string; 7 | proxy_icon_url: string; 8 | } 9 | 10 | export class EmbedFooterBuilder { 11 | private text!: string; 12 | private iconUrl!: string; 13 | private proxyIconUrl!: string; 14 | 15 | public setText(text: string): EmbedFooterBuilder { 16 | this.text = text; 17 | return this; 18 | } 19 | 20 | public setIconUrl(url: URL): EmbedFooterBuilder { 21 | this.iconUrl = url.toString(); 22 | return this; 23 | } 24 | 25 | public setProxyIconUrl(url: URL): EmbedFooterBuilder { 26 | this.proxyIconUrl = url.toString(); 27 | return this; 28 | } 29 | 30 | public build(): IEmbedFooter { 31 | return { 32 | text: this.text, 33 | icon_url: this.iconUrl, 34 | proxy_icon_url: this.proxyIconUrl, 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Interfaces/NewsChannelOptions.ts: -------------------------------------------------------------------------------- 1 | import { CHANNELTYPES } from ".."; 2 | import { IOverwrite } from "./OverwriteOptions"; 3 | 4 | export interface INewsChannel { 5 | id: string; // The ID of this channel 6 | type: CHANNELTYPES.News; // The type of channel 7 | guild_id: string; // The ID of the guild 8 | position: number; // Sorting position of the channel 9 | permission_overwrites: IOverwrite[]; // Explicit permission overwrites for members and roles 10 | name: string; // The name of the channel 11 | topic?: string | null; // The channel topic 12 | nsfw: boolean; // wWhether the channel is nsfw 13 | last_message_id?: string | null; // The id of the last message sent in this channel 14 | rate_limit_per_user: number; // Amount of seconds a user has to wait before sending another message (0-21600) 15 | parent_id?: string; // ID of the parent category for a channel 16 | last_pin_timestamp?: number; // Timestamp when the last pinned message was pinned 17 | } 18 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_MEMBER_ADD.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EvolveClient, 3 | EVENTS, 4 | Payload, 5 | GuildMember, 6 | User, 7 | Endpoints, 8 | } from "../../.."; 9 | import { IGuild } from "../../../Interfaces/GuildOptions"; 10 | import { Guild } from "../../../Structures/Guild/Guild"; 11 | import { GuildMemberEvent } from "../../Events/GuildMemberEvents"; 12 | 13 | export default class { 14 | constructor(client: EvolveClient, payload: Payload, shard: number) { 15 | const member = new GuildMember(payload.d); 16 | (async () => { 17 | const o = await client.rest 18 | .endpoint(Endpoints.GUILD) 19 | .get(payload.d.guild_id); 20 | if (client.options.enableUsersCache) 21 | client.users.set(member.user?.id as string, member.user as User); 22 | client.emit( 23 | EVENTS.GUILD_MEMBER_ADD, 24 | new GuildMemberEvent(client, member, new Guild(o, client), shard) 25 | ); 26 | })(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Interfaces/TextChannelOptions.ts: -------------------------------------------------------------------------------- 1 | import { CHANNELTYPES } from ".."; 2 | import { IOverwrite } from "./OverwriteOptions"; 3 | 4 | export interface ITextChannel { 5 | id: string; // The ID of this channel 6 | type: CHANNELTYPES.Text; // The type of channel 7 | guild_id: string; // The ID of the guild 8 | position: number; // Sorting position of the channel 9 | permission_overwrites: IOverwrite[]; // Explicit permission overwrites for members and roles 10 | name: string; // The name of the channel 11 | topic?: string | null; // The channel topic 12 | nsfw: boolean; // wWhether the channel is nsfw 13 | last_message_id?: string | null; // The id of the last message sent in this channel 14 | rate_limit_per_user: number; // Amount of seconds a user has to wait before sending another message (0-21600) 15 | parent_id?: string | null; // ID of the parent category for a channel 16 | last_pin_timestamp?: number; // Timestamp when the last pinned message was pinned 17 | } 18 | -------------------------------------------------------------------------------- /src/Structures/Guild/Role.ts: -------------------------------------------------------------------------------- 1 | import { IRole } from "../.."; 2 | 3 | export class Role { 4 | public id!: string; 5 | public name!: string; 6 | public color!: number; 7 | public hoist = false; 8 | public position!: number; 9 | public permissions!: number; 10 | public managed = false; 11 | public mentionable = false; 12 | public data!: IRole; 13 | 14 | constructor(data: IRole) { 15 | Object.defineProperty(this, "data", { 16 | value: data, 17 | enumerable: false, 18 | writable: false, 19 | }); 20 | this._handle(); 21 | } 22 | 23 | private _handle() { 24 | if (!this.data) return; 25 | this.id = this.data.id; 26 | this.name = this.data.name; 27 | this.color = this.data.color; 28 | this.hoist = this.data.hoist; 29 | this.position = this.data.position; 30 | this.permissions = this.data.permissions; 31 | this.managed = this.data.managed; 32 | this.mentionable = this.data.mentionable; 33 | return this; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Utils/AsyncronousQueue.ts: -------------------------------------------------------------------------------- 1 | export class AsyncronousQueue { 2 | private _promises: QueuePromise[] = []; 3 | 4 | public get resolved(): boolean { 5 | return this._promises.length === 0; 6 | } 7 | 8 | public get notResolved(): number { 9 | return this._promises.length; 10 | } 11 | 12 | public delay(): Promise { 13 | const next = this._promises.length 14 | ? this._promises[this._promises.length - 1].promise 15 | : Promise.resolve(); 16 | 17 | this.enqueue(); 18 | return next; 19 | } 20 | 21 | public enqueue(): void { 22 | let resolve!: (value: void) => void; 23 | const promise = new Promise((res) => { 24 | resolve = res; 25 | }); 26 | 27 | this._promises.push({ promise, resolve }); 28 | } 29 | 30 | public dequeue(): void { 31 | const next = this._promises.shift(); 32 | if (next) next.resolve(); 33 | } 34 | } 35 | 36 | interface QueuePromise { 37 | promise: Promise; 38 | resolve(value: void): void; 39 | } 40 | -------------------------------------------------------------------------------- /src/Utils/Collectors/MessageCollector.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-types */ 2 | import { BaseCollector } from "./BaseCollector"; 3 | import { TextChannel } from "../../Structures/Channel/TextChannel"; 4 | import { Message } from "../../Structures/Message/Message"; 5 | import { Objex } from "@evolvejs/objex"; 6 | import { MessageReaction } from "../../Structures/Message/MessageReaction"; 7 | 8 | export class MessageCollector extends BaseCollector { 9 | constructor(public channel: TextChannel, public filter: Function) { 10 | super(channel.client, filter); 11 | this.channel.client.on( 12 | "newMessage", 13 | (this.listener = (msg: Message) => { 14 | filter(msg); 15 | }) 16 | ); 17 | } 18 | 19 | public end(): Objex { 20 | this.channel.client.off("newMessage", this.listener); 21 | return this.collected; 22 | } 23 | 24 | public handle(message: Message): void { 25 | this.collected.set(message.id, message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Structures/Channel/CategoryChannel.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | 3 | import { 4 | Overwrite, 5 | Guild, 6 | EvolveClient, 7 | CHANNELTYPES, 8 | ICategoryChannel, 9 | } from "../.."; 10 | import { Objex } from "@evolvejs/objex"; 11 | import { Channel } from "./Channel"; 12 | 13 | export class CategoryChannel extends Channel { 14 | public overwrites: Objex = new Objex(); 15 | 16 | public position!: number; 17 | public name!: string; 18 | public data!: ICategoryChannel; 19 | public guildId?: string; 20 | 21 | constructor(data: ICategoryChannel, client: EvolveClient) { 22 | super(data.id, CHANNELTYPES.Category, client); 23 | Object.defineProperty(this, "data", { 24 | value: data, 25 | enumerable: false, 26 | writable: false, 27 | }); 28 | this._handle(); 29 | } 30 | 31 | private _handle() { 32 | if (!this.data) return; 33 | this.position = this.data.position; 34 | this.name = this.data.name; 35 | this.guildId = this.data.guild_id; 36 | 37 | return this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Interfaces/UserOptions.ts: -------------------------------------------------------------------------------- 1 | export interface IUser { 2 | id?: string; // The user's id identify 3 | username: string; // The user's username, not unique across the platform identify 4 | discriminator: string; // The user's 4-digit discord-tag identify 5 | avatar: string | null; // The user's avatar hash identify 6 | bot?: boolean; // Whether the user belongs to an OAuth2 application identify 7 | system?: boolean; // Whether the user is an Official Discord System user (part of the urgent message system) identify 8 | mfa_enabled?: boolean; // Whether the user has two factor enabled on their account identify 9 | locale?: string; // The user's chosen language option identify 10 | verified?: boolean; // Whether the email on this account has been verified email 11 | email?: string | null; // The user's email email 12 | flags?: number; // The flags on a user's account identify 13 | premium_type?: 0 | 1 | 2; // The type of Nitro subscription on a user's account identify 14 | public_flags?: number; // The public flags on a user's account 15 | } 16 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/MESSAGE_CREATE.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient, EVENTS, Payload, Message } from "../../.."; 2 | import { IGuild } from "../../../Interfaces/GuildOptions"; 3 | import { ITextChannel } from "../../../Interfaces/TextChannelOptions"; 4 | import { TextChannel } from "../../../Structures/Channel/TextChannel"; 5 | import { Guild } from "../../../Structures/Guild/Guild"; 6 | import { Endpoints } from "../../../Utils/Endpoints"; 7 | import { MessageEvents } from "../../Events/MessageEvents"; 8 | 9 | export default class { 10 | constructor( 11 | private client: EvolveClient, 12 | private payload: Payload, 13 | private shard: number 14 | ) { 15 | this._init(); 16 | } 17 | 18 | public async _init(): Promise { 19 | const message = new Message(this.payload.d, this.client); 20 | 21 | if (this.client.options.enableMessageCache) 22 | this.client.messages.set(message.id, message); 23 | 24 | this.client.emit( 25 | EVENTS.MESSAGE_CREATE, 26 | new MessageEvents(this.client, message, this.shard) 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedImage.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | import { URL } from "url"; 3 | 4 | export interface IEmbedImage { 5 | url: string; 6 | proxy_url: string; 7 | height: number; 8 | width: number; 9 | } 10 | 11 | export class EmbedImageBuilder { 12 | private url!: string; 13 | private proxyURl!: string; 14 | private height!: number; 15 | private width!: number; 16 | 17 | public setURL(url: URL): EmbedImageBuilder { 18 | this.url = url.toString(); 19 | return this; 20 | } 21 | 22 | public setProxyURL(url: URL): EmbedImageBuilder { 23 | this.proxyURl = url.toString(); 24 | return this; 25 | } 26 | 27 | public setHeight(height: number): EmbedImageBuilder { 28 | this.height = height; 29 | return this; 30 | } 31 | 32 | public setWidth(width: number): EmbedImageBuilder { 33 | this.width = width; 34 | return this; 35 | } 36 | 37 | public build(): IEmbedImage { 38 | return { 39 | url: this.url, 40 | proxy_url: this.proxyURl, 41 | height: this.height, 42 | width: this.width, 43 | }; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedAuthor.ts: -------------------------------------------------------------------------------- 1 | import { URL } from "url"; 2 | 3 | /* eslint-disable no-mixed-spaces-and-tabs */ 4 | export interface IEmbedAuthor { 5 | name: string; 6 | url: string; 7 | icon_url: string; 8 | proxy_icon_url: string; 9 | } 10 | 11 | export class EmbedAuthorBuilder { 12 | private name!: string; 13 | private url!: string; 14 | private iconUrl!: string; 15 | private proxyiconUrl!: string; 16 | 17 | public setName(name: string): EmbedAuthorBuilder { 18 | this.name = name; 19 | return this; 20 | } 21 | 22 | public setURL(url: URL): EmbedAuthorBuilder { 23 | this.url = url.toString(); 24 | return this; 25 | } 26 | 27 | public setIconURL(url: URL): EmbedAuthorBuilder { 28 | this.iconUrl = url.toString(); 29 | return this; 30 | } 31 | 32 | public setProxyIconURL(url: URL): EmbedAuthorBuilder { 33 | this.proxyiconUrl = url.toString(); 34 | return this; 35 | } 36 | 37 | public build(): IEmbedAuthor { 38 | return { 39 | name: this.name, 40 | url: this.url, 41 | icon_url: this.iconUrl, 42 | proxy_icon_url: this.proxyiconUrl, 43 | }; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Structures/Guild/GuildMember.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | /* eslint-disable no-mixed-spaces-and-tabs */ 3 | 4 | import { User, Role, IGuildMember } from "../.."; 5 | 6 | export class GuildMember { 7 | public user!: User | undefined; 8 | public nick!: string | null; 9 | public roles!: Array; 10 | public joinedAt!: number; 11 | public premiumFrom!: number | undefined | null; 12 | public deaf!: boolean; 13 | public mute!: boolean; 14 | public data!: IGuildMember; 15 | constructor(data: IGuildMember) { 16 | Object.defineProperty(this, "data", { 17 | value: data, 18 | enumerable: false, 19 | writable: false, 20 | }); 21 | this._handle(); 22 | } 23 | 24 | private _handle() { 25 | if (!this.data) return; 26 | if (this.data.user) this.user = new User(this.data.user); 27 | this.nick = this.data.nick; 28 | this.roles = this.data.roles; 29 | this.joinedAt = this.data.joined_at; 30 | this.premiumFrom = this.data.premium_since; 31 | this.deaf = this.data.deaf; 32 | this.mute = this.data.mute; 33 | 34 | return this; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Client/Events/GuildMembersChunkEvents.ts: -------------------------------------------------------------------------------- 1 | import { BaseEvent } from "./BaseEvent"; 2 | import { EvolveClient } from "../EvolveClient"; 3 | import { Objex } from "@evolvejs/objex"; 4 | import { GuildMember } from "../../Structures/Guild/GuildMember"; 5 | import { PresenceUpdate } from "../../Structures/User/PresenceUpdate"; 6 | 7 | export class GuildMembersChunkUpdate extends BaseEvent { 8 | constructor( 9 | client: EvolveClient, 10 | public members: Objex, 11 | public presence: Objex, 12 | public chunk: Array, 13 | public notFound: boolean, 14 | public nonce: string, 15 | shard: number 16 | ) { 17 | super(shard, client); 18 | 19 | for (const [k, v] of members) { 20 | this.members.delete(k); 21 | 22 | this.members.set( 23 | k, 24 | new (this.client.structures.get("GuildMember"))(v.data) 25 | ); 26 | } 27 | 28 | for (const [k, v] of presence) { 29 | this.presence.delete(k); 30 | 31 | this.presence.set( 32 | k, 33 | new (this.client.structures.get("PresenceUpdate"))(v.data, client) 34 | ); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_MEMBER_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EvolveClient, 3 | EVENTS, 4 | Payload, 5 | GuildMember, 6 | User, 7 | Endpoints, 8 | } from "../../.."; 9 | import { IGuild } from "../../../Interfaces/GuildOptions"; 10 | import { Guild } from "../../../Structures/Guild/Guild"; 11 | import { GuildMemberEvent } from "../../Events/GuildMemberEvents"; 12 | export default class { 13 | constructor(client: EvolveClient, payload: Payload, shard: number) { 14 | const { guild_id, roles, user, nick, joined_at, premium_since } = payload.d; 15 | const member = new GuildMember({ 16 | user, 17 | nick, 18 | roles, 19 | joined_at, 20 | premium_since, 21 | deaf: false, 22 | mute: false, 23 | }); 24 | if (client.options.enableUsersCache) 25 | client.users.set(member.user?.id as string, member.user as User); 26 | 27 | (async () => { 28 | const o = await client.rest 29 | .endpoint(Endpoints.GUILD) 30 | .get(guild_id); 31 | client.emit( 32 | EVENTS.GUILD_MEMBER_UPDATE, 33 | new GuildMemberEvent(client, member, new Guild(o, client), shard) 34 | ); 35 | })(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_EMOJIS_UPDATE.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EvolveClient, 3 | EVENTS, 4 | Payload, 5 | Emoji, 6 | Endpoints, 7 | Guild, 8 | } from "../../.."; 9 | import { Objex } from "@evolvejs/objex"; 10 | import { GuildEmojiEvents } from "../../Events/GuildEmojiEvents"; 11 | import { IGuild } from "../../../Interfaces/GuildOptions"; 12 | 13 | export default class { 14 | constructor(client: EvolveClient, payload: Payload, shard: number) { 15 | const { guild_id, emojis } = payload.d; 16 | 17 | (async () => { 18 | const guild = await client.rest 19 | .endpoint(Endpoints.GUILD) 20 | .get(guild_id); 21 | const emojiObjex: Objex = new Objex(); 22 | for (const emoji of emojis) { 23 | emojiObjex.set(emoji.id, new Emoji(emoji)); 24 | if (client.options.enableEmojiCache) 25 | client.emojis.set(emoji.id, new Emoji(emoji)); 26 | } 27 | client.emit( 28 | EVENTS.GUILD_EMOJIS_UPDATE, 29 | new GuildEmojiEvents( 30 | client, 31 | emojiObjex, 32 | new Guild(guild, client), 33 | shard 34 | ) 35 | ); 36 | })(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedThumbnail.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | import { URL } from "url"; 3 | 4 | export interface IEmbedThumbnail { 5 | url: string; 6 | proxy_url: string; 7 | height: number; 8 | width: number; 9 | } 10 | 11 | export class EmbedThumbnailBuilder { 12 | private url!: string; 13 | private proxy_url!: string; 14 | private height!: number; 15 | private width!: number; 16 | 17 | public setURL(url: URL): EmbedThumbnailBuilder { 18 | this.url = url.toString(); 19 | return this; 20 | } 21 | 22 | public setProxyURL(url: URL): EmbedThumbnailBuilder { 23 | this.proxy_url = url.toString(); 24 | return this; 25 | } 26 | 27 | public setHeight(height: number): EmbedThumbnailBuilder { 28 | this.height = height; 29 | return this; 30 | } 31 | 32 | public setWidth(width: number): EmbedThumbnailBuilder { 33 | this.width = width; 34 | return this; 35 | } 36 | 37 | public build(): IEmbedThumbnail { 38 | const thumbnail: IEmbedThumbnail = { 39 | url: this.url, 40 | proxy_url: this.proxy_url, 41 | height: this.height, 42 | width: this.width, 43 | }; 44 | 45 | return thumbnail; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Structures/Guild/Webhook.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | 3 | import { User, IWebhook, EvolveClient } from "../.."; 4 | 5 | export class Webhook { 6 | public id!: string; 7 | public type!: number; 8 | public guildId!: string; 9 | public channelId!: string; 10 | public user!: User; 11 | public name!: string; 12 | public avatar!: string; 13 | public token!: string; 14 | public data!: IWebhook; 15 | constructor(data: IWebhook, public client: EvolveClient) { 16 | Object.defineProperty(this, "data", { 17 | value: data, 18 | enumerable: false, 19 | writable: false, 20 | }); 21 | Object.defineProperty(this, "client", { 22 | value: client, 23 | enumerable: false, 24 | writable: false, 25 | }); 26 | this._handle(); 27 | } 28 | 29 | private _handle() { 30 | if (!this.data) return; 31 | this.id = this.data.id; 32 | this.type = this.data.type; 33 | if (this.data.guild_id) this.guildId = this.data.guild_id; 34 | this.channelId = this.data.channel_id; 35 | this.user = new User(this.data.user!); 36 | this.name = this.data.name!; 37 | this.avatar = this.data.avatar!; 38 | this.token = this.data.token!; 39 | return this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Structures/Channel/StoreChannel.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Overwrite, 3 | Guild, 4 | CategoryChannel, 5 | IStoreChannel, 6 | EvolveClient, 7 | CHANNELTYPES, 8 | } from "../.."; 9 | import { Objex } from "@evolvejs/objex"; 10 | import { Channel } from "./Channel"; 11 | 12 | export class StoreChannel extends Channel { 13 | public overwrites: Objex = new Objex(); 14 | 15 | public guildId?: string; 16 | public position!: number; 17 | public name!: string; 18 | public nsfw!: boolean; 19 | public rateLimit!: number; 20 | public parentId?: string; 21 | public data!: IStoreChannel; 22 | 23 | constructor(data: IStoreChannel, client: EvolveClient) { 24 | super(data.id, CHANNELTYPES.Store, client); 25 | Object.defineProperty(this, "data", { 26 | value: data, 27 | enumerable: false, 28 | writable: false, 29 | }); 30 | this._handle(); 31 | } 32 | 33 | private _handle() { 34 | if (!this.data) return; 35 | this.guildId = this.data.guild_id; 36 | this.position = this.data.position; 37 | this.name = this.data.name; 38 | this.nsfw = this.data.nsfw; 39 | this.rateLimit = this.data.rate_limit_per_user; 40 | this.parentId = this.data.parent_id ?? undefined; 41 | return this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Structures/Guild/Emoji.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | 3 | import { Objex } from "@evolvejs/objex"; 4 | import { Role, User, IEmoji } from "../.."; 5 | 6 | export class Emoji { 7 | public id!: string | null; 8 | public name!: string | null; 9 | public roles: Objex = new Objex(); 10 | public user!: User; 11 | public reqColons?: boolean; 12 | public managed?: boolean; 13 | public animated?: boolean; 14 | public available?: boolean; 15 | public data!: IEmoji; 16 | 17 | constructor(data: IEmoji) { 18 | Object.defineProperty(this, "data", { 19 | value: data, 20 | enumerable: false, 21 | writable: false, 22 | }); 23 | this._handle(); 24 | } 25 | 26 | private _handle() { 27 | if (!this.data) return; 28 | this.id = this.data.id; 29 | this.name = this.data.name; 30 | if (this.data.roles) 31 | this.data.roles.forEach((i) => this.roles.set(i.id, new Role(i))); 32 | this.user = new User(this.data.user); 33 | this.reqColons = this.data.require_colons; 34 | this.managed = this.data.managed; 35 | this.animated = this.data.animated; 36 | this.available = this.data.available; 37 | return this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Structures/Channel/VoiceChannel.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Overwrite, 3 | Guild, 4 | CategoryChannel, 5 | IVoiceChannel, 6 | EvolveClient, 7 | CHANNELTYPES, 8 | } from "../.."; 9 | import { Objex } from "@evolvejs/objex"; 10 | import { Channel } from "./Channel"; 11 | 12 | export class VoiceChannel extends Channel { 13 | public overwrites: Objex = new Objex(); 14 | 15 | public guildId?: Guild; 16 | public position!: number; 17 | public name!: string; 18 | public bitrate!: number; 19 | public userLimit!: number; 20 | public parentId?: string; 21 | public data!: IVoiceChannel; 22 | 23 | constructor(data: IVoiceChannel, client: EvolveClient) { 24 | super(data.id, CHANNELTYPES.Voice, client); 25 | Object.defineProperty(this, "data", { 26 | value: data, 27 | enumerable: false, 28 | writable: false, 29 | }); 30 | this._handle(); 31 | } 32 | 33 | private _handle() { 34 | if (!this.data) return; 35 | this.guildId = this.client.guilds.get(this.data.guild_id); 36 | this.position = this.data.position; 37 | this.name = this.data.name; 38 | this.bitrate = this.data.bitrate; 39 | this.userLimit = this.data.user_limit; 40 | this.parentId = this.data.parent_id ?? undefined; 41 | return this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Structures/Message/MessageReaction.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | import { 3 | User, 4 | TextChannel, 5 | Message, 6 | GuildMember, 7 | Guild, 8 | Emoji, 9 | IMessageReaction, 10 | EvolveClient, 11 | } from "../../"; 12 | 13 | export class MessageReaction { 14 | public user?: User; 15 | public channel!: TextChannel; 16 | public message!: Message; 17 | public member?: GuildMember; 18 | public guild!: Guild; 19 | public emoji?: Emoji; 20 | private client!: EvolveClient; 21 | public data!: IMessageReaction; 22 | 23 | constructor(data: IMessageReaction, client: EvolveClient) { 24 | Object.defineProperty(this, "data", { 25 | value: data, 26 | enumerable: false, 27 | writable: false, 28 | }); 29 | Object.defineProperty(this, "client", { 30 | value: client, 31 | enumerable: false, 32 | writable: false, 33 | }); 34 | this._handle(); 35 | } 36 | 37 | private _handle() { 38 | if (!this.data) return; 39 | this.message = new Message(this.data.message, this.client); 40 | this.channel = new TextChannel(this.data.channel, this.client); 41 | this.emoji = new Emoji(this.data.emoji); 42 | this.user = new User(this.data.user); 43 | this.member = new GuildMember(this.data.member); 44 | this.guild = new Guild(this.data.guild, this.client); 45 | return this; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/GUILD_MEMBERS_CHUNK.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EvolveClient, 3 | EVENTS, 4 | Payload, 5 | GuildMember, 6 | PresenceUpdate, 7 | } from "../../.."; 8 | import { Objex } from "@evolvejs/objex"; 9 | import { GuildMembersChunkUpdate } from "../../Events/GuildMembersChunkEvents"; 10 | 11 | export default class { 12 | constructor(client: EvolveClient, payload: Payload, shard: number) { 13 | (async () => { 14 | const { 15 | members, 16 | chunk_index, 17 | chunk_count, 18 | not_found, 19 | presences, 20 | nonce, 21 | } = payload.d; 22 | const memberObjex: Objex = new Objex(); 23 | for (const member of members) { 24 | memberObjex.set(member.user.id, new GuildMember(member)); 25 | } 26 | 27 | const presenceObjex: Objex = new Objex(); 28 | for (const presence of presences) { 29 | presenceObjex.set( 30 | presence.user.id, 31 | new PresenceUpdate(presence, client) 32 | ); 33 | } 34 | 35 | client.emit( 36 | EVENTS.GUILD_MEMBERS_CHUNK, 37 | new GuildMembersChunkUpdate( 38 | client, 39 | memberObjex, 40 | presenceObjex, 41 | [chunk_index, chunk_count], 42 | not_found, 43 | nonce, 44 | shard 45 | ) 46 | ); 47 | })(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Documentations Generator 2 | 3 | on: 4 | create: 5 | tags: 6 | - "*" 7 | push: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | generate-docs: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: actions/setup-node@v1 17 | with: 18 | node-version: 15 19 | registry-url: https://registry.npmjs.org/ 20 | - name: Install dependencies 21 | run: yarn 22 | - name: Extract and save tag in env 23 | run: echo VERSION=${GITHUB_REF#refs/*/} >> $GITHUB_PATH 24 | - name: Generate docs 25 | run: yarn docs ${{ env.VERSION }} 26 | - name: Set JSON file's base64 in env 27 | id: json-file 28 | run: echo "json::$(cat ${{ env.VERSION }}.json | base64 -w 0 -)" >> $GITHUB_PATH 29 | - name: Checkout the docs branch 30 | run: | 31 | git fetch 32 | git checkout docs -f 33 | - name: Configure git identity 34 | run: | 35 | git config user.name github-actions 36 | git config user.email github-actions@github.com 37 | - name: Stage, commit & push changes 38 | run: | 39 | echo '${{ env.json }}' | base64 -w 0 -d - > ${{ env.VERSION }}.json 40 | git add ${{ env.VERSION }}.json 41 | git commit -m "Docs update triggered by ${{ env.VERSION }}" 42 | git push origin docs 43 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | publish-npm: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: actions/setup-node@v1 14 | with: 15 | node-version: 15 16 | registry-url: https://registry.npmjs.org/ 17 | - run: yarn && yarn build 18 | - run: npm publish --access public 19 | env: 20 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 21 | 22 | publish-deno: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: actions/setup-node@v1 27 | with: 28 | node-version: 15 29 | registry-url: https://registry.npmjs.org/ 30 | - name: Install dependencies 31 | run: yarn 32 | - name: Generate Deno 33 | run: node scripts/nodetodeno.js 34 | - name: Checkout the deno-master branch 35 | run: | 36 | git fetch 37 | git checkout deno-master -f 38 | - name: Configure git identity 39 | run: | 40 | git config user.name github-actions 41 | git config user.email github-actions@github.com 42 | - name: Stage, commit & push changes 43 | run: | 44 | git add ./deno/ 45 | git commit -m "Deno Publish Triggered due to new version" 46 | git push origin deno-master 47 | -------------------------------------------------------------------------------- /src/Structures/Channel/GroupChannel.ts: -------------------------------------------------------------------------------- 1 | import { User, IGroupChannel, EvolveClient, CHANNELTYPES, IUser } from "../.."; 2 | import { Objex } from "@evolvejs/objex"; 3 | import { Channel } from "./Channel"; 4 | import { Endpoints } from "../../Utils/Endpoints"; 5 | 6 | export class GroupChannel extends Channel { 7 | public recipients: Objex = new Objex(); 8 | 9 | public name?: string; 10 | public lastMessage?: string; 11 | public icon?: string; 12 | public applicationID?: string; 13 | public lastPin?: number; 14 | public data!: IGroupChannel; 15 | 16 | constructor(data: IGroupChannel, client: EvolveClient, public owner?: User) { 17 | super(data.id, CHANNELTYPES.Group, client); 18 | Object.defineProperty(this, "data", { 19 | value: data, 20 | enumerable: false, 21 | writable: false, 22 | }); 23 | this._handle(); 24 | } 25 | 26 | private _handle() { 27 | if (!this.data) return; 28 | 29 | this.name = this.data.name; 30 | this.lastMessage = this.data.last_message_id || undefined; 31 | this.icon = this.data.icon || undefined; 32 | this.applicationID = this.data.application_id; 33 | this.lastPin = this.data.last_pin_timestamp; 34 | 35 | return this; 36 | } 37 | 38 | static async new(data: IGroupChannel, client: EvolveClient) { 39 | return new GroupChannel( 40 | data, 41 | client, 42 | new User( 43 | await client.rest.endpoint(Endpoints.USER).get(data.owner_id) 44 | ) 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Structures/Channel/NewsChannel.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Overwrite, 3 | Guild, 4 | CategoryChannel, 5 | INewsChannel, 6 | EvolveClient, 7 | CHANNELTYPES, 8 | } from "../.."; 9 | import { Objex } from "@evolvejs/objex"; 10 | import { Channel } from "./Channel"; 11 | 12 | export class NewsChannel extends Channel { 13 | public overwrites: Objex = new Objex(); 14 | 15 | public guild?: Guild; 16 | public position!: number; 17 | public name!: string; 18 | public topic?: string; 19 | public nsfw = false; 20 | public lastMessage?: string; 21 | public rateLimit!: number; 22 | public parentID?: string; 23 | public lastPin?: string; 24 | public data!: INewsChannel; 25 | 26 | constructor(data: INewsChannel, client: EvolveClient) { 27 | super(data.id, CHANNELTYPES.News, client); 28 | Object.defineProperty(this, "data", { 29 | value: data, 30 | enumerable: false, 31 | writable: false, 32 | }); 33 | this._handle(); 34 | } 35 | 36 | private _handle() { 37 | if (!this.data) return; 38 | this.guild = this.client.guilds.get(this.data.guild_id); 39 | this.position = this.data.position; 40 | this.name = this.data.name; 41 | this.topic = this.data.topic ?? ""; 42 | this.nsfw = this.data.nsfw; 43 | this.lastMessage = this.data.last_message_id || undefined; 44 | this.rateLimit = this.data.rate_limit_per_user; 45 | this.parentID = this.data.parent_id; 46 | this.lastPin = this.data.last_message_id || undefined; 47 | return this; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Decorators/Builder.ts: -------------------------------------------------------------------------------- 1 | import { EvolveBuilder } from "../Client/EvolveBuilder"; 2 | import { EvolveClient } from "../Client/EvolveClient"; 3 | import { CacheProviders } from "../Interfaces/Interfaces"; 4 | import { Structures } from "../Structures/Structures"; 5 | import { CacheOptions, GatewayIntents } from "../Utils/Constants"; 6 | 7 | export function Builder(options: BuilderDecoratorOptions) { 8 | return (target: typeof EvolveClient): void => { 9 | const builder: EvolveBuilder = new EvolveBuilder( 10 | options.token, 11 | options.useDefaultSetting ?? true 12 | ).setClientClass(target); 13 | 14 | if (options.intents) builder.enableIntents(...options.intents); 15 | if (options.cache) builder.enableCache(...options.cache); 16 | if (options.secret) builder.setSecret(options.secret); 17 | if (options.activity) builder.setActivity(options.activity); 18 | if (options.encoding) builder.setEncoding(options.encoding); 19 | if (options.shards) builder.setShards(options.shards); 20 | if (options.structure) builder.setStructureClass(options.structure); 21 | if (options.cacheProvider) builder.setCacheProviders(options.cacheProvider); 22 | 23 | builder.build(); 24 | }; 25 | } 26 | 27 | interface BuilderDecoratorOptions { 28 | intents?: GatewayIntents[]; 29 | cache?: CacheOptions[]; 30 | useDefaultSetting?: boolean; 31 | token: string; 32 | secret?: string; 33 | activity?: Object; 34 | encoding?: "json" | "etf"; 35 | shards?: number; 36 | structure?: Structures; 37 | cacheProvider?: CacheProviders; 38 | } 39 | -------------------------------------------------------------------------------- /src/Structures/User/User.ts: -------------------------------------------------------------------------------- 1 | import { IUser, NITRO } from "../.."; 2 | 3 | export class User { 4 | public id!: string; 5 | public username!: string; 6 | public discriminator!: string; 7 | public avatar?: string; 8 | public bot!: boolean; 9 | public system!: boolean; 10 | public twoFactor!: boolean; 11 | public lang?: string; 12 | public verified!: boolean; 13 | public email?: string; 14 | public flags?: number; 15 | public premiumType!: string; 16 | public publicFlags?: number; 17 | public data!: IUser; 18 | 19 | constructor(data: IUser) { 20 | Object.defineProperty(this, "data", { 21 | value: data, 22 | enumerable: false, 23 | writable: false, 24 | }); 25 | this._handle(); 26 | } 27 | 28 | private _handle() { 29 | if (!this.data) return; 30 | if (this.data.id) this.id = this.data.id; 31 | this.username = this.data.username; 32 | this.discriminator = this.data.discriminator; 33 | this.avatar = this.data.avatar ?? undefined; 34 | this.bot = this.data.bot ?? false; 35 | this.system = this.data.system ?? false; 36 | this.twoFactor = this.data.mfa_enabled ?? false; 37 | this.lang = this.data.locale; 38 | this.verified = this.data.verified ?? false; 39 | this.email = this.data.email ?? undefined; 40 | this.flags = this.data.flags; 41 | this.premiumType = this.data.premium_type 42 | ? NITRO[this.data.premium_type] 43 | : "None"; 44 | this.publicFlags = this.data.public_flags; 45 | return this; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Structures/Guild/Invite.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | 3 | import { Guild, User, IInvite, EvolveClient } from "../.."; 4 | import { Channel } from "../Channel/Channel"; 5 | 6 | export class Invite { 7 | public code!: string; 8 | public guild!: Guild; 9 | public channel!: Channel; 10 | public inviter!: User; 11 | public targetUser!: User; 12 | public targetUserType?: number; 13 | public approxPresenceCount?: number; 14 | public approxMemberCount?: number; 15 | private client!: EvolveClient; 16 | public data!: IInvite; 17 | constructor(data: IInvite, client: EvolveClient) { 18 | Object.defineProperty(this, "data", { 19 | value: data, 20 | enumerable: false, 21 | writable: false, 22 | }); 23 | Object.defineProperty(this, "client", { 24 | value: client, 25 | enumerable: false, 26 | writable: false, 27 | }); 28 | this._handle(); 29 | } 30 | 31 | private _handle() { 32 | if (!this.data) return; 33 | this.code = this.data.code; 34 | this.guild = new Guild(this.data.guild!, this.client); 35 | this.channel = new Channel( 36 | this.data.channel.id, 37 | this.data.channel.type, 38 | this.client 39 | ); 40 | this.inviter = new User(this.data.inviter!); 41 | this.targetUser = new User(this.data.target_user!); 42 | this.targetUserType = this.data.target_user_type; 43 | this.approxPresenceCount = this.data.approximate_presence_count; 44 | this.approxMemberCount = this.data.approximate_member_count; 45 | return this; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Client/Websocket/ShardManager.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { promisify } from "util"; 3 | import { EventListener } from "../../Utils/EventListener"; 4 | import { EvolveBuilder } from "../EvolveBuilder"; 5 | import { EvolveSocket } from "./Websocket"; 6 | 7 | export class ShardManager extends EventListener { 8 | public builder!: EvolveBuilder; 9 | public connections: Objex = new Objex(); 10 | constructor(builder: EvolveBuilder) { 11 | super(); 12 | Object.defineProperty(this, "builder", { 13 | value: builder, 14 | enumerable: false, 15 | writable: false, 16 | }); 17 | } 18 | 19 | public spawnAll(): void { 20 | for (let i = 0; i < this.builder.shards; i++) { 21 | promisify(setTimeout)(5000).then(() => { 22 | const socket = new EvolveSocket(this, i); 23 | this.connections.set(i, socket); 24 | }); 25 | } 26 | } 27 | 28 | public destroy(id: number): void { 29 | this.connections.get(id)?.gateway.destroy(); 30 | } 31 | 32 | public respawn(id: number): void { 33 | this.connections.get(id)?.gateway.reconnect(); 34 | } 35 | 36 | public destroyAll(code = 0): void { 37 | const initialLastShardConnection = this.connections.size - 1; 38 | for (const [k, v] of this.connections) { 39 | v.gateway.destroy(); 40 | 41 | if (k === initialLastShardConnection) { 42 | process.exit(code); 43 | } 44 | } 45 | } 46 | 47 | get ping(): number { 48 | return ( 49 | this.connections.reduce((a, b) => a + b.shardPing) / 50 | this.connections.size 51 | ); 52 | } 53 | 54 | public getguildShardId(guildID: string): number { 55 | return (Number(guildID) >> 22) % this.connections.size; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Client/RestAPI/RestAPI.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | 3 | import { RestAPIHandler } from "./RestAPIHandler"; 4 | import { EvolveClient } from "../EvolveClient"; 5 | import { Objex } from "@evolvejs/objex"; 6 | 7 | /** 8 | * RestAPI Class 9 | * 10 | * @param {client} - Your EvolveClient 11 | */ 12 | export class RestAPI { 13 | private _client!: EvolveClient; 14 | private _handler!: Objex; 15 | 16 | constructor(client: EvolveClient) { 17 | Object.defineProperty(this, "_client", { 18 | value: client, 19 | enumerable: false, 20 | writable: false, 21 | configurable: false, 22 | }); 23 | Object.defineProperty(this, "_handler", { 24 | value: new Objex(), 25 | enumerable: false, 26 | writable: false, 27 | configurable: false, 28 | }); 29 | } 30 | 31 | /** 32 | * 33 | * @param endpoint 34 | * Gets a Handler for the specific endpoint or creates a new one 35 | */ 36 | public endpoint(endpoint: string): RestAPIHandler { 37 | if (this._handler.has(endpoint)) return this._handler.get(endpoint)!!; 38 | else { 39 | this._handler.set(endpoint, new RestAPIHandler(this._client, endpoint)); 40 | return this._handler.get(endpoint)!!; 41 | } 42 | } 43 | 44 | public get active(): boolean { 45 | return this.activeRequests.length !== 0; 46 | } 47 | 48 | public get activeRequests(): RestAPIHandler[] { 49 | const activeArray: RestAPIHandler[] = []; 50 | for (const [_, v] of this._handler.filter( 51 | (handler) => handler.active === true 52 | )) { 53 | activeArray.push(v); 54 | } 55 | 56 | return activeArray; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Structures/User/PresenceUpdate.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | import { 3 | User, 4 | Role, 5 | Activity, 6 | Guild, 7 | ClientStatus, 8 | IPresenceUpdate, 9 | EvolveClient, 10 | IGuild, 11 | } from "../.."; 12 | import { Objex } from "@evolvejs/objex"; 13 | import { Endpoints } from "../../Utils/Endpoints"; 14 | 15 | export class PresenceUpdate { 16 | public user!: User; 17 | public roles: Objex = new Objex(); 18 | public game!: Activity; 19 | public guildId!: string; 20 | public status!: string; 21 | public activities!: Array; 22 | public clientStatus!: ClientStatus; 23 | public premiumFrom?: number | null; 24 | public nick?: string | null; 25 | private client!: EvolveClient; 26 | public data!: IPresenceUpdate; 27 | constructor(data: IPresenceUpdate, client: EvolveClient) { 28 | Object.defineProperty(this, "data", { 29 | value: data, 30 | enumerable: false, 31 | writable: false, 32 | }); 33 | Object.defineProperty(this, "client", { 34 | value: client, 35 | enumerable: false, 36 | writable: false, 37 | }); 38 | this._handle(); 39 | } 40 | 41 | private _handle() { 42 | if (!this.data) return; 43 | this.user = new User(this.data.user); 44 | this.data.roles.forEach((o) => 45 | this.roles.set(o, this.client.roles.get(o)!) 46 | ); 47 | if (this.data.game) this.game = new Activity(this.data.game); 48 | this.guildId = this.data.guild_id; 49 | this.status = this.data.status; 50 | this.activities = this.data.activities; 51 | this.clientStatus = new ClientStatus(this.data.client_status); 52 | this.premiumFrom = this.data.premium_since; 53 | this.nick = this.data.nick; 54 | return this; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Structures/User/Activity.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | import { IActivityEmoji, IParty, IAssets, ISecrets, IActivity } from "../.."; 3 | 4 | export class Activity { 5 | public name!: string; 6 | public type!: number; 7 | public createdAt!: number; 8 | public url?: string | null; 9 | public startTime?: number; 10 | public endTime?: number; 11 | public applicationID?: string; 12 | public details?: string | null; 13 | public state?: string | null; 14 | public emoji?: IActivityEmoji | null; 15 | public party?: IParty; 16 | public assets?: IAssets; 17 | public secrets?: ISecrets; 18 | public instance?: boolean; 19 | public flags?: number; 20 | public data!: IActivity; 21 | 22 | constructor(data: IActivity) { 23 | Object.defineProperty(this, "data", { 24 | value: data, 25 | enumerable: false, 26 | writable: false, 27 | }); 28 | this._handle(); 29 | } 30 | 31 | private _handle() { 32 | if (!this.data) return; 33 | this.name = this.data.name; 34 | this.type = this.data.type; 35 | this.createdAt = this.data.created_at; 36 | this.url = this.data.url; 37 | if (this.data.timestamps) { 38 | if (this.data.timestamps.start) 39 | this.startTime = this.data.timestamps.start; 40 | if (this.data.timestamps.end) this.endTime = this.data.timestamps.end; 41 | } 42 | this.applicationID = this.data.application_id; 43 | this.state = this.data.state; 44 | this.details = this.data.details; 45 | this.emoji = this.data.emoji; 46 | this.party = this.data.party; 47 | this.assets = this.data.assets; 48 | this.secrets = this.data.secrets; 49 | this.instance = this.data.instance; 50 | this.flags = this.data.flags; 51 | return this; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Structures/Guild/VoiceState.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | 3 | import { 4 | Guild, 5 | User, 6 | GuildMember, 7 | IVoiceState, 8 | EvolveClient, 9 | IUser, 10 | IGuild, 11 | } from "../.."; 12 | import { Endpoints } from "../../Utils/Endpoints"; 13 | import { Channel } from "../Channel/Channel"; 14 | 15 | export class VoiceState { 16 | public guildId?: string; 17 | public channelId?: string; 18 | public userId!: string; 19 | public member?: GuildMember; 20 | public sessionID!: string; 21 | public deaf!: boolean; 22 | public mute!: boolean; 23 | public selfDeaf!: boolean; 24 | public selfMute!: boolean; 25 | public selfStream!: boolean; 26 | public selfVideo!: boolean; 27 | public supress!: boolean; 28 | private client!: EvolveClient; 29 | public data!: IVoiceState; 30 | 31 | constructor(data: IVoiceState, client: EvolveClient) { 32 | Object.defineProperty(this, "data", { 33 | value: data, 34 | enumerable: false, 35 | writable: false, 36 | }); 37 | Object.defineProperty(this, "client", { 38 | value: client, 39 | enumerable: false, 40 | writable: false, 41 | }); 42 | this._handle(); 43 | } 44 | 45 | private _handle() { 46 | if (!this.data) return; 47 | this.guildId = this.data.guild_id; 48 | this.channelId = this.data.channel_id ?? undefined; 49 | this.userId = this.data.user_id; 50 | this.member = this.data.member 51 | ? new GuildMember(this.data.member) 52 | : undefined; 53 | this.sessionID = this.data.session_id; 54 | this.deaf = this.data.deaf; 55 | this.mute = this.data.mute; 56 | this.selfDeaf = this.data.self_deaf; 57 | this.selfMute = this.data.self_mute; 58 | this.selfStream = this.data.self_stream!; 59 | this.selfVideo = this.data.self_video; 60 | this.supress = this.data.suppress; 61 | return this; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Client/Managers/ChannelsManger.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { ChannelOptions } from "../../Interfaces/Interfaces"; 3 | import { Guild } from "../../Structures/Guild/Guild"; 4 | import { 5 | ChannelResolvable, 6 | ChannelResolver, 7 | ChannelTypes, 8 | } from "../../Utils/Constants"; 9 | import { Endpoints } from "../../Utils/Endpoints"; 10 | import { EvolveClient } from "../EvolveClient"; 11 | 12 | export class ChannelsManager extends Objex { 13 | private client!: EvolveClient; 14 | private guild!: Guild; 15 | constructor(client: EvolveClient, guild?: Guild) { 16 | super(); 17 | Object.defineProperty(this, "client", { 18 | value: client, 19 | enumerable: false, 20 | writable: false, 21 | }); 22 | if (guild) this.guild = guild; 23 | } 24 | 25 | public async resolve(id: string): Promise { 26 | let channel: ChannelTypes = (super.get(id) as unknown) as ChannelTypes; 27 | if (channel) return channel; 28 | 29 | const request = await this.client.rest 30 | .endpoint(Endpoints.CHANNEL) 31 | .get(id); 32 | return new ChannelResolver[request.type](request as never, this.client); 33 | } 34 | 35 | public async new( 36 | options: ChannelOptions, 37 | guild?: Guild 38 | ): Promise { 39 | if (!guild) guild = this.guild; 40 | if (!guild) 41 | throw this.client.transformer.error( 42 | "No Guild Found for Creating the Channel" 43 | ); 44 | 45 | const request = await this.client.rest 46 | .endpoint(Endpoints.GUILD_CHANNELS) 47 | .post(options, guild.id); 48 | return new ChannelResolver[request.type](request as never, this.client); 49 | } 50 | 51 | public delete(id: string, onlyFromCache: boolean = false): boolean { 52 | if (!onlyFromCache) this.client.rest.endpoint(Endpoints.CHANNEL).delete(id); 53 | return super.delete(id); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Oauth2/Oauth2.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient } from "../Client/EvolveClient"; 2 | import { TokenAccessOptions, CONSTANTS } from ".."; 3 | import fetch from "node-fetch"; 4 | 5 | export class Oauth2 { 6 | constructor(public client: EvolveClient) { 7 | if (!this.client.secret) 8 | throw this.client.transformer.error( 9 | "No Client Secret Provided in EvolveBuilder" 10 | ); 11 | } 12 | 13 | public async requestOauth2Token(options: TokenAccessOptions): Promise { 14 | let string = ""; 15 | for (const [key, value] of Object.entries({ 16 | client_id: this.client.user.id, 17 | client_secret: this.client.secret, 18 | grant_type: "authorization_code", 19 | code: options.code, 20 | redirect_uri: options.redirectUri, 21 | scope: options.scopes, 22 | })) { 23 | if (!value) continue; 24 | string += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`; 25 | } 26 | 27 | const fetched = await fetch(`${CONSTANTS.Api}/oauth2/token`, { 28 | headers: { 29 | "Content-Type": "application/x-www-form-urlencoded", 30 | }, 31 | method: "POST", 32 | body: string.substring(1), 33 | }); 34 | 35 | return await fetched.json(); 36 | } 37 | 38 | public async requestTokenExchange( 39 | refreshToken: string, 40 | redirectURI: string, 41 | scopes: string 42 | ): Promise { 43 | let string = ""; 44 | for (const [k, v] of Object.entries({ 45 | client_id: this.client.user.id, 46 | client_secret: this.client.secret, 47 | grant_type: "refresh_token", 48 | refresh_token: refreshToken, 49 | redirect_uri: redirectURI, 50 | scope: scopes, 51 | })) { 52 | if (!v) continue; 53 | string += `&${encodeURIComponent(k)}=${encodeURIComponent(v)}`; 54 | } 55 | 56 | const fetched = await fetch(`${CONSTANTS.Api}/oauth2/token`, { 57 | method: "POST", 58 | body: string.substring(1), 59 | }); 60 | return fetched.json(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@evolvejs/core", 3 | "version": "0.3.2-alpha", 4 | "description": "An advanced Discord API wrapper with TS and JS support", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "install": "echo Thanks for installing EvolveJS", 8 | "build": "tsc", 9 | "build:test": "cd tests/ && tsc && cd ..", 10 | "prettier": "prettier ./ --write", 11 | "docs": "node scripts/gendocs.js", 12 | "build:dev": "tsc --watch", 13 | "development:test": "cd tests && nodemon ./dist/builder.js", 14 | "build::test": "nodemon --ignore dist/ -e ts --exec \"tsc && cd tests && tsc && node dist/builder\"" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/EvolveJS/EvolveJS.git" 19 | }, 20 | "keywords": [ 21 | "evolvejs", 22 | "evjs", 23 | "discord", 24 | "library", 25 | "typescript", 26 | "javascript", 27 | "discord-library" 28 | ], 29 | "author": "evolvejs", 30 | "license": "AGPL-3.0-or-later", 31 | "maintainers": [ 32 | "RoMeAh" 33 | ], 34 | "bugs": { 35 | "url": "https://github.com/EvolveJS/EvolveJS/issues" 36 | }, 37 | "homepage": "https://evolve.js.org", 38 | "markdown": "github", 39 | "exports": { 40 | ".": [ 41 | { 42 | "require": "./dist/index.js", 43 | "import": "./esm/discord.mjs" 44 | }, 45 | "./dist/index.js" 46 | ], 47 | "./esm": "./esm/index.mjs" 48 | }, 49 | "readme": "./README.md", 50 | "dependencies": { 51 | "@evolvejs/objex": "^1.0.5", 52 | "node-fetch": "^2.6.1", 53 | "sign-logger": "^2.2.6", 54 | "ws": "^7.4.2" 55 | }, 56 | "optionalDependencies": { 57 | "erlpack": "^0.1.3" 58 | }, 59 | "devDependencies": { 60 | "@types/node": "^14.0.23", 61 | "@types/node-fetch": "^2.5.7", 62 | "@types/ws": "^7.2.6", 63 | "typedoc": "^0.20.20", 64 | "typescript": "^4.1.3" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Client/Websocket/Voice/VoiceGateway.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | import { Gateway } from "../Gateway"; 3 | import ws, { Data } from "ws"; 4 | import { VoiceIdentify, Heartbeat, EVENTS } from "../../../Utils/Constants"; 5 | import { Payload } from "../../.."; 6 | import { EventListener } from "../../../Utils/EventListener"; 7 | 8 | export class VoiceGateway extends EventListener { 9 | public link!: string; 10 | public websocket!: ws; 11 | public seq!: number; 12 | constructor(public gateway: Gateway) { 13 | super(); 14 | } 15 | 16 | public init(): void { 17 | let endpoint = this.gateway.voiceServerUpdate.d.endpoint; 18 | if (!endpoint) return; 19 | endpoint = endpoint.match(/([^:]*)/)[0]; 20 | this.websocket = new ws(`wss://${endpoint}?v=4`); 21 | 22 | this.websocket.on("open", () => { 23 | VoiceIdentify.d.server_id = this.gateway.voiceServerUpdate.d.server_id; 24 | VoiceIdentify.d.user_id = this.gateway.voiceStateUpdate.userId; 25 | VoiceIdentify.d.session_id = this.gateway.voiceStateUpdate.sessionID; 26 | VoiceIdentify.d.token = this.gateway.voiceServerUpdate.d.token; 27 | this.websocket.send(JSON.stringify(VoiceIdentify)); 28 | }); 29 | 30 | this.websocket.on("error", (e) => 31 | this.gateway.ws.manager.builder.client.transformer.error(e.message) 32 | ); 33 | 34 | this.websocket.on("message", (data: Data) => { 35 | this.handle(data); 36 | }); 37 | } 38 | 39 | public handle(data: Data): void { 40 | const payload: Payload = JSON.parse(data.toString()); 41 | const { op, d } = payload; 42 | if (op == 2) { 43 | this.emit("ready" as EVENTS, payload); 44 | } else if (op == 8) { 45 | setInterval(() => { 46 | Heartbeat.op = 3; 47 | if (this.seq) Heartbeat.d = this.seq; 48 | this.websocket.send(JSON.stringify(Heartbeat)); 49 | }, d.heartbeat_interval); 50 | } else if (op == 6) { 51 | this.seq = d; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Client/Websocket/Handlers/READY.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | 3 | import { EvolveClient, Payload, EVENTS, ClientUser, Endpoints } from "../../.."; 4 | import { IGuild } from "../../../Interfaces/GuildOptions"; 5 | import { Guild } from "../../../Structures/Guild/Guild"; 6 | 7 | export default class { 8 | public client: EvolveClient; 9 | public payload: Payload; 10 | 11 | constructor(client: EvolveClient, payload: Payload, shard: number) { 12 | this.client = client; 13 | this.payload = payload; 14 | 15 | (async () => await this.generate(payload, shard))(); 16 | this.client.readyAt = Date.now(); 17 | this.client.sessionID = payload.d.session_id; 18 | } 19 | 20 | private async generate(payload: Payload, shard: number) { 21 | const { user, guilds } = payload.d; 22 | 23 | this.client.user = new ClientUser( 24 | user.username, 25 | user.discriminator, 26 | user.verified, 27 | user.id, 28 | user.flags, 29 | user.email, 30 | user.bot, 31 | user.avatar 32 | ); 33 | 34 | for (const guild of guilds) { 35 | const fetched: Guild = new Guild( 36 | await this.client.rest.endpoint(Endpoints.GUILD).get(guild.id), 37 | this.client 38 | ); 39 | 40 | for (const [k, v] of fetched.members) { 41 | if (this.client.options.enableUsersCache) 42 | if (v.user) this.client.users.set(k, v.user); 43 | } 44 | 45 | for (const [k, v] of fetched.channels) { 46 | if (this.client.options.enableChannelCache) 47 | this.client.channels.set(k, v); 48 | } 49 | 50 | for (const [k, v] of fetched.emojis) { 51 | if (this.client.options.enableEmojiCache) this.client.emojis.set(k, v); 52 | } 53 | 54 | for (const [k, v] of fetched.roles) { 55 | this.client.roles.set(k, v); 56 | } 57 | 58 | if (this.client.options.enableGuildCache) 59 | this.client.guilds.set(fetched.id, fetched); 60 | } 61 | 62 | this.client.emit(EVENTS.READY, shard); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Client/Websocket/Websocket.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | import ws from "ws"; 3 | import { CONSTANTS } from "../.."; 4 | import { Gateway } from "./Gateway"; 5 | import { ShardManager } from "./ShardManager"; 6 | 7 | export class EvolveSocket extends ws { 8 | public seq?: number; 9 | public gateway: Gateway = new Gateway(); 10 | 11 | constructor(public manager: ShardManager, public shard: number) { 12 | super(CONSTANTS.Gateway + manager.builder.encoding); 13 | this._init(); 14 | } 15 | 16 | public async send(data: any): Promise { 17 | let payload; 18 | if (this.manager.builder.encoding == "json") { 19 | payload = JSON.stringify(data); 20 | } else if (this.manager.builder.encoding == "etf") { 21 | try { 22 | payload = require("erlpack").pack(data); 23 | } catch (e) { 24 | throw this.manager.builder.client.transformer.error(e); 25 | } 26 | } else { 27 | throw this.manager.builder.client.transformer.error( 28 | "Invalid Encoding Type. Only JSON or etf is accepted" 29 | ); 30 | } 31 | return super.send(payload); 32 | } 33 | 34 | get shardPing(): number { 35 | return Date.now() - this.gateway.lastPingTimeStamp; 36 | } 37 | 38 | private _init(): void { 39 | this.on("error", (err: Error) => { 40 | throw this.manager.builder.client.transformer.error(err.message); 41 | }); 42 | 43 | this.on("close", (code: number, res: string) => { 44 | if (code == 4009) { 45 | this.manager.connections.set( 46 | this.shard, 47 | new EvolveSocket(this.manager, this.shard) 48 | ); 49 | this.gateway.reconnect(); 50 | this.close(); 51 | } else if (code == 4004) { 52 | throw this.manager.builder.client.transformer.error( 53 | `Code: ${code}, Response: ${res}\n Destroying Shards and Exitting Process...` 54 | ); 55 | } 56 | }); 57 | 58 | this.on("message", async (data: string) => { 59 | await this.gateway.init(data, this); 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Interfaces/Interfaces.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | import { OPCODE } from ".."; 3 | import { ChannelsManager } from "../Client/Managers/ChannelsManger"; 4 | import { EmojisManager } from "../Client/Managers/EmojisManager"; 5 | import { GuildsManager } from "../Client/Managers/GuildsManager"; 6 | import { MessagesManager } from "../Client/Managers/MessagesManager"; 7 | import { RolesManager } from "../Client/Managers/RolesManager"; 8 | import { UsersManager } from "../Client/Managers/UsersManager"; 9 | import { Overwrite } from "../Structures/Channel/Overwrite"; 10 | import { CHANNELTYPES } from "../Utils/Constants"; 11 | import { MessageEmbed } from "../Utils/Embed/MessageEmbed"; 12 | import { ICreateGuildIntegration, IGuildIntegration } from "./Integration"; 13 | 14 | export interface CacheProviders { 15 | guilds?: GuildsManager; 16 | channels?: ChannelsManager; 17 | users?: UsersManager; 18 | messages?: MessagesManager; 19 | roles?: RolesManager; 20 | emojis: EmojisManager; 21 | } 22 | 23 | export interface IAPIParams { 24 | endpoint: string; 25 | method: "GET" | "POST" | "DELETE" | "PUT" | "PATCH"; 26 | postType?: "Message" | "Channel" | "Integration" | "[Message]" | "JSON"; 27 | message?: MessageOptions; 28 | channel?: ChannelOptions; 29 | integration?: ICreateGuildIntegration; 30 | messages?: string[]; 31 | json_params?: Object; 32 | } 33 | 34 | export interface MessageOptions { 35 | content?: string; 36 | tts?: boolean; 37 | embed?: MessageEmbed; 38 | } 39 | 40 | export interface ChannelOptions { 41 | name: string; 42 | type?: CHANNELTYPES; 43 | topic?: string; 44 | bitrate?: string; 45 | user_limit?: number; 46 | rate_limit_per_user?: number; 47 | position?: number; 48 | permission_overwrites?: Array; 49 | parent_id?: string; 50 | nsfw?: boolean; 51 | } 52 | 53 | export interface Payload { 54 | op: OPCODE; 55 | t?: string; 56 | s?: number; 57 | d?: D; 58 | } 59 | -------------------------------------------------------------------------------- /src/Interfaces/MessageOptions.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-types */ 2 | import { IUser } from "./UserOptions"; 3 | import { IGuildMember } from "./GuildMemberOptions"; 4 | 5 | export interface IMessage { 6 | id: string; // ID of the message 7 | channel_id: string; // ID of the channel the message was sent in 8 | guild_id?: string; // ID of the guild the message was sent in 9 | author: IUser; // The author of this message (not guaranteed to be a valid user, see below) 10 | member?: IGuildMember; // Member properties for this message's author 11 | content: string; // Contents of the message 12 | timestamp: number; // Timestamp when this message was sent 13 | edited_timestamp: number | null; // Timestamp when this message was edited (or null if never) 14 | tts: boolean; // Whether this was a TTS message 15 | mention_everyone: boolean; // Whether this message mentions everyone 16 | mentions: IUser[]; // Users specifically mentioned in the message 17 | mention_roles: string[]; // Roles specifically mentioned in this message 18 | mention_channels?: {}; // Channels specifically mentioned in this message 19 | attachments: []; // Any attached files 20 | embeds: []; // Any embedded content 21 | reactions?: []; // Reactions to the message 22 | nonce?: number | string; // Used for validating a message was sent 23 | pinned: boolean; // Whether this message is pinned 24 | webhook_id?: string; // If the message is generated by a webhook, this is the webhook ID 25 | type: number; // Type of message 26 | activity?: {}; // Sent with Rich Presence-related chat embeds 27 | application?: {}; // Sent with Rich Presence-related chat embeds 28 | message_reference?: {}; // Reference data sent with cross-posted messages 29 | flags?: number; // Message flag 30 | sent_at: string; 31 | } 32 | 33 | export interface IChannelMention { 34 | id: string; // ID of the channel 35 | guild_id: string; // ID of the guild containing the channel 36 | type: number; // The type of channel 37 | name: string; // the name of the channel 38 | } 39 | -------------------------------------------------------------------------------- /src/Structures/Channel/TextChannel.ts: -------------------------------------------------------------------------------- 1 | import { Channel } from "./Channel"; 2 | import { Objex } from "@evolvejs/objex"; 3 | import { Overwrite } from "./Overwrite"; 4 | import { Guild } from "../Guild/Guild"; 5 | import { CategoryChannel } from "./CategoryChannel"; 6 | import { MessageEmbed } from "../../Utils/Embed/MessageEmbed"; 7 | import { Message } from "../Message/Message"; 8 | import { ITextChannel } from "../../Interfaces/TextChannelOptions"; 9 | import { CHANNELTYPES } from "../../Utils/Constants"; 10 | import { EvolveClient } from "../../Client/EvolveClient"; 11 | import { Endpoints } from "../../Utils/Endpoints"; 12 | import { IMessage } from "../../Interfaces/MessageOptions"; 13 | 14 | export class TextChannel extends Channel { 15 | public overwrites: Objex = new Objex(); 16 | 17 | public guild?: Guild; 18 | public position!: number; 19 | public name!: string; 20 | public topic?: string; 21 | public nsfw!: boolean; 22 | public lastMessage?: string; 23 | public rateLimit!: number; 24 | public parentId?: string; 25 | public lastPin?: number; 26 | public data!: ITextChannel; 27 | 28 | constructor(data: ITextChannel, client: EvolveClient) { 29 | super(data.id, CHANNELTYPES.Text, client); 30 | Object.defineProperty(this, "data", { 31 | value: data, 32 | enumerable: false, 33 | writable: false, 34 | }); 35 | this._handle(); 36 | } 37 | 38 | private _handle() { 39 | if (!this.data) return; 40 | this.guild = this.client.guilds.get(this.data.guild_id); 41 | this.position = this.data.position; 42 | this.name = this.data.name; 43 | this.topic = this.data.topic ?? ""; 44 | this.nsfw = this.data.nsfw; 45 | this.rateLimit = this.data.rate_limit_per_user; 46 | this.parentId = this.data.parent_id ?? undefined; 47 | this.lastPin = this.data.last_pin_timestamp; 48 | } 49 | 50 | public async send(content: string | MessageEmbed): Promise { 51 | return new Message( 52 | await this.client.rest 53 | .endpoint(Endpoints.CHANNEL_MESSAGES) 54 | .post( 55 | typeof content === "string" ? { content } : { embed: content }, 56 | this.id 57 | ), 58 | this.client 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Utils/EventListener.ts: -------------------------------------------------------------------------------- 1 | import { Objex } from "@evolvejs/objex"; 2 | import { EvolveClient } from "../Client/EvolveClient"; 3 | import { listeners } from "../Decorators/Events"; 4 | import { EVENTS } from "./Constants"; 5 | 6 | export class EventListener { 7 | private _objListeners: Set = new Set(); 8 | private _funcListeners = new Objex<(...args: unknown[]) => void, string>(); 9 | 10 | public listenerCount(eventName: string): number { 11 | let size = this._funcListeners.filter((name: string) => name === eventName) 12 | .size; 13 | for (const listener of this._objListeners) { 14 | if (Object.getOwnPropertyNames(listener).includes(eventName)) size += 1; 15 | } 16 | size += listeners.filter( 17 | (_: EvolveClient, key: string[]) => key[0] === eventName 18 | ).size; 19 | return size; 20 | } 21 | 22 | public addListener(o: Object): void { 23 | this._objListeners.add(o); 24 | } 25 | 26 | public removeListener(o: Object): void { 27 | this._objListeners.delete(o); 28 | } 29 | 30 | public removeAllListeners(): void { 31 | this._funcListeners.clear(); 32 | this._objListeners.clear(); 33 | listeners.clear(); 34 | } 35 | 36 | public on(name: string, listener: (...args: any[]) => void): void { 37 | this._funcListeners.set(listener, name); 38 | } 39 | 40 | public off(name: string, listener: (...args: any[]) => void): void { 41 | const value = this._funcListeners.get(listener); 42 | if (value) { 43 | if (value === name) { 44 | this._funcListeners.delete(listener); 45 | } 46 | } 47 | } 48 | 49 | public emit(name: EVENTS, ...args: any[]): void { 50 | if (this._objListeners.size !== 0) { 51 | for (const listener of this._objListeners) { 52 | if (Object.keys(listener).includes(name)) { 53 | const func = listener[(name as unknown) as keyof typeof listener]; 54 | if (typeof func !== "function") { 55 | throw new TypeError(`${func} should be type of function`); 56 | } 57 | Object.call(listener, func)(...args); 58 | } 59 | } 60 | } 61 | 62 | if (listeners) { 63 | for (const [k, v] of listeners) { 64 | if (k[0] === name) { 65 | try { 66 | const func = v[(k[1] as unknown) as keyof typeof v]; 67 | Object.call(v, func)(...args); 68 | } catch (e) { 69 | v.transformer.error(e); 70 | } 71 | } 72 | } 73 | } 74 | 75 | if (this._funcListeners.size !== 0) { 76 | for (const [key, value] of this._funcListeners) { 77 | if (value == name) { 78 | key(...args); 79 | } 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Structures/Message/Message.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 2 | /* eslint-disable no-mixed-spaces-and-tabs */ 3 | 4 | import { User, GuildMember, Guild, IMessage, Endpoints } from "../.."; 5 | import { TextChannel } from "../Channel/TextChannel"; 6 | import { EvolveClient } from "../../Client/EvolveClient"; 7 | import { promisify } from "util"; 8 | import { IGuild } from "../../Interfaces/GuildOptions"; 9 | 10 | export class Message { 11 | public sentAt!: string; 12 | public id!: string; 13 | public pinned!: boolean; 14 | public mentions: User[] = []; 15 | public rolementions?: Array; 16 | public mentionEveryone!: boolean; 17 | public member!: GuildMember | undefined; 18 | public author!: User; 19 | public editedTimestamp!: number | null; 20 | public attachments!: Array; 21 | public content!: string; 22 | public guildId?: string; 23 | public channelId!: string; 24 | public data!: IMessage; 25 | private client!: EvolveClient; 26 | 27 | constructor(data: IMessage, client: EvolveClient) { 28 | Object.defineProperty(this, "client", { 29 | value: client, 30 | writable: false, 31 | enumerable: false, 32 | }); 33 | Object.defineProperty(this, "data", { 34 | value: data, 35 | enumerable: false, 36 | writable: false, 37 | }); 38 | if (!this.data) return; 39 | if (this.data.mentions) 40 | for (const it of this.data.mentions) { 41 | this.mentions.push(new User(it)); 42 | } 43 | this.channelId = data.channel_id; 44 | this.guildId = data.guild_id; 45 | if (this.data.guild_id) 46 | this.client.rest.endpoint(Endpoints.GUILD).get(this.data.guild_id); 47 | this.sentAt = this.data.sent_at; 48 | this.id = this.data.id; 49 | this.pinned = this.data.pinned; 50 | this.rolementions = this.data.mention_roles; 51 | this.mentionEveryone = this.data.mention_everyone; 52 | if (this.data.member) this.member = new GuildMember(this.data.member); 53 | this.author = new User(this.data.author); 54 | if (this.member) this.member.user = this.author; 55 | this.editedTimestamp = this.data.edited_timestamp; 56 | this.attachments = this.data.attachments; 57 | this.content = this.data.content; 58 | return this; 59 | } 60 | 61 | public async delete(time = 0): Promise { 62 | await promisify(setTimeout)(time); 63 | return await this.client.rest 64 | .endpoint(Endpoints.CHANNEL_MESSAGE(this.channelId)) 65 | .delete(this.id); 66 | } 67 | 68 | public async edit(content: string, time = 0): Promise { 69 | await promisify(setTimeout)(time); 70 | return await this.client.rest 71 | .endpoint(Endpoints.CHANNEL_MESSAGE(this.channelId)) 72 | .patch({ content }, this.id); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Structures/Structures.ts: -------------------------------------------------------------------------------- 1 | import { EvolveClient } from "../Client/EvolveClient"; 2 | import { CategoryChannel } from "./Channel/CategoryChannel"; 3 | import { DMChannel } from "./Channel/DMChannel"; 4 | import { NewsChannel } from "./Channel/NewsChannel"; 5 | import { StoreChannel } from "./Channel/StoreChannel"; 6 | import { TextChannel } from "./Channel/TextChannel"; 7 | import { VoiceChannel } from "./Channel/VoiceChannel"; 8 | import { Emoji } from "./Guild/Emoji"; 9 | import { Guild } from "./Guild/Guild"; 10 | import { GuildMember } from "./Guild/GuildMember"; 11 | import { Role } from "./Guild/Role"; 12 | import { VoiceState } from "./Guild/VoiceState"; 13 | import { Message } from "./Message/Message"; 14 | import { MessageReaction } from "./Message/MessageReaction"; 15 | import { ClientStatus } from "./Miscs/ClientStatus"; 16 | import { PresenceUpdate } from "./User/PresenceUpdate"; 17 | import { User } from "./User/User"; 18 | 19 | export class Structures { 20 | public structures: Classes = { 21 | Emoji, 22 | DMChannel, 23 | TextChannel, 24 | VoiceChannel, 25 | CategoryChannel, 26 | NewsChannel, 27 | StoreChannel, 28 | GuildMember, 29 | Guild, 30 | Message, 31 | MessageReaction, 32 | PresenceUpdate, 33 | ClientStatus, 34 | VoiceState, 35 | Role, 36 | User, 37 | }; 38 | private client!: EvolveClient; 39 | constructor(client: EvolveClient) { 40 | Object.defineProperty(this, "client", { 41 | value: client, 42 | enumerable: false, 43 | writable: false, 44 | }); 45 | } 46 | 47 | public get(name: K): Classes[K] { 48 | if (!this.structures[name]) 49 | throw this.client.transformer.error("Invalid Structure Name"); 50 | return this.structures[name]; 51 | } 52 | 53 | public extend( 54 | name: K, 55 | extender: (structure: Classes[K]) => T 56 | ): T { 57 | try { 58 | const structure = this.get(name); 59 | const extended = extender(structure); 60 | 61 | this.structures[name] = extended; 62 | return extended; 63 | } catch (e) { 64 | throw this.client.transformer.error(e); 65 | } 66 | } 67 | } 68 | 69 | export interface Classes { 70 | Emoji: typeof Emoji; 71 | DMChannel: typeof DMChannel; 72 | TextChannel: typeof TextChannel; 73 | VoiceChannel: typeof VoiceChannel; 74 | CategoryChannel: typeof CategoryChannel; 75 | NewsChannel: typeof NewsChannel; 76 | StoreChannel: typeof StoreChannel; 77 | GuildMember: typeof GuildMember; 78 | Guild: typeof Guild; 79 | Message: typeof Message; 80 | MessageReaction: typeof MessageReaction; 81 | PresenceUpdate: typeof PresenceUpdate; 82 | ClientStatus: typeof ClientStatus; 83 | VoiceState: typeof VoiceState; 84 | Role: typeof Role; 85 | User: typeof User; 86 | } 87 | -------------------------------------------------------------------------------- /src/Interfaces/ActivityOptions.ts: -------------------------------------------------------------------------------- 1 | import { ACTIVITY } from ".."; 2 | 3 | export interface IActivity { 4 | /** 5 | * The activity name 6 | */ 7 | name: string; 8 | /** 9 | * The activity type 10 | */ 11 | type: ACTIVITY; 12 | /** 13 | * Timestamp of when the activity was added to the user's session 14 | */ 15 | created_at: number; 16 | /** 17 | * Stream url, is validated when type is 1 18 | */ 19 | url?: string | null; 20 | /** 21 | * Timestamps for start and/or end of the game 22 | */ 23 | timestamps?: ITimestamps; 24 | /** 25 | * Application id for the game 26 | */ 27 | application_id?: string; 28 | /** 29 | * What the player is currently doing 30 | */ 31 | details?: string | null; 32 | /** 33 | * The user's current party status 34 | */ 35 | state?: string | null; 36 | /** 37 | * The emoji used for a custom status 38 | */ 39 | emoji?: IActivityEmoji | null; 40 | /** 41 | * Information for the current party of the player 42 | */ 43 | party?: IParty; 44 | /** 45 | * Images for the presence and their hover texts 46 | */ 47 | assets?: IAssets; 48 | /** 49 | * Secrets for Rich Presence joining and spectating 50 | */ 51 | secrets?: ISecrets; 52 | /** 53 | * Whether or not the activity is an instanced game session 54 | */ 55 | instance?: boolean; 56 | /** 57 | * Activity flags ORd together, describes what the payload includes 58 | */ 59 | flags?: number; 60 | } 61 | 62 | export interface ITimestamps { 63 | start?: number; // Activity start time in ms 64 | end?: number; // Activity end time in ms 65 | } 66 | 67 | export interface IActivityEmoji { 68 | /** 69 | * Emoji name 70 | */ 71 | name: string; 72 | /** 73 | * Emoji ID 74 | */ 75 | id?: string; 76 | /** 77 | * Whether the emoji is animated 78 | */ 79 | animated?: boolean; 80 | } 81 | 82 | export interface IParty { 83 | /** 84 | * The id of the party 85 | */ 86 | id?: string; 87 | /** 88 | * The party's current and maximum size 89 | */ 90 | size?: [number, number]; 91 | } 92 | 93 | export interface IAssets { 94 | /** 95 | * The ID for a large asset of the activity 96 | */ 97 | large_image?: string; 98 | /** 99 | * Text displayed when hovering over the large image of the activity 100 | */ 101 | large_text?: string; 102 | /** 103 | * The ID for a small asset of the activity 104 | */ 105 | small_image?: string; 106 | /** 107 | * Text displayed when hovering over the small image of the activity 108 | */ 109 | small_text?: string; 110 | } 111 | 112 | export interface ISecrets { 113 | /** 114 | * The secret for joining a party 115 | */ 116 | join?: string; 117 | /** 118 | * The secret for spectating a game 119 | */ 120 | spectate?: string; 121 | /** 122 | * The secret for a specific instanced match 123 | */ 124 | match?: string; 125 | } 126 | -------------------------------------------------------------------------------- /scripts/nodetodeno.js: -------------------------------------------------------------------------------- 1 | const { readFile, readdirSync, appendFile, mkdir } = require("fs"); 2 | 3 | const nodeDenoReplacement = { 4 | process: "Deno", 5 | 'import { URL } from "url";': "", 6 | 'import fetch from "node-fetch";': "", 7 | 'import ws from "ws";': 8 | 'import { WebSocket as ws, WebSocketError as Error } from "https://deno.land/x/websocket@v0.0.5/mod";', 9 | "@evolvejs/objex": "https://deno.land/x/objex/mod", 10 | "sign-logger": "https://deno.land/x/sign_logger/mod", 11 | 'require("erlpack").unpack(Buffer.from(data.toString(), "binary"))': 12 | '(await (await import("https://deno.land/std/encoding/toml")).parse(new TextDecoder().decode(data as unknown as ArrayBuffer)))[0] as Payload', 13 | 'require("erlpack").pack(data)': "payload = new TextEncoder().encode(data)", 14 | }; 15 | 16 | const replaceIfPresent = (stringedData, original, replacer) => 17 | stringedData.includes(original) 18 | ? stringedData.replaceAll(original, replacer) 19 | : stringedData; 20 | 21 | function editFile(filename) { 22 | readFile(`${filename}`, (err, data) => { 23 | if (err) throw err; 24 | let stringedData = data.toString(); 25 | const args = stringedData.split(/ +/g); 26 | for (const [k, v] of Object.entries(nodeDenoReplacement)) { 27 | stringedData = replaceIfPresent(stringedData, k, v); 28 | } 29 | for (let i = 0; i < args.length; i++) { 30 | if (args[i] === "from") { 31 | const double = args[i + 1].lastIndexOf('"'); 32 | args[i + 1] = 33 | args[i + 1].slice(0, double) + ".ts" + args[i + 1].slice(double); 34 | } 35 | } 36 | stringedData = args.join(" "); 37 | stringedData = replaceIfPresent(stringedData, "...ts", "../mod.ts"); 38 | filename = replaceIfPresent(filename, "index.ts", "mod.ts"); 39 | filename = replaceIfPresent(filename, "src", "deno/src"); 40 | 41 | appendFile(filename, stringedData, {}, () => { 42 | console.log(`Wrote Data to ${filename}`); 43 | }); 44 | }); 45 | } 46 | function readDir(dirName) { 47 | try { 48 | readdirSync(dirName, { withFileTypes: true }).forEach((file) => { 49 | if (file.isDirectory()) { 50 | mkdir(`${dirName.replace("src", "deno/src")}/${file.name}`, () => { 51 | readDir(`${dirName}/${file.name}`); 52 | }); 53 | } else { 54 | editFile(`${dirName}/${file.name}`); 55 | } 56 | }); 57 | } catch (e) { 58 | console.error(e); 59 | } 60 | } 61 | 62 | mkdir("deno", () => { 63 | mkdir("deno/src", () => { 64 | mkdir("deno/.vscode", () => { 65 | appendFile( 66 | "deno/.vscode/settings.json", 67 | JSON.stringify( 68 | { 69 | "deno.enable": true, 70 | }, 71 | null, 72 | 4 73 | ), 74 | {}, 75 | () => { 76 | readFile("README.md", (err, data) => { 77 | if (err) console.error(err); 78 | 79 | appendFile("deno/README.md", data, {}, () => { 80 | appendFile( 81 | "deno/src/README.md", 82 | "# [EvolveJS README](https://github.com/EvolveJS/EvolveJS/blob/deno-master/README.md)", 83 | {}, 84 | () => { 85 | readFile("LICENSE", (err, data) => { 86 | if (err) console.error(err); 87 | 88 | appendFile("LICENSE", data, {}, () => { 89 | readDir("src"); 90 | }); 91 | }); 92 | } 93 | ); 94 | }); 95 | }); 96 | } 97 | ); 98 | }); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /src/Interfaces/GuildOptions.ts: -------------------------------------------------------------------------------- 1 | import { ChannelResolvable } from ".."; 2 | import { IEmoji } from "./EmojiOptions"; 3 | import { IRole } from "./RoleOptions"; 4 | import { IVoiceState } from "./VoiceStateOptions"; 5 | import { IGuildMember } from "./GuildMemberOptions"; 6 | import { IPresenceUpdate } from "./PresenceUpdateOptions"; 7 | 8 | export interface IGuild { 9 | id: string; // ID of the guild 10 | name: string; // Guild name (2-100 characters, excluding trailing and leading whitespace) 11 | icon: string; // Guild icon hash 12 | splash: string | null; // Guild splash hash 13 | discovery_splash: string | null; // Discovery splash hash (only present for guilds with the "DISCOVERABLE" feature) 14 | owner?: boolean; // Only true if the user is the owner of the guild 15 | owner_id: string; // The user ID of owner 16 | permissions?: number; // Total permissions for the user in the guild (excludes overrides) 17 | region: string; // Voice region ID for the guild 18 | afk_channel_id: string | null; // ID of afk channel 19 | afk_timeout: number; // AFK timeout in seconds 20 | verification_level: number; // Verification level required for the guild 21 | default_message_notifications: number; // Default message notifications level 22 | explicit_content_filter: number; // explicit content filter level 23 | roles: IRole[]; // Array of roles in the guild 24 | emojis: IEmoji[]; // Array of custom guild emojis 25 | features: string[]; // Array of guild feature strings 26 | mfa_level: number; // Required MFA level for the guild 27 | application_id: string; // Application ID of the guild creator if it is bot-created 28 | widget_enabled?: boolean; // "true" if the server widget is enabled 29 | widget_channel_id?: string; // The channel ID that the widget will generate an invite to 30 | system_channel_id?: string; // The ID of the system channel 31 | system_channel_flags: number; // System channel flags 32 | rules_channel_id?: string; // The ID of the rule channel of guilds with the "PUBLIC" feature 33 | joined_at?: number; // When this guild was joined at 34 | large?: boolean; // "true" if this is considered a large guild 35 | unavailable?: boolean; // "true" if this guild is unavailable due to an outage 36 | member_count?: number; // Total number of members in this guild 37 | voice_states?: IVoiceState[]; // States of members currently in voice channels (lacks the guild_id key) 38 | members?: IGuildMember[]; // Users in the guild 39 | channels?: ChannelResolvable[]; // Channels in the guild 40 | presences?: IPresenceUpdate[]; // Presences of the members in the guild 41 | max_presences?: number; // The maximum number of presences for the guild (25000 when null is returned) 42 | max_members?: number; // The maximum number of members for the guild 43 | vanity_url_code: string; // The vanity url code for the guild 44 | description: string; // The description for the guild, if the guild is discoverable 45 | banner: string; // Guild banner hash 46 | premium_tier: number; // Premium tier (Server Boost level) 47 | premium_subscription_count?: number; // The number of boosts this guild currently has 48 | preferred_locale: string; // The preferred locale of a guild with the "PUBLIC" feature (defaults "en-US") 49 | public_updates_channel_id?: string; // Where of guilds with the "PUBLIC" feature receive notices from Discord 50 | max_video_channel_users?: number; // The maximum amount of users in a video channel 51 | approximate_member_count?: number; // Approximate number of members in this guild 52 | approximate_presence_count?: number; // Approximate number of non-offline members in this guild 53 | } 54 | -------------------------------------------------------------------------------- /src/Utils/Endpoints.ts: -------------------------------------------------------------------------------- 1 | export class Endpoints { 2 | /* 3 | Constant 4 | */ 5 | static GUILD = "/guilds/:id"; 6 | static GUILD_PREVIEW = "/guilds/:id/preview"; 7 | static GUILD_CHANNELS = "/guilds/:id/channels"; 8 | static GUILD_MEMBERS = "/guilds/:id/members"; 9 | static GUILD_BANS = "/guilds/:id/bans"; 10 | static GUILD_ROLES = "/guilds/:id/roles"; 11 | static GUILD_PRUNE = "/guilds/:id/prune"; 12 | static GUILD_VOICE_REGIONS = "/guilds/:id/regions"; 13 | static GUILD_INVITES = "/guilds/:id/invites"; 14 | static GUILD_INTEGRATIONS = "/guilds/:id/integrations"; 15 | static GUILD_WIDGET = "/guilds/:id/widget"; 16 | static GUILD_WIDGET_JSON = "/guilds/:id/widget.json"; 17 | static GUILD_VANITY_URL = "/guilds/:id/vanity-url"; 18 | static GUILD_ICON = "/guild/:id/widget.png"; 19 | 20 | static CLIENT_USER_NICK = "/guilds/:id/members/@me/nick"; 21 | 22 | static CHANNEL = "/channels/:id"; 23 | static CHANNEL_MESSAGES = "/channels/:id/messages"; 24 | static CHANNEL_INVITES = "/channels/:id/invites"; 25 | static CHANNEL_FOLLOWERS = "/channels/:id/followers"; 26 | static TYPING = "/channels/:id/typing"; 27 | static CHANNEL_PINS = "/channels/:id/pins"; 28 | static BULK_DELETE = "/channels/:id/messages/bulk-delete"; 29 | 30 | static EMOJIS = "/guilds/:id/emojis"; 31 | 32 | static INVITE = "/invites/:id"; 33 | 34 | static CLIENT_USER = "/users/@me"; 35 | static CLIENT_USER_GUILDS = "/users/@me/guilds"; 36 | static USER = "/users/:id"; 37 | static CLIENT_USER_GUILD = "/users/@me/guilds/:id"; 38 | static CLIENT_USER_DMS = "/users/@me/channels"; 39 | static CLIENT_USER_CONNECTIONS = "/users/@me/connections"; 40 | 41 | static VOICE_REGIONS = "/voice/regions"; 42 | 43 | static WEBHOOK = "/webhooks/:id"; 44 | static CHANNEL_WEBHOOKS = "/channels/:id/webhooks"; 45 | static GUILD_WEBHOOKS = "/guilds/:id/webhooks"; 46 | /* 47 | Dynamic 48 | */ 49 | static GUILD_MEMBER = (guildId: string) => `/guilds/${guildId}/members/:id`; 50 | static GUILD_MEMBER_ROLE = (guildId: string, memberId: string) => 51 | `/guilds/${guildId}/members/${memberId}/roles/:id`; 52 | static GUILD_BAN = (guildId: string) => `/guilds/${guildId}/bans/:id`; 53 | static GUILD_ROLE = (guildId: string) => `/guilds/${guildId}/roles/:id`; 54 | static GUILD_INTEGRATION = (guildId: string) => 55 | `/guilds/${guildId}/integrations/:id`; 56 | static GUILD_INTEGRATION_SYNC = (guildId: string) => 57 | `/guilds/${guildId}/integrations/:id/sync`; 58 | 59 | static CHANNEL_MESSAGE = (channelId: string) => 60 | `/channels/${channelId}/messages/:id`; 61 | static CROSSPOST_MESSAGE = (channelId: string) => 62 | `/channels/${channelId}/messages/:id/crosspost`; 63 | static MESSAGE_REACTION = (channelId: string, emoji: string) => 64 | `/channels/${channelId}/messages/:id/reactions/${encodeURI(emoji)}/@me`; 65 | static USER_REACTION = ( 66 | channelId: string, 67 | emoji: string, 68 | messageId: string 69 | ) => 70 | `/channels/${channelId}/messages/${messageId}/reactions/${encodeURI( 71 | emoji 72 | )}/:id`; 73 | static MESSAGE_EMOJI_REACTIONS = (channelId: string, emoji: string) => 74 | `/channels/${channelId}/messages/:id/reactions/${encodeURI(emoji)}`; 75 | static MESSAGE_REACTIONS = (channelId: string) => 76 | `/channels/${channelId}/messages/:id/reactions`; 77 | static CHANNEL_PERMISSIONS = (channelId: string) => 78 | `/channels/${channelId}/permissions/:id`; 79 | static CHANNEL_PIN = (channelId: string) => `/channels/${channelId}/pins/:id`; 80 | static GROUP_DM_RECIPIENT = (channelId: string) => 81 | `/channels/${channelId}/recipients/:id`; 82 | static GUILD_EMOJI = (guildId: string) => `/guilds/${guildId}/emojis/:id`; 83 | 84 | static WEBHOOK_TOKEN = (webhookId: string) => `/webhooks/${webhookId}/:id`; 85 | static WEBHOOK_SLACK = (webhookId: string) => 86 | `/webhooks/${webhookId}/:id/slack`; 87 | static WEBHOOK_GITHUB = (webhookId: string) => 88 | `/webhooks/${webhookId}/:id/github`; 89 | } 90 | -------------------------------------------------------------------------------- /src/Client/EvolveClient.ts: -------------------------------------------------------------------------------- 1 | import { Transformer } from "sign-logger"; 2 | import { Oauth2 } from "../Oauth2/Oauth2"; 3 | import { Structures } from "../Structures/Structures"; 4 | import { EventListener } from "../Utils/EventListener"; 5 | import { GuildsManager } from "./Managers/GuildsManager"; 6 | import { ChannelsManager } from "./Managers/ChannelsManger"; 7 | import { UsersManager } from "./Managers/UsersManager"; 8 | import { RolesManager } from "./Managers/RolesManager"; 9 | import { MessagesManager } from "./Managers/MessagesManager"; 10 | import { EmojisManager } from "./Managers/EmojisManager"; 11 | import { ClientOptions } from "./ClientOptions"; 12 | import { RestAPI } from "./RestAPI/RestAPI"; 13 | import { ClientUser } from "./ClientUser"; 14 | import { ShardManager } from "./Websocket/ShardManager"; 15 | 16 | /** 17 | * The Client which was given by EvolveBuilder#build 18 | * @type {EvolveClient} 19 | * @class 20 | * @extends {EventListener} 21 | */ 22 | export class EvolveClient extends EventListener { 23 | /** 24 | * The Bot Token 25 | * @type {string} 26 | */ 27 | public token: string; 28 | /** 29 | * Client Caching Options 30 | * @type {ClientOptions} 31 | */ 32 | public options: ClientOptions; 33 | /** 34 | * The Guilds and Guilds Cache Managet 35 | * @type {GuildsManager} 36 | */ 37 | public guilds: GuildsManager = new GuildsManager(this); 38 | /** 39 | * The Channels and Channels Cache Manager 40 | * @type {ChannelsManageer} 41 | */ 42 | public channels: ChannelsManager = new ChannelsManager(this); 43 | /** 44 | * The Users and UsersCacheManager 45 | * @type {UsersManager} 46 | */ 47 | public users: UsersManager = new UsersManager(); 48 | /** 49 | * The Emojis and Emoji Cache Manager 50 | * @type {EmojisManager} 51 | */ 52 | public emojis: EmojisManager = new EmojisManager(); 53 | /** 54 | * The Roles and Role Cache Manager 55 | * @type {RolesManager} 56 | */ 57 | public roles: RolesManager = new RolesManager(); 58 | /** 59 | * The Messsages and Message Cache Manager 60 | * @type {MessagesManager} 61 | */ 62 | public messages: MessagesManager = new MessagesManager(); 63 | /** 64 | * The Client User Object 65 | * @type {ClientUser} 66 | */ 67 | public user!: ClientUser; 68 | /** 69 | * The RestAPI Class for handling the Discord Rest Api 70 | * @type {RestAPI} 71 | * @readonly 72 | */ 73 | public readonly rest: RestAPI = new RestAPI(this); 74 | /** 75 | * The sharder/shard manager is used for handling of destroying and launching shards 76 | * @type {ShardManager} 77 | */ 78 | public sharder!: ShardManager; 79 | /** 80 | * The Discord Oauth2 Handler 81 | * @type {Oauth2} 82 | */ 83 | public oauth2!: Oauth2; 84 | /** 85 | * The Client Secret for Oauth2 86 | * @type {string} 87 | */ 88 | public secret!: string; 89 | /** 90 | * The Structures Class 91 | * @type {Structures} 92 | */ 93 | public structures: Structures = new Structures(this); 94 | /** 95 | * Sign Logger for customized logging 96 | * @type {Transformer} 97 | */ 98 | public readonly transformer: Transformer = new Transformer().setSymbols([ 99 | "[", 100 | "]", 101 | ]); 102 | /** 103 | * The Session ID which was collected in the READY Event 104 | * @type {string} 105 | */ 106 | public sessionID!: string; 107 | /** 108 | * The Time when the READY Event was fired 109 | * @type {number} 110 | */ 111 | public readyAt!: number; 112 | 113 | /** 114 | * @constructor 115 | * @param token 116 | * @param options 117 | */ 118 | public constructor(token: string, options: ClientOptions) { 119 | super(); 120 | this.token = token; 121 | this.options = options; 122 | if (!this.token) throw this.transformer.error("No token provided"); 123 | } 124 | 125 | get uptime(): number { 126 | if (!this.readyAt) 127 | throw this.transformer.error("EvolveClient not ready yet..."); 128 | return Date.now() - this.readyAt; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | EvolveJS Logo 4 |

5 |

6 | Discord 7 | Twitter 8 | License 9 | Downloads 10 | Dependencies 11 |

12 |
13 |

14 | Status Banner 15 |

16 | 17 | # What is EvolveJS? 18 | **EvolveJS is a Discord Library in which bots can be made. We provide high control over the module so that the customizability can be the top of the level. 19 | Have fun with the library and happy coding :)** 20 | 21 | # Node and Deno Support 22 | **Often times people ask node and deno are different in many ways so how can a library be present in both? Well in our case we have a [simple script](https://github.com/EvolveJS/EvolveJS/blob/master/scripts/nodetodeno.js) which just changes some of the internals of the library and pushed to the [deno-master](https://github.com/EvolveJS/EvolveJS/blob/deno-master) branch... Note: The Docs are valid for both node and deno as the user experience is same...** 23 | 24 | # Installation 25 | 26 | **Node Usage** 27 | 28 | ```shell script 29 | npm install @evolvejs/evolvejs 30 | ``` 31 | **Deno Usage** 32 | - **Import from `https://deno.land/x/evolvejs`** 33 | 34 | # Important 35 | 36 | **You need the following things before you can kick off with EvolveJS:** 37 | 38 | **Node:** 39 | - [**NodeJS v15 Installed**](https://www.nodejs.org) 40 | 41 | **Deno** 42 | - [**Deno Installed**](https://deno.land) 43 | 44 | # Documentation and Support 45 | 46 | - **[Official Docs](https://evolve.js.org)** 47 | Note :- The Docs aren't completed 48 | - **For any further query and support join us at [EvolveJS](https://discord.gg/9bnpjqY) discord.** 49 | 50 | # Basic Startup Guide 51 | 52 | **Example code for running the client** 53 | 54 | ```js 55 | const { EvolveBuilder, GatewayIntents, CacheOptions } = require("@evolvejs/evolvejs") 56 | const client = new EvolveBuilder() 57 | .setToken("") 58 | .setShards(2) 59 | .enableIntents(GatewayIntent.GUILD) 60 | .enableCache(CacheOptions.GUILD) 61 | .build() 62 | 63 | client.on("clientReady", () => { 64 | console.log(client.user.username) // logs the client's username when all shard is ready 65 | }) 66 | 67 | client.sharder.on("shardSpawn", (id) => console.log(`${id} shard is now online`)) 68 | client.sharder.on("shardDestroy", (id) => console.log(`${id} shard is destryed`)) 69 | ``` 70 | **Incase of Deno use https://deno.land/x/evolvejs instead of @evolvejs/evolvejs** 71 | 72 | # More Information 73 | - **If you want to use ETF for Payloads Sending, just use EvolveBuilder#setEncoding, make sure to install erlpack, as it's a dev dependency of the package** 74 | - **If you want to contribute, you can star the repo or make pull request, but the pull request should be on the development branch, id you are adding anything from [#4](https://github.com/EvolveJS/EvolveJS/issues/4), just comment saying *feature* has been implemented** 75 | 76 | # Author(s) 77 | 78 | - [**RoMeAh**](https://github.com/RoMeAh) 79 | 80 | - [**Collbrothers**](https://github.com/Collbrothers) 81 | 82 | - **[nerdthatnoonelikes](https://github.com/nerdthatnoonelikes)** 83 | 84 | ## Contributor 85 | 86 | - **[Olyno](https://github.com/Olyno)** 87 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Client/EvolveBuilder"; 2 | export * from "./Client/EvolveClient"; 3 | export * from "./Client/ClientOptions"; 4 | export * from "./Decorators/Builder"; 5 | export * from "./Decorators/Events"; 6 | export * from "./Client/ClientUser"; 7 | export * from "./Client/RestAPI/RestAPI"; 8 | export * from "./Client/RestAPI/RestAPIHandler"; 9 | export * from "./Client/Websocket/Gateway"; 10 | export * from "./Client/Websocket/Websocket"; 11 | export * from "./Client/Events/BaseEvent"; 12 | export * from "./Client/Events/ChannelEvents"; 13 | export * from "./Client/Events/GuildBanEvents"; 14 | export * from "./Client/Events/GuildEmojiEvents"; 15 | export * from "./Client/Events/GuildEvents"; 16 | export * from "./Client/Events/GuildIntegrationEvents"; 17 | export * from "./Client/Events/GuildMemberEvents"; 18 | export * from "./Client/Events/GuildMembersChunkEvents"; 19 | export * from "./Client/Events/GuildRoleEvents"; 20 | export * from "./Client/Events/MessageEvents"; 21 | export * from "./Client/Events/MessageReactionEvents"; 22 | export * from "./Interfaces/ActivityOptions"; 23 | export * from "./Interfaces/CategoryChannelOptions"; 24 | export * from "./Interfaces/DMChannelOptions"; 25 | export * from "./Interfaces/EmojiOptions"; 26 | export * from "./Interfaces/GroupChannelOptions"; 27 | export * from "./Interfaces/GuildMemberOptions"; 28 | export * from "./Interfaces/GuildOptions"; 29 | export * from "./Interfaces/Interfaces"; 30 | export * from "./Interfaces/InviteOptions"; 31 | export * from "./Interfaces/InviteOptions"; 32 | export * from "./Interfaces/MessageOptions"; 33 | export * from "./Interfaces/NewsChannelOptions"; 34 | export * from "./Interfaces/OverwriteOptions"; 35 | export * from "./Interfaces/PresenceUpdateOptions"; 36 | export * from "./Interfaces/RoleOptions"; 37 | export * from "./Interfaces/StoreChannelOptions"; 38 | export * from "./Interfaces/MessageReactionOptions"; 39 | export * from "./Interfaces/TextChannelOptions"; 40 | export * from "./Interfaces/UserOptions"; 41 | export * from "./Interfaces/VoiceChannelOptions"; 42 | export * from "./Interfaces/VoiceRegionOptions"; 43 | export * from "./Interfaces/VoiceStateOptions"; 44 | export * from "./Interfaces/WebhookOptions"; 45 | export * from "./Oauth2/Oauth2"; 46 | export * from "./Structures/Channel/CategoryChannel"; 47 | export * from "./Structures/Channel/Channel"; 48 | export * from "./Structures/Channel/DMChannel"; 49 | export * from "./Structures/Channel/GroupChannel"; 50 | export * from "./Structures/Channel/NewsChannel"; 51 | export * from "./Structures/Channel/Overwrite"; 52 | export * from "./Structures/Channel/StoreChannel"; 53 | export * from "./Structures/Channel/TextChannel"; 54 | export * from "./Structures/Channel/VoiceChannel"; 55 | export * from "./Structures/Guild/Emoji"; 56 | export * from "./Structures/Guild/Guild"; 57 | export * from "./Structures/Guild/GuildMember"; 58 | export * from "./Structures/Guild/Invite"; 59 | export * from "./Structures/Guild/Role"; 60 | export * from "./Structures/Guild/VoiceState"; 61 | export * from "./Structures/Guild/Webhook"; 62 | export * from "./Structures/Message/Message"; 63 | export * from "./Structures/Message/MessageReaction"; 64 | export * from "./Structures/Miscs/ClientStatus"; 65 | export * from "./Structures/User/Activity"; 66 | export * from "./Structures/User/PresenceUpdate"; 67 | export * from "./Structures/User/User"; 68 | export * from "./Structures/Structures"; 69 | export * from "./Utils/Embed/EmbedBuilder"; 70 | export * from "./Utils/Embed/EmbedAuthor"; 71 | export * from "./Utils/Embed/EmbedField"; 72 | export * from "./Utils/Embed/EmbedFooter"; 73 | export * from "./Utils/Embed/EmbedImage"; 74 | export * from "./Utils/Embed/EmbedProvider"; 75 | export * from "./Utils/Embed/EmbedThumbnail"; 76 | export * from "./Utils/Embed/EmbedVideo"; 77 | export * from "./Utils/Embed/MessageEmbed"; 78 | export * from "./Utils/Collectors/BaseCollector"; 79 | export * from "./Utils/Collectors/MessageCollector"; 80 | export * from "./Utils/Collectors/MessageReactionCollector"; 81 | export * from "./Utils/Constants"; 82 | export * from "./Utils/EventListener"; 83 | export * from "./Utils/AsyncronousQueue"; 84 | export * from "./Utils/Endpoints"; 85 | -------------------------------------------------------------------------------- /src/Client/Websocket/Gateway.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-types */ 2 | /* eslint-disable no-mixed-spaces-and-tabs */ 3 | import { EvolveSocket } from "./Websocket"; 4 | import { OPCODE, Heartbeat, Identify, VoiceStateUpdate } from "../.."; 5 | import { Payload } from "../../Interfaces/Interfaces"; 6 | import { VoiceGateway } from "./Voice/VoiceGateway"; 7 | import { EVENTS } from "../../Utils/Constants"; 8 | import { VoiceState } from "../../Structures/Guild/VoiceState"; 9 | 10 | export class Gateway { 11 | public data!: string; 12 | public ws!: EvolveSocket; 13 | public launchedShards: Set = new Set(); 14 | public voice!: VoiceGateway; 15 | public voiceStateUpdate!: VoiceState; 16 | public voiceServerUpdate!: Payload; 17 | public shard!: number; 18 | public lastPingTimeStamp!: number; 19 | 20 | public async init(data: string, ws: EvolveSocket): Promise { 21 | this.data = data; 22 | this.ws = ws; 23 | this.shard = this.ws.shard; 24 | 25 | try { 26 | let payload: Payload; 27 | if (this.ws.manager.builder.encoding == "json") { 28 | payload = JSON.parse(data.toString()); 29 | } else { 30 | try { 31 | payload = require("erlpack").unpack( 32 | Buffer.from(data.toString(), "binary") 33 | ); 34 | } catch (e) { 35 | throw this.ws.manager.builder.client.transformer.error(e); 36 | } 37 | } 38 | const { op, t, d } = payload; 39 | if (!d) return; 40 | 41 | if (op === OPCODE.Hello) { 42 | // Command: Heartbeat 43 | this._spawn(this.shard); 44 | 45 | setInterval(() => { 46 | this.lastPingTimeStamp = Date.now(); 47 | this.ws.send(Heartbeat); 48 | }, d.heartbeat_interval); 49 | } else if (op === OPCODE.Reconnect) { 50 | this.ws.manager.connections.set( 51 | this.shard, 52 | new EvolveSocket(this.ws.manager, this.shard) 53 | ); 54 | this.reconnect(); 55 | this.ws.close(); 56 | } else if (t) { 57 | this.ws.manager.builder.client.emit(EVENTS.RAW, { 58 | name: t, 59 | payload, 60 | shard: this.shard, 61 | }); 62 | try { 63 | const { default: handler } = await import(`./Handlers/${t}`); 64 | new handler(this.ws.manager.builder.client, payload, this.shard); 65 | } catch (e) { 66 | this.ws.manager.builder.client.transformer.error(e); 67 | } 68 | } 69 | } catch (e) { 70 | this.ws.manager.builder.client.transformer.error(e); 71 | } 72 | } 73 | 74 | private _spawn(shard: number): void { 75 | Identify.d.token = this.ws.manager.builder.client.token; 76 | Identify.d.activity = this.ws.manager.builder.activity; 77 | Identify.d.shard = [shard, this.ws.manager.builder.shards]; 78 | Identify.d.intents = this.ws.manager.builder.intents; 79 | 80 | if (this._debug(shard)) { 81 | this.ws.send(Identify); 82 | } 83 | } 84 | 85 | public destroy(): void { 86 | this.ws.manager.connections.delete(this.shard); 87 | this.ws.manager.emit(EVENTS.SHARD_DESTROY, this.shard); 88 | this.ws.close(); 89 | } 90 | 91 | private _debug(shard: number): boolean { 92 | this.ws.manager.emit(EVENTS.SHARD_SPAWN, shard); 93 | return true; 94 | } 95 | 96 | public reconnect(): void { 97 | const payload: Payload = { 98 | op: OPCODE.Resume, 99 | d: { 100 | token: this.ws.manager.builder.client.token, 101 | session_id: this.ws.manager.builder.client.sessionID, 102 | seq: this.ws.seq, 103 | }, 104 | }; 105 | this.ws.send(payload); 106 | } 107 | 108 | public sendVoiceStateUpdate( 109 | guildID: string, 110 | channelID: string, 111 | options?: { 112 | self_deaf: boolean; 113 | self_mute: boolean; 114 | }, 115 | initialize = false 116 | ): void { 117 | VoiceStateUpdate.d.guild_id = guildID; 118 | VoiceStateUpdate.d.channel_id = channelID; 119 | if (options) { 120 | VoiceStateUpdate.d.self_deaf = options.self_deaf; 121 | VoiceStateUpdate.d.self_mute = options.self_mute; 122 | } 123 | 124 | this.ws.send(VoiceStateUpdate); 125 | 126 | this.ws.manager.builder.client.on(EVENTS.VOICE_STATE_UPDATE, (pk) => { 127 | if (pk.member.user.id !== this.ws.manager.builder.client.user.id) return; 128 | this.voiceStateUpdate = pk; 129 | if (this.voiceStateUpdate && this.voiceServerUpdate && !this.voice) { 130 | this.voice = new VoiceGateway(this); 131 | this.voice.emit( 132 | EVENTS.PACKET_READY, 133 | (this.voiceStateUpdate, this.voiceServerUpdate) 134 | ); 135 | if (initialize) this.voice.init(); 136 | } 137 | }); 138 | 139 | this.ws.manager.builder.client.on(EVENTS.VOICE_SERVER_UPDATE, (pk) => { 140 | this.voiceServerUpdate = pk; 141 | if (this.voiceStateUpdate && this.voiceServerUpdate && !this.voice) { 142 | this.voice = new VoiceGateway(this); 143 | this.voice.emit( 144 | EVENTS.PACKET_READY, 145 | (this.voiceStateUpdate, this.voiceServerUpdate, this.shard) 146 | ); 147 | if (initialize) this.voice.init(); 148 | } 149 | }); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Utils/Embed/EmbedBuilder.ts: -------------------------------------------------------------------------------- 1 | import { URL } from "url"; 2 | import { 3 | IEmbedThumbnail, 4 | IEmbedVideo, 5 | IEmbedImage, 6 | IEmbedAuthor, 7 | IEmbedFooter, 8 | IEmbedProvider, 9 | IEmbedField, 10 | EmbedThumbnailBuilder, 11 | EmbedVideoBuilder, 12 | EmbedImageBuilder, 13 | EmbedAuthorBuilder, 14 | EmbedFooterBuilder, 15 | EmbedProviderBuilder, 16 | EmbedFieldBuilder, 17 | MessageEmbed, 18 | } from "../.."; 19 | 20 | export class EmbedBuilder { 21 | private title!: string; 22 | private type!: string; 23 | private description!: string; 24 | private timestamp!: number; 25 | private url!: string; 26 | private color!: number; 27 | private thumbnail!: IEmbedThumbnail; 28 | private video!: IEmbedVideo; 29 | private image!: IEmbedImage; 30 | private author!: IEmbedAuthor; 31 | private footer!: IEmbedFooter; 32 | private provider!: IEmbedProvider; 33 | private fields: IEmbedField[] = []; 34 | 35 | public setTitle(title: string): EmbedBuilder { 36 | this.title = title; 37 | return this; 38 | } 39 | 40 | public setType( 41 | type: "rich" | "image" | "video" | "gifv" | "article" | "link" 42 | ): EmbedBuilder { 43 | this.type = type; 44 | return this; 45 | } 46 | 47 | public setDescription(description: string): EmbedBuilder { 48 | this.description = description; 49 | return this; 50 | } 51 | 52 | public appendDescription(description: string): EmbedBuilder { 53 | this.description += description; 54 | return this; 55 | } 56 | 57 | public setTimestamp(timestamp: number): EmbedBuilder { 58 | this.timestamp = timestamp; 59 | return this; 60 | } 61 | 62 | public setURL(url: URL): EmbedBuilder { 63 | this.url = url.toString(); 64 | return this; 65 | } 66 | 67 | public setColor(color: number): EmbedBuilder { 68 | this.color = color; 69 | return this; 70 | } 71 | 72 | public setThumbnail( 73 | url: URL, 74 | proxyURL?: URL, 75 | height?: number, 76 | width?: number 77 | ): EmbedBuilder { 78 | const thumbnail = new EmbedThumbnailBuilder(); 79 | if (url) thumbnail.setURL(url); 80 | if (proxyURL) thumbnail.setProxyURL(proxyURL); 81 | if (height) thumbnail.setHeight(height); 82 | if (width) thumbnail.setWidth(width); 83 | 84 | this.thumbnail = thumbnail.build(); 85 | return this; 86 | } 87 | 88 | public setVideo(url: URL, height?: number, width?: number): EmbedBuilder { 89 | const video = new EmbedVideoBuilder(); 90 | if (url) video.setURL(url); 91 | if (height) video.setHeight(height); 92 | if (width) video.setWidth(width); 93 | 94 | this.video = video.build(); 95 | return this; 96 | } 97 | 98 | public setImage( 99 | url: URL, 100 | proxyURL?: string, 101 | height?: number, 102 | width?: number 103 | ): EmbedBuilder { 104 | const image = new EmbedImageBuilder(); 105 | if (url) image.setURL(url); 106 | if (proxyURL) image.setProxyURL(url); 107 | if (height) image.setHeight(height); 108 | if (width) image.setWidth(width); 109 | 110 | this.image = image.build(); 111 | return this; 112 | } 113 | 114 | public setAuthor( 115 | text?: string, 116 | url?: URL, 117 | iconURL?: URL, 118 | proxyIconURL?: URL 119 | ): EmbedBuilder { 120 | const author = new EmbedAuthorBuilder(); 121 | if (text) author.setName(text); 122 | if (url) author.setURL(url); 123 | if (iconURL) author.setIconURL(iconURL); 124 | if (proxyIconURL) author.setProxyIconURL(proxyIconURL); 125 | 126 | this.author = author.build(); 127 | return this; 128 | } 129 | 130 | public setFooter(text?: string, url?: URL, proxyURL?: URL): EmbedBuilder { 131 | const footer = new EmbedFooterBuilder(); 132 | if (text) footer.setText(text); 133 | if (url) footer.setIconUrl(url); 134 | if (proxyURL) footer.setProxyIconUrl(proxyURL); 135 | 136 | this.footer = footer.build(); 137 | return this; 138 | } 139 | 140 | public setProvider(name?: string, url?: URL): EmbedBuilder { 141 | const provider = new EmbedProviderBuilder(); 142 | if (name) provider.setName(name); 143 | if (url) provider.setURL(url); 144 | 145 | this.provider = provider.build(); 146 | return this; 147 | } 148 | 149 | public addField(key: string, value: string, inline = false): EmbedBuilder { 150 | const field: IEmbedField = new EmbedFieldBuilder() 151 | .setName(key) 152 | .setValue(value) 153 | .enableInline(inline) 154 | .build(); 155 | this.fields.push(field); 156 | return this; 157 | } 158 | 159 | public addFields( 160 | ...fields: { key: string; value: string; inline?: boolean }[] 161 | ): EmbedBuilder { 162 | for (const field of fields) { 163 | this.addField(field.key, field.value, field.inline); 164 | } 165 | 166 | return this; 167 | } 168 | 169 | public build(): MessageEmbed { 170 | return { 171 | title: this.title, 172 | type: this.type, 173 | description: this.description, 174 | url: this.url, 175 | timestamp: this.timestamp, 176 | color: this.color, 177 | footer: this.footer, 178 | image: this.image, 179 | thumnail: this.thumbnail, 180 | video: this.video, 181 | provider: this.provider, 182 | author: this.author, 183 | fields: this.fields, 184 | }; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/Structures/Guild/Guild.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-mixed-spaces-and-tabs */ 2 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ 3 | import { 4 | EvolveClient, 5 | GuildMember, 6 | Role, 7 | Emoji, 8 | VoiceState, 9 | PresenceUpdate, 10 | IGuild, 11 | } from "../.."; 12 | import { Objex } from "@evolvejs/objex"; 13 | import { ChannelsManager } from "../../Client/Managers/ChannelsManger"; 14 | import { Endpoints } from "../../Utils/Endpoints"; 15 | import { ChannelResolver } from "../../Utils/Constants"; 16 | import { IGuildMember } from "../../Interfaces/GuildMemberOptions"; 17 | import { UsersManager } from "../../Client/Managers/UsersManager"; 18 | import { RolesManager } from "../../Client/Managers/RolesManager"; 19 | import { EmojisManager } from "../../Client/Managers/EmojisManager"; 20 | 21 | export class Guild { 22 | public client!: EvolveClient; 23 | public members: Objex = new Objex(); 24 | public channels!: ChannelsManager; 25 | public roles: RolesManager = new Objex(); 26 | public emojis: EmojisManager = new Objex(); 27 | public voiceStates: Objex = new Objex(); 28 | public presences: Objex = new Objex(); 29 | public features: Array = []; 30 | 31 | public id: string; 32 | public name!: string; 33 | public icon!: string; 34 | public splash?: string; 35 | public discoverySplash?: string; 36 | public isOwner?: boolean; 37 | public ownerId?: string; 38 | public permissions?: number; 39 | public region!: string; 40 | public afkChannelId?: string; 41 | public afkTimeout!: number; 42 | public verificationLevel!: number; 43 | public defMessageNotify!: number; 44 | public explicitContentFilter!: number; 45 | public mfaLevel!: number; 46 | public applicationID?: string; 47 | public widgetEnabled!: boolean; 48 | public widgetChannelId?: string; 49 | public systemChannelId?: string; 50 | public systemChannelFlag!: number; 51 | public rulesChannelId?: string; 52 | public joinedAt?: number; 53 | public large!: boolean; 54 | public unavailable!: boolean; 55 | public memberCount!: number; 56 | public maxPresences?: number; 57 | public maxMembers?: number; 58 | public vanityCode?: string; 59 | public description?: string; 60 | public banner?: string; 61 | public premiumTier!: number; 62 | public premiumSubCount!: number; 63 | public preferredLang!: string; 64 | public updatesChannelId?: string; 65 | public maxChannelUsers?: number; 66 | public data!: IGuild; 67 | 68 | constructor(data: IGuild, client: EvolveClient) { 69 | Object.defineProperty(this, "client", { 70 | value: client, 71 | enumerable: false, 72 | writable: false, 73 | }); 74 | Object.defineProperty(this, "data", { 75 | value: data, 76 | enumerable: false, 77 | writable: false, 78 | }); 79 | this.id = data.id; 80 | this.channels = new ChannelsManager(client, this); 81 | this._handle(); 82 | } 83 | 84 | private _handle() { 85 | if (!this.data) return; 86 | this.data.emojis.forEach((o) => { 87 | this.emojis.set(o.id, new Emoji(o)); 88 | }); 89 | 90 | this.data.roles.forEach((o) => { 91 | this.roles.set(o.id, new Role(o)); 92 | }); 93 | 94 | this.name = this.data.name; 95 | this.icon = this.data.icon; 96 | this.splash = this.data.splash || undefined; 97 | this.discoverySplash = this.data.discovery_splash || undefined; 98 | this.isOwner = this.data.owner; 99 | this.ownerId = this.data.owner_id; 100 | this.permissions = this.data.permissions; 101 | this.region = this.data.region; 102 | this.afkChannelId = this.data.afk_channel_id ?? undefined; 103 | this.afkTimeout = this.data.afk_timeout; 104 | this.verificationLevel = this.data.verification_level; 105 | this.defMessageNotify = this.data.default_message_notifications; 106 | this.explicitContentFilter = this.data.explicit_content_filter; 107 | this.mfaLevel = this.data.mfa_level; 108 | this.applicationID = this.data.application_id || undefined; 109 | this.widgetEnabled = this.data.widget_enabled ?? false; 110 | this.widgetChannelId = this.data.widget_channel_id ?? undefined; 111 | this.systemChannelId = this.data.system_channel_id ?? undefined; 112 | this.systemChannelFlag = this.data.system_channel_flags; 113 | this.rulesChannelId = this.data.rules_channel_id ?? undefined; 114 | this.joinedAt = this.data.joined_at ?? undefined; 115 | this.large = this.data.large ?? false; 116 | this.unavailable = this.data.unavailable ?? false; 117 | this.memberCount = this.members.size; 118 | this.maxPresences = this.data.max_presences ?? undefined; 119 | this.maxMembers = this.data.max_members; 120 | this.vanityCode = this.data.vanity_url_code ?? undefined; 121 | this.description = this.data.description ?? undefined; 122 | this.banner = this.data.banner ?? undefined; 123 | this.premiumTier = this.data.premium_tier; 124 | this.premiumSubCount = this.data.premium_subscription_count ?? 0; 125 | this.preferredLang = this.data.preferred_locale; 126 | this.updatesChannelId = this.data.public_updates_channel_id ?? undefined; 127 | this.maxChannelUsers = this.data.max_video_channel_users; 128 | return this; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /scripts/gendocs.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const typedoc = require("typedoc"); 3 | const path = require("path"); 4 | 5 | const { version } = require("../package.json"); 6 | 7 | const app = new typedoc.Application(); 8 | 9 | app.options.addReader(new typedoc.TSConfigReader()); 10 | 11 | function getConvertedType(type) { 12 | if (type.type === "query") { 13 | if (type.queryType.type === "reference") { 14 | return { 15 | ...type.queryType, 16 | }; 17 | } 18 | } 19 | return type; 20 | } 21 | 22 | function getSignature(signature) { 23 | if ( 24 | signature.flags && 25 | (!signature.flags.isExported || signature.flags.isPrivate) 26 | ) { 27 | return; 28 | } 29 | 30 | if (signature.comment && typeof signature.comment !== "string") { 31 | signature.comment = Object.fromEntries( 32 | Object.entries(signature.comment) 33 | .filter(([k, v]) => typeof v == "string") 34 | .map(([k, v]) => [k, v.replace(/(\r\n|\n|\r)/gm, "")]) 35 | ); 36 | } else if (signature.comment && typeof signature.comment == "string") { 37 | signature.comment.replace(/(\r\n|n\n|\r)/gm, ""); 38 | } 39 | 40 | if (signature.type) { 41 | signature.type = getConvertedType(signature.type); 42 | } 43 | 44 | if (signature.parameters) { 45 | signature.parameters = getParameters(signature); 46 | } 47 | 48 | // cleanup 49 | delete signature.kindString; 50 | delete signature.flags; 51 | return signature; 52 | } 53 | 54 | function getParameters(object) { 55 | const parameters = []; 56 | for (let i = 0; i < object.parameters.length; i++) { 57 | const parameter = object.parameters[i]; 58 | if ( 59 | parameter.flags && 60 | (!parameter.flags.isExported || parameter.flags.isPrivate) 61 | ) { 62 | continue; 63 | } 64 | 65 | if (parameter.comment) { 66 | parameter.comment = Object.fromEntries( 67 | Object.entries(parameter.comment).map(([k, v]) => [ 68 | k, 69 | v.replace(/(\r\n|\n|\r)/gm, ""), 70 | ]) 71 | ); 72 | } 73 | 74 | if (parameter.type) { 75 | parameter.type = getConvertedType(parameter.type); 76 | } 77 | 78 | if (parameter.flags.isOptional) { 79 | parameter.optional = true; 80 | } 81 | 82 | // cleanup 83 | delete parameter.kindString; 84 | delete parameter.flags; 85 | parameters.push(parameter); 86 | } 87 | return parameters; 88 | } 89 | 90 | function getSignatures(object) { 91 | const signatures = []; 92 | for (let i = 0; i < object.signatures.length; i++) { 93 | let signature = object.signatures[i]; 94 | signature = getSignature(signature); 95 | if (signature) signatures.push(signature); 96 | } 97 | return signatures; 98 | } 99 | 100 | function getChildren(object) { 101 | const children = []; 102 | for (let i = 0; i < object.children.length; i++) { 103 | const child = object.children[i]; 104 | if (!(child.flags.isExported ?? true) || (child.flags.isPrivate ?? false)) { 105 | continue; 106 | } 107 | if (child.children) { 108 | children.push(...getChildren(child)); 109 | child.children = child.children.map((x) => x.id); 110 | } 111 | if ( 112 | child.sources && 113 | child.sources.every((x) => x.fileName.startsWith("node_modules")) 114 | ) { 115 | continue; 116 | } 117 | 118 | if (child.sources) child.source = child.sources[0]; 119 | 120 | if (child.comment && typeof child.comment !== "string") { 121 | child.comment = Object.fromEntries( 122 | Object.entries(child.comment) 123 | .filter(([k, v]) => typeof v == "string") 124 | .map(([k, v]) => [k, v.replace(/(\r\n|\n|\r)/gm, "")]) 125 | ); 126 | } else if (child.comment && typeof child.comment == "string") { 127 | child.comment.replace(/(\r\n|\n|\r)/gm, ""); 128 | } 129 | 130 | if (child.type) { 131 | child.type = getConvertedType(child.type); 132 | } 133 | 134 | if (child.signatures) { 135 | child.signatures = getSignatures(child); 136 | } 137 | 138 | // cleanup 139 | delete child.kindString; 140 | delete child.flags; 141 | delete child.sources; 142 | if (child.source) delete child.source.character; 143 | if (child.getSignature) { 144 | delete child.getSignature; 145 | } 146 | if (child.signatures && !child.signatures.length) delete child.signatures; 147 | 148 | children.push(child); 149 | } 150 | return children.sort((a, b) => a.id - b.id); 151 | } 152 | 153 | function cleanNames(json) { 154 | const newJson = []; 155 | 156 | for (let i = 0; i < json.length; i++) { 157 | json[i].name = json[i].name.split("/").pop(); 158 | if (json[i].name.endsWith("ts")) 159 | json[i].name = json[i].name.split(".").pop(); 160 | 161 | if (json[i].name.includes('"')) 162 | json[i].name = json[i].name.replace('"', ""); 163 | 164 | newJson.push(json[i]); 165 | } 166 | return newJson; 167 | } 168 | 169 | app.bootstrap({ 170 | tsconfig: path.join(__dirname, "..", "tsconfig.json"), 171 | entryPoints: [path.join(__dirname, "..", "src/")], 172 | }); 173 | 174 | const project = app.convert(); 175 | if (project) { 176 | const outputJson = app.serializer.projectToObject(project); 177 | let customJson = getChildren(outputJson); 178 | customJson = cleanNames(customJson); 179 | fs.writeFile( 180 | path.join(__dirname, "..", `${process.argv[2] || version}.json`), 181 | JSON.stringify(customJson, null, 4), 182 | (err) => { 183 | if (err) console.error(err); 184 | else console.log("Success"); 185 | } 186 | ); 187 | } else { 188 | throw new Error("Project not found!"); 189 | } 190 | -------------------------------------------------------------------------------- /src/Client/RestAPI/RestAPIHandler.ts: -------------------------------------------------------------------------------- 1 | import fetch from "node-fetch"; 2 | import { EvolveClient, IAPIParams, CONSTANTS } from "../.."; 3 | import { promisify } from "util"; 4 | import DiscordRejection from "./DiscordRejection"; 5 | import { EVENTS } from "../.."; 6 | import { AsyncronousQueue } from "../../Utils/AsyncronousQueue"; 7 | 8 | /** 9 | * RestAPIHandler 10 | * A promise based queued rest api handler 11 | * @param client Your EvolveClient 12 | * @param endpoint The endpoint from which to fetch 13 | */ 14 | export class RestAPIHandler { 15 | private _cooldown: number = 0; 16 | private _queue!: AsyncronousQueue; 17 | private _endpoint!: string; 18 | private _client!: EvolveClient; 19 | 20 | constructor(client: EvolveClient, endpoint: string) { 21 | Object.defineProperty(this, "_client", { 22 | value: client, 23 | enumerable: false, 24 | writable: false, 25 | configurable: false, 26 | }); 27 | Object.defineProperty(this, "_endpoint", { 28 | value: endpoint, 29 | enumerable: false, 30 | writable: false, 31 | configurable: false, 32 | }); 33 | Object.defineProperty(this, "_queue", { 34 | value: new AsyncronousQueue(), 35 | enumerable: false, 36 | writable: false, 37 | configurable: false, 38 | }); 39 | } 40 | 41 | public get active(): boolean { 42 | return this._queue.resolved; 43 | } 44 | 45 | public async get(id?: string): Promise { 46 | let endpoint: string = this._endpoint; 47 | if (id) endpoint = endpoint.replace(":id", id); 48 | if (!id && endpoint.includes(":id")) 49 | throw this._client.transformer.error( 50 | `Id parameter is required as the ${this._endpoint} has a ':id' which needs to be replaced...` 51 | ); 52 | return this._fetch({ endpoint, method: "GET", json_params: undefined }); 53 | } 54 | 55 | public async put(json: object | string, id?: string): Promise { 56 | let endpoint: string = this._endpoint; 57 | if (id) endpoint = endpoint.replace(":id", id); 58 | if (!id && endpoint.includes(":id")) 59 | throw this._client.transformer.error( 60 | `Id parameter is required as the ${this._endpoint} has a ':id' which needs to be replaced...` 61 | ); 62 | return this._fetch({ 63 | endpoint, 64 | method: "PUT", 65 | json_params: typeof json == "object" ? JSON.stringify(json) : json, 66 | }); 67 | } 68 | 69 | public async delete(id?: string): Promise { 70 | let endpoint: string = this._endpoint; 71 | if (id) endpoint = endpoint.replace(":id", id); 72 | if (!id && endpoint.includes(":id")) 73 | throw this._client.transformer.error( 74 | `Id parameter is required as the ${this._endpoint} has a ':id' which needs to be replaced...` 75 | ); 76 | return this._fetch({ endpoint, method: "DELETE", json_params: undefined }); 77 | } 78 | 79 | public async post(json: object | string, id?: string): Promise { 80 | let endpoint: string = this._endpoint; 81 | if (id) endpoint = endpoint.replace(":id", id); 82 | if (!id && endpoint.includes(":id")) 83 | throw this._client.transformer.error( 84 | `Id parameter is required as the ${this._endpoint} has a ':id' which needs to be replaced...` 85 | ); 86 | return this._fetch({ 87 | endpoint, 88 | method: "POST", 89 | json_params: typeof json == "object" ? JSON.stringify(json) : json, 90 | }); 91 | } 92 | 93 | public async patch(json: object | string, id?: string): Promise { 94 | let endpoint: string = this._endpoint; 95 | if (id) endpoint = endpoint.replace(":id", id); 96 | if (!id && endpoint.includes(":id")) 97 | throw this._client.transformer.error( 98 | `Id parameter is required as the ${this._endpoint} has a ':id' which needs to be replaced...` 99 | ); 100 | return this._fetch({ 101 | endpoint, 102 | method: "PATCH", 103 | json_params: typeof json == "object" ? JSON.stringify(json) : json, 104 | }); 105 | } 106 | 107 | private async _fetch(options: NewIAPIParams): Promise { 108 | await this._queue.delay(); 109 | const whileExectued = RestAPIHandler.globalTimeout; 110 | await promisify(setTimeout)(whileExectued); 111 | RestAPIHandler.globalTimeout -= whileExectued; 112 | try { 113 | await promisify(setTimeout)(this._cooldown); 114 | this._cooldown = 1; 115 | const res = await fetch(`${CONSTANTS.Api}${options.endpoint}`, { 116 | method: options.method, 117 | headers: { 118 | "Content-Type": "application/json", 119 | Authorization: `Bot ${this._client.token}`, 120 | }, 121 | body: options.json_params, 122 | }); 123 | 124 | const json = await res.json(); 125 | 126 | if (res.headers) { 127 | const resetAfter = 128 | Number( 129 | res.headers.get("x-ratelimit-reset-after") ?? json.retry_after 130 | ) * 1000; 131 | if (this._cooldown !== 0) { 132 | this._cooldown += resetAfter; 133 | } else this._cooldown = resetAfter; 134 | } 135 | 136 | if (res.status === 429) { 137 | if (json.global) RestAPIHandler.globalTimeout += this._cooldown; 138 | await promisify(setTimeout)(this._cooldown); 139 | return this._fetch(options); 140 | } 141 | 142 | if (!res.ok) { 143 | const rejection = new DiscordRejection({ 144 | code: json.code, 145 | msg: this._client.transformer.error(json.message), 146 | http: res.status, 147 | path: options.endpoint, 148 | }); 149 | 150 | if (this._client.listenerCount(EVENTS.API_ERROR) < 1) { 151 | throw rejection; 152 | } else throw this._client.emit(EVENTS.API_ERROR, rejection); 153 | } 154 | return json; 155 | } catch (e) { 156 | if (this._client.listenerCount(EVENTS.API_ERROR) < 1) 157 | throw this._client.transformer.error(e); 158 | else throw this._client.emit(EVENTS.API_ERROR, e); 159 | } finally { 160 | this._cooldown = 1; 161 | this._queue.dequeue(); 162 | } 163 | } 164 | 165 | public dequeueAll() { 166 | try { 167 | for (let i = 0; i < this._queue.notResolved; i++) { 168 | try { 169 | this._queue.dequeue(); 170 | } catch (e) { 171 | throw new Error(e); 172 | } 173 | } 174 | } catch (e) { 175 | throw this._client.transformer.error(e); 176 | } 177 | } 178 | 179 | static globalTimeout = 1; 180 | } 181 | 182 | interface NewIAPIParams { 183 | endpoint: string; 184 | method: "GET" | "POST" | "DELETE" | "PUT" | "PATCH"; 185 | json_params: string | undefined; 186 | } 187 | -------------------------------------------------------------------------------- /src/Client/EvolveBuilder.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-constant-condition */ 2 | /* eslint-disable no-mixed-spaces-and-tabs */ 3 | 4 | import { Oauth2 } from "../Oauth2/Oauth2"; 5 | import { Structures } from "../Structures/Structures"; 6 | import { CacheOptions, GatewayIntents, Identify } from "../Utils/Constants"; 7 | import { EvolveClient } from "./EvolveClient"; 8 | import { ShardManager } from "./Websocket/ShardManager"; 9 | import { CacheProviders } from "../Interfaces/Interfaces"; 10 | 11 | export class EvolveBuilder { 12 | private token!: string; 13 | public shards = 1; 14 | public intents = 0; 15 | private cache: Set = new Set(); 16 | public activity: typeof Identify.d.activity; 17 | public secret!: string; 18 | public encoding: "etf" | "json" = "json"; 19 | public client!: EvolveClient; 20 | private structure!: Structures; 21 | private typeOfclient!: typeof EvolveClient; 22 | private _providers!: CacheProviders; 23 | 24 | public constructor(token?: string, useDefaultSettings: boolean = true) { 25 | if (token) { 26 | this.token = token; 27 | } 28 | 29 | if (useDefaultSettings) { 30 | this.enableCache( 31 | CacheOptions.GUILD, 32 | CacheOptions.CHANNELS, 33 | CacheOptions.USERS 34 | ); 35 | this.enableIntents( 36 | GatewayIntents.GUILD + 37 | GatewayIntents.GUILD_MESSAGES + 38 | GatewayIntents.DIRECT_MESSAGES 39 | ); 40 | } 41 | } 42 | 43 | /** 44 | * 45 | * @param token 46 | * @returns The EvolveBuilder Class 47 | */ 48 | public setToken(token: string): EvolveBuilder { 49 | this.token = token; 50 | return this; 51 | } 52 | 53 | /** 54 | * 55 | * @param encoding 56 | */ 57 | 58 | public setEncoding(encoding: "json" | "etf"): EvolveBuilder { 59 | this.encoding = encoding; 60 | return this; 61 | } 62 | 63 | /** 64 | * 65 | * @param totalShards 66 | * @note It must be greater than 0 67 | * @returns The EvolveBuilder Class 68 | */ 69 | public setShards(totalShards: number): EvolveBuilder { 70 | this.shards = totalShards; 71 | return this; 72 | } 73 | 74 | /** 75 | * 76 | * @param activity 77 | * @note The input should be the same as given in the discord api docs 78 | * @returns The EvolveBuilder Class 79 | */ 80 | public setActivity(activity: typeof Identify.d.activity): EvolveBuilder { 81 | this.activity = activity; 82 | return this; 83 | } 84 | 85 | /** 86 | * 87 | * @param cache 88 | * @enables The Cache Options for the library 89 | * @returns The EvolveBuilder Client 90 | */ 91 | public enableCache(...caches: CacheOptions[]): EvolveBuilder { 92 | for (const cache of caches) { 93 | this.cache.add(cache); 94 | } 95 | return this; 96 | } 97 | 98 | /** 99 | * 100 | * @param cache 101 | * @disables The Cache Options for the Library 102 | * @returns EvolveBuilder Class 103 | */ 104 | public disableCache(...caches: CacheOptions[]): EvolveBuilder { 105 | for (const cache of caches) { 106 | this.cache.add(cache); 107 | } 108 | return this; 109 | } 110 | 111 | /** 112 | * 113 | * @param intents 114 | * @enables The Required Intents for the Bot 115 | * @returns EvolveBuilder Class 116 | * @warning No intents are applied at default so you wont receive any events except some exceptions 117 | */ 118 | public enableIntents(...intents: GatewayIntents[]): EvolveBuilder { 119 | for (const intent of intents) { 120 | this.intents = this.intents + intent; 121 | } 122 | return this; 123 | } 124 | 125 | /** 126 | * 127 | * @param intents 128 | * @disables The Intents for your bot 129 | * @returns EvolveBuilder Class 130 | */ 131 | public disableIntents(...intents: GatewayIntents[]): EvolveBuilder { 132 | for (const intent of intents) { 133 | this.intents = this.intents - intent; 134 | } 135 | return this; 136 | } 137 | 138 | public setSecret(clientSecret: string): EvolveBuilder { 139 | this.secret = clientSecret; 140 | return this; 141 | } 142 | 143 | public setStructureClass(structure: Structures): EvolveBuilder { 144 | this.structure = structure; 145 | return this; 146 | } 147 | 148 | public setClientClass(client: typeof EvolveClient): EvolveBuilder { 149 | this.typeOfclient = client; 150 | return this; 151 | } 152 | 153 | public setCacheProviders(providers: CacheProviders): EvolveBuilder { 154 | this._providers = providers; 155 | return this; 156 | } 157 | 158 | /** 159 | * @param none 160 | * @returns {EvolveClient} A Initialized EvolveClient Instance 161 | */ 162 | public build(): EvolveClient { 163 | if (!this.typeOfclient) { 164 | this.client = new EvolveClient(this.token, { 165 | enableGuildCache: this.cache.has(CacheOptions.GUILD) 166 | ? true 167 | : this.cache.has(CacheOptions.ALL), 168 | enableChannelCache: this.cache.has(CacheOptions.CHANNELS) 169 | ? true 170 | : this.cache.has(CacheOptions.ALL), 171 | enableEmojiCache: this.cache.has(CacheOptions.EMOJI) 172 | ? true 173 | : this.cache.has(CacheOptions.ALL), 174 | enableUsersCache: this.cache.has(CacheOptions.USERS) 175 | ? true 176 | : this.cache.has(CacheOptions.ALL), 177 | enableMessageCache: this.cache.has(CacheOptions.MESSAGES) 178 | ? true 179 | : this.cache.has(CacheOptions.ALL), 180 | }); 181 | } else { 182 | this.client = new this.typeOfclient(this.token, { 183 | enableGuildCache: this.cache.has(CacheOptions.GUILD) 184 | ? true 185 | : this.cache.has(CacheOptions.ALL), 186 | enableChannelCache: this.cache.has(CacheOptions.CHANNELS) 187 | ? true 188 | : this.cache.has(CacheOptions.ALL), 189 | enableEmojiCache: this.cache.has(CacheOptions.EMOJI) 190 | ? true 191 | : this.cache.has(CacheOptions.ALL), 192 | enableUsersCache: this.cache.has(CacheOptions.USERS) 193 | ? true 194 | : this.cache.has(CacheOptions.ALL), 195 | enableMessageCache: this.cache.has(CacheOptions.MESSAGES) 196 | ? true 197 | : this.cache.has(CacheOptions.ALL), 198 | }); 199 | } 200 | 201 | if (this._providers) { 202 | if (this._providers.guilds) { 203 | this.client.guilds = this._providers.guilds; 204 | } 205 | if (this._providers.channels) { 206 | this.client.channels = this._providers.channels; 207 | } 208 | if (this._providers.emojis) { 209 | this.client.emojis = this._providers.emojis; 210 | } 211 | if (this._providers.users) { 212 | this.client.users = this._providers.users; 213 | } 214 | if (this._providers.messages) { 215 | this.client.messages = this._providers.messages; 216 | } 217 | if (this._providers.roles) { 218 | this.client.roles = this._providers.roles; 219 | } 220 | } 221 | 222 | if (!this.token) { 223 | throw this.client.transformer.error( 224 | "EvolveBuilder#build Error.. -> No token Provided for EvolveClient to be initialized" 225 | ); 226 | } 227 | if (this.shards <= 0) 228 | throw this.client.transformer.error("Total shards must be more than 0!"); 229 | 230 | if (this.intents == 0) { 231 | throw this.client.transformer.error( 232 | "No Intents are given, you will not get any events except some..." 233 | ); 234 | } 235 | 236 | if (this.secret) { 237 | this.client.secret = this.secret; 238 | this.client.oauth2 = new Oauth2(this.client); 239 | } 240 | 241 | if (this.structure) this.client.structures = this.structure; 242 | 243 | this.client.sharder = new ShardManager(this); 244 | this.client.sharder.spawnAll(); 245 | 246 | return this.client; 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /src/Utils/Constants.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ITextChannel, 3 | IDMChannel, 4 | IVoiceChannel, 5 | IGroupChannel, 6 | ICategoryChannel, 7 | INewsChannel, 8 | IStoreChannel, 9 | Payload, 10 | } from ".."; 11 | import { TextChannel } from "../Structures/Channel/TextChannel"; 12 | import { VoiceChannel } from "../Structures/Channel/VoiceChannel"; 13 | import { DMChannel } from "../Structures/Channel/DMChannel"; 14 | import { CategoryChannel } from "../Structures/Channel/CategoryChannel"; 15 | import { GroupChannel } from "../Structures/Channel/GroupChannel"; 16 | import { NewsChannel } from "../Structures/Channel/NewsChannel"; 17 | import { StoreChannel } from "../Structures/Channel/StoreChannel"; 18 | 19 | export enum CONSTANTS { 20 | Gateway = "wss://gateway.discord.gg/?v=8&encoding=", 21 | Api = "https://discord.com/api/v8", 22 | API_ERROR = "API_ERROR", 23 | EVENTS = "EVENTS", 24 | } 25 | 26 | export enum CHANNELTYPES { 27 | Text = 0, 28 | Direct = 1, 29 | Voice = 2, 30 | Group = 3, 31 | Category = 4, 32 | News = 5, 33 | Store = 6, 34 | } 35 | 36 | export enum ACTIVITY { 37 | Game = 0, 38 | Stream = 1, 39 | Listening = 2, 40 | Custom = 3, 41 | } 42 | 43 | export const NITRO = { 44 | 0: "None", 45 | 1: "Nitro Classic", 46 | 2: "Nitro", 47 | }; 48 | 49 | export enum WEBHOOKTYPE { 50 | Incoming = 1, 51 | Channel_Follower = 2, 52 | } 53 | 54 | export type Visibility = "idle" | "dnd" | "online" | "offline"; 55 | export type ChannelResolvable = 56 | | ITextChannel 57 | | IDMChannel 58 | | IVoiceChannel 59 | | IGroupChannel 60 | | ICategoryChannel 61 | | INewsChannel 62 | | IStoreChannel; 63 | 64 | export type ChannelTypes = 65 | | TextChannel 66 | | VoiceChannel 67 | | DMChannel 68 | | CategoryChannel 69 | | GroupChannel 70 | | NewsChannel 71 | | StoreChannel; 72 | 73 | export const ChannelResolver = [ 74 | TextChannel, 75 | DMChannel, 76 | VoiceChannel, 77 | GroupChannel, 78 | CategoryChannel, 79 | NewsChannel, 80 | StoreChannel, 81 | ]; 82 | 83 | export enum ActivityTypes { 84 | PLAYING = 0, 85 | STREAMING = 1, 86 | LISTENING = 2, 87 | CUSTOM = 4, 88 | } 89 | 90 | export enum CacheOptions { 91 | GUILD, 92 | CHANNELS, 93 | USERS, 94 | MESSAGES, 95 | EMOJI, 96 | ALL, 97 | } 98 | export type Events = "rawEvent" | "packetReady" | "clientReady" | "resumed" | "reconnect" | "invalidSession" | "newChannel" | "channelUpdate" | "removeChannel" 99 | | "channelPinsUpdate" | "addedGuild" | "guildUpdate" | "removeGuild" | "voiceStateUpdate" | "voiceServerUpdate" | "newMessage" 100 | 101 | export enum EVENTS { 102 | RAW = "rawEvent", 103 | PACKET_READY = "packetReady", 104 | HELLO = "hello", 105 | READY = "clientReady", 106 | RESUMED = "resumed", 107 | RECONNECT = "reconnect", 108 | INVALID_SESSION = "invalidSession", 109 | CHANNEL_CREATE = "newChannel", 110 | CHANNEL_UPDATE = "channelUpdate", 111 | CHANNEL_DELETE = "removeChannel", 112 | CHANNEL_PINS_UPDATE = "channelPinsUpdate", 113 | GUILD_CREATE = "addedGuild", 114 | GUILD_UPDATE = "guildUpdate", 115 | GUILD_DELETE = "removeGuild", 116 | GUILD_BAN_ADD = "userBanned", 117 | GUILD_BAN_REMOVE = "userUnbanned", 118 | GUILD_EMOJIS_UPDATE = "guildEmojisUpdate", 119 | GUILD_INTEGRATIONS_UPDATE = "guildIntegrationsUpdate", 120 | GUILD_MEMBER_ADD = "memberJoined", 121 | GUILD_MEMBER_REMOVE = "memberLeft", 122 | GUILD_MEMBER_UPDATE = "memberUpdate", 123 | GUILD_MEMBERS_CHUNK = "memberChunk", 124 | GUILD_ROLE_CREATE = "newRole", 125 | GUILD_ROLE_UPDATE = "roleUpdated", 126 | GUILD_ROLE_DELETE = "removeRole", 127 | INVITE_CREATE = "addInvite", 128 | INVITE_DELETE = "removeInvite", 129 | MESSAGE_CREATE = "newMessage", 130 | MESSAGE_UPDATE = "updateMessage", 131 | MESSAGE_DELETE = "removeMessage", 132 | MESSAGE_DELETE_BULK = "bulkMessageRemove", 133 | MESSAGE_REACTION_ADD = "reactionAdd", 134 | MESSAGE_REACTION_REMOVE = "reactionRemove", 135 | MESSAGE_REACTION_REMOVE_All = "reactionRemoveAll", 136 | MESSAGE_REACTION_REMOVE_EMOJI = "removeReactionEmoji", 137 | PRESENCE_UPDATE = "userPresenceUpdate", 138 | TYPING_START = "typing", 139 | USER_UPDATE = "userUpdate", 140 | VOICE_STATE_UPDATE = "voiceStateUpdate", 141 | VOICE_SERVER_UPDATE = "voiceServerUpdate", 142 | WEBHOOKS_UPDATE = "webhookUpdate", 143 | SHARD_SPAWN = "shardSpawn", 144 | SHARD_DESTROY = "shardDestroy", 145 | API_ERROR = "restError", 146 | } 147 | 148 | export enum GatewayIntents { 149 | GUILD = 1 << 0, 150 | GUILD_MEMBERS = 1 << 1, 151 | GUILD_BANS = 1 << 2, 152 | GUILD_EMOJIS = 1 << 3, 153 | GUILD_INTEGRATIONS = 1 << 4, 154 | GUILD_WEBHOOKS = 1 << 5, 155 | GUILD_INVITES = 1 << 6, 156 | GUILD_VOICE_STATES = 1 << 7, 157 | GUILD_PRESENCES = 1 << 8, 158 | GUILD_MESSAGES = 1 << 9, 159 | GUILD_MESSAGES_REACTIONS = 1 << 10, 160 | GUILD_MESSAGE_TYPING = 1 << 11, 161 | DIRECT_MESSAGES = 1 << 12, 162 | DIRECT_MESSAGES_REACTIONS = 1 << 13, 163 | DIRECT_MESSAGES_TYPING = 1 << 14, 164 | ALL = GUILD + 165 | GUILD_MEMBERS + 166 | GUILD_BANS + 167 | GUILD_EMOJIS + 168 | GUILD_INTEGRATIONS + 169 | GUILD_WEBHOOKS + 170 | GUILD_INVITES + 171 | GUILD_VOICE_STATES + 172 | GUILD_PRESENCES + 173 | GUILD_MESSAGES + 174 | GUILD_MESSAGES_REACTIONS + 175 | GUILD_MESSAGE_TYPING + 176 | DIRECT_MESSAGES + 177 | DIRECT_MESSAGES_REACTIONS + 178 | DIRECT_MESSAGES_TYPING, 179 | } 180 | 181 | export enum OPCODE { 182 | Dispatch = 0, // Receive an dispatched event. 183 | Heartbeat = 1, // Send or receive periodically fired heartbeat which keeps connection alive. 184 | Identify = 2, // Starts a new session during the initial handshake. 185 | Presence_Update = 3, // Update the client's presence status. 186 | Voice_State_Update = 4, // Used to join/leave or move between voice channels. 187 | Resume = 6, // Resume a previous session that was disconnected. 188 | Reconnect = 7, // When received attempt to reconnect and resume should be made immediately. 189 | Request = 8, // Send or request information about offline guild members in a large guild. 190 | Invalid = 9, // Received when session has been invalidated. You should reconnect and resume accordingly. 191 | Hello = 10, // Sent immediately after connecting, contains the heartbeat_interval to use. 192 | Heartbeat_ACK = 11, // Sent in response to receiving a heartbeat to acknowledge that it has been received. 193 | } 194 | 195 | export const Heartbeat: Payload = { 196 | op: OPCODE.Heartbeat, 197 | d: null, 198 | }; 199 | 200 | export const VoiceStateUpdate: Payload = { 201 | op: OPCODE.Voice_State_Update, 202 | d: { 203 | guild_id: "", 204 | channel_id: "", 205 | self_mute: false, 206 | self_deaf: false, 207 | }, 208 | }; 209 | 210 | export const VoiceIdentify: Payload = { 211 | op: 0, 212 | d: { 213 | server_id: "", 214 | user_id: "", 215 | session_id: "", 216 | token: "", 217 | }, 218 | }; 219 | 220 | export const Identify: Payload = { 221 | op: OPCODE.Identify, 222 | d: { 223 | token: "", 224 | intents: 0, 225 | shard: [0, 1], 226 | properties: { 227 | $os: process.platform, 228 | $browser: "discord", 229 | $device: "evolvejs", 230 | }, 231 | presence: { 232 | since: Date.now(), 233 | game: { 234 | name: "EvolveJS", 235 | type: ActivityTypes.PLAYING, 236 | }, 237 | status: "", 238 | afk: false, 239 | }, 240 | }, 241 | }; 242 | 243 | export interface TokenAccessOptions { 244 | code: string; 245 | redirectUri: string; 246 | scopes: string; 247 | } 248 | 249 | export enum PERMISSIONS { 250 | ADMINISTRATOR = "", 251 | } 252 | --------------------------------------------------------------------------------