feat: void -- start work
This commit is contained in:
		
							parent
							
								
									6f60bd5040
								
							
						
					
					
						commit
						a6697a75a7
					
				
					 13 changed files with 485 additions and 365 deletions
				
			
		|  | @ -1,7 +1,9 @@ | |||
| export const DISCORD_API_URL: string = 'https://discord.com/api' | ||||
| 
 | ||||
| export const DISCORD_GATEWAY_URL: string = 'wss://gateway.discord.gg' | ||||
| 
 | ||||
| export const DISCORD_CDN_URL: string = 'https://cdn.discordapp.com' | ||||
| 
 | ||||
| export const DISCORD_API_VERSION: number = 8 | ||||
| export const DISCORD_API_URL: string = 'https://discord.com/api' | ||||
| 
 | ||||
| export const DISCORD_GATEWAY_URL: string = 'wss://gateway.discord.gg' | ||||
| 
 | ||||
| export const DISCORD_CDN_URL: string = 'https://cdn.discordapp.com' | ||||
| 
 | ||||
| export const DISCORD_API_VERSION: number = 8 | ||||
| 
 | ||||
| export const DISCORD_VOICE_VERSION: number = 4 | ||||
|  | @ -36,6 +36,9 @@ import { Member } from "../../structures/member.ts" | |||
| import { Role } from "../../structures/role.ts" | ||||
| import { Message } from "../../structures/message.ts" | ||||
| import { Collection } from "../../utils/collection.ts" | ||||
| import { voiceServerUpdate } from "./voiceServerUpdate.ts" | ||||
| import { voiceStateUpdate } from "./voiceStateUpdate.ts" | ||||
| import { VoiceState } from "../../structures/voiceState.ts" | ||||
| 
 | ||||
| export const gatewayHandlers: { | ||||
|   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||
|  | @ -74,7 +77,8 @@ export const gatewayHandlers: { | |||
|   PRESENCE_UPDATE: undefined, | ||||
|   TYPING_START: typingStart, | ||||
|   USER_UPDATE: userUpdate, | ||||
|   VOICE_SERVER_UPDATE: undefined, | ||||
|   VOICE_STATE_UPDATE: voiceStateUpdate, | ||||
|   VOICE_SERVER_UPDATE: voiceServerUpdate, | ||||
|   WEBHOOKS_UPDATE: webhooksUpdate | ||||
| } | ||||
| 
 | ||||
|  | @ -82,6 +86,12 @@ export interface EventTypes { | |||
|   [name: string]: (...args: any[]) => void | ||||
| } | ||||
| 
 | ||||
| export interface VoiceServerUpdateData { | ||||
|   token: string | ||||
|   endpoint: string | ||||
|   guild: Guild | ||||
| } | ||||
| 
 | ||||
| export interface ClientEvents extends EventTypes { | ||||
|   'ready': () => void | ||||
|   'reconnect': () => void | ||||
|  | @ -111,5 +121,9 @@ export interface ClientEvents extends EventTypes { | |||
|   'messageUpdate': (before: Message, after: Message) => void | ||||
|   'typingStart': (user: User, channel: TextChannel, at: Date, guildData?: TypingStartGuildData) => void | ||||
|   'userUpdate': (before: User, after: User) => void | ||||
|   'voiceServerUpdate': (data: VoiceServerUpdateData) => void | ||||
|   'voiceStateAdd': (state: VoiceState) => void | ||||
|   'voiceStateRemove': (state: VoiceState) => void | ||||
|   'voiceStateUpdate': (state: VoiceState, after: VoiceState) => void | ||||
|   'webhooksUpdate': (guild: Guild, channel: GuildTextChannel) => void | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/gateway/handlers/voiceServerUpdate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/gateway/handlers/voiceServerUpdate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| import { Guild } from "../../structures/guild.ts" | ||||
| import { VoiceServerUpdatePayload } from "../../types/gateway.ts" | ||||
| import { Gateway, GatewayEventHandler } from '../index.ts' | ||||
| 
 | ||||
| export const voiceServerUpdate: GatewayEventHandler = async ( | ||||
|   gateway: Gateway, | ||||
|   d: VoiceServerUpdatePayload | ||||
| ) => { | ||||
|   gateway.client.emit('voiceServerUpdate', { | ||||
|     token: d.token, | ||||
|     endpoint: d.endpoint, | ||||
|     guild: (await gateway.client.guilds.get(d.guild_id) as unknown) as Guild | ||||
|   }) | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/gateway/handlers/voiceStateUpdate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/gateway/handlers/voiceStateUpdate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| import { Guild } from "../../structures/guild.ts" | ||||
| import { VoiceState } from "../../structures/voiceState.ts" | ||||
| import { VoiceStatePayload } from "../../types/voice.ts" | ||||
| import { Gateway, GatewayEventHandler } from '../index.ts' | ||||
| 
 | ||||
| export const voiceStateUpdate: GatewayEventHandler = async ( | ||||
|   gateway: Gateway, | ||||
|   d: VoiceStatePayload | ||||
| ) => { | ||||
|   // TODO(DjDeveloperr): Support self-bot here; they can be in DMs (Call)
 | ||||
|   if (d.guild_id === undefined) return | ||||
|   const guild = (await gateway.client.guilds.get(d.guild_id) as unknown) as Guild | ||||
| 
 | ||||
|   const voiceState = await guild.voiceStates.get(d.user_id) | ||||
| 
 | ||||
|   if (d.channel_id === null) { | ||||
|     // No longer in the channel, so delete
 | ||||
|     await guild.voiceStates.delete(d.user_id) | ||||
|     gateway.client.emit('voiceStateRemove', (voiceState as unknown) as VoiceState) | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   await guild.voiceStates.set(d.user_id, d) | ||||
|   const newVoiceState = await guild.voiceStates.get(d.user_id) | ||||
|   if (voiceState === undefined) { | ||||
|     gateway.client.emit('voiceStateAdd', (newVoiceState as unknown) as VoiceState) | ||||
|   } else { | ||||
|     gateway.client.emit('voiceStateUpdate', voiceState, (newVoiceState as unknown) as VoiceState) | ||||
|   } | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/managers/guildVoiceStates.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/managers/guildVoiceStates.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| import { Client } from '../models/client.ts' | ||||
| import { Guild } from "../structures/guild.ts" | ||||
| import { VoiceChannel } from "../structures/guildVoiceChannel.ts" | ||||
| import { User } from "../structures/user.ts" | ||||
| import { VoiceState } from "../structures/voiceState.ts" | ||||
| import { VoiceStatePayload } from "../types/voice.ts" | ||||
| import { BaseManager } from './base.ts' | ||||
| 
 | ||||
| export class GuildVoiceStatesManager extends BaseManager<VoiceStatePayload, VoiceState> { | ||||
|   guild: Guild | ||||
| 
 | ||||
|   async get (key: string): Promise<VoiceState | undefined> { | ||||
|     const raw = await this._get(key) | ||||
|     if (raw === undefined) return | ||||
| 
 | ||||
|     const guild = raw.guild_id === undefined ? undefined : await this.client.guilds.get(raw.guild_id) | ||||
| 
 | ||||
|     return new VoiceState(this.client, raw, { | ||||
|       user: (await this.client.users.get(raw.user_id) as unknown) as User, | ||||
|       channel: raw.channel_id == null ? null : (await this.client.channels.get<VoiceChannel>(raw.channel_id) as unknown) as VoiceChannel, | ||||
|       guild, | ||||
|       member: guild === undefined ? undefined : await guild.members.get(raw.user_id)  | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   constructor (client: Client, guild: Guild) { | ||||
|     super(client, `vs:${guild.id}`, VoiceState) | ||||
|     this.guild = guild | ||||
|   } | ||||
| } | ||||
|  | @ -1,190 +1,190 @@ | |||
| import { Guild } from '../structures/guild.ts' | ||||
| import { Message } from '../structures/message.ts' | ||||
| import { TextChannel } from '../structures/textChannel.ts' | ||||
| import { User } from '../structures/user.ts' | ||||
| import { Collection } from '../utils/collection.ts' | ||||
| import { CommandClient } from './commandClient.ts' | ||||
| import { Extension } from "./extensions.ts" | ||||
| 
 | ||||
| export interface CommandContext { | ||||
|   /** The Client object */ | ||||
|   client: CommandClient | ||||
|   /** Message which was parsed for Command */ | ||||
|   message: Message | ||||
|   /** The Author of the Message */ | ||||
|   author: User | ||||
|   /** The Channel in which Command was used */ | ||||
|   channel: TextChannel | ||||
|   /** Prefix which was used */ | ||||
|   prefix: string | ||||
|   /** Oject of Command which was used */ | ||||
|   command: Command | ||||
|   /** Name of Command which was used */ | ||||
|   name: string | ||||
|   /** Array of Arguments used with Command */ | ||||
|   args: string[] | ||||
|   /** Complete Raw String of Arguments */ | ||||
|   argString: string | ||||
|   /** Guild which the command has called */ | ||||
|   guild?: Guild | ||||
| } | ||||
| 
 | ||||
| export class Command { | ||||
|   /** Name of the Command */ | ||||
|   name: string = '' | ||||
|   /** Description of the Command */ | ||||
|   description?: string | ||||
|   /** Array of Aliases of Command, or only string */ | ||||
|   aliases?: string | string[] | ||||
|   /** Extension (Parent) of the Command */ | ||||
|   extension?: Extension | ||||
|   /** Usage of Command, only Argument Names */ | ||||
|   usage?: string | string[] | ||||
|   /** Usage Example of Command, only Arguments (without Prefix and Name) */ | ||||
|   examples?: string | string[] | ||||
|   /** Does the Command take Arguments? Maybe number of required arguments? */ | ||||
|   args?: number | boolean | ||||
|   /** Permission(s) required for using Command */ | ||||
|   permissions?: string | string[] | ||||
|   /** Permission(s) bot will need in order to execute Command */ | ||||
|   botPermissions?: string | string[] | ||||
|   /** Role(s) user will require in order to use Command. List or one of ID or name */ | ||||
|   roles?: string | string[] | ||||
|   /** Whitelisted Guilds. Only these Guild(s) can execute Command. (List or one of IDs) */ | ||||
|   whitelistedGuilds?: string | string[] | ||||
|   /** Whitelisted Channels. Command can be executed only in these channels. (List or one of IDs) */ | ||||
|   whitelistedChannels?: string | string[] | ||||
|   /** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */ | ||||
|   whitelistedUsers?: string | string[] | ||||
|   /** Whether the Command can only be used in Guild (if allowed in DMs) */ | ||||
|   guildOnly?: boolean | ||||
|   /** Whether the Command can only be used in Bot's DMs (if allowed) */ | ||||
|   dmOnly?: boolean | ||||
|   /** Whether the Command can only be used by Bot Owners */ | ||||
|   ownerOnly?: boolean | ||||
| 
 | ||||
|   /** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */ | ||||
|   beforeExecute(ctx: CommandContext): boolean | Promise<boolean> { return true } | ||||
|   /** Actual command code, which is executed when all checks have passed. */ | ||||
|   execute(ctx: CommandContext): any { } | ||||
|   /** Method executed after executing command, passes on CommandContext and the value returned by execute too. (optional) */ | ||||
|   afterExecute(ctx: CommandContext, executeResult: any): any { } | ||||
| 
 | ||||
|   toString(): string { | ||||
|     return `Command: ${this.name}${this.extension !== undefined ? ` [${this.extension.name}]` : ''}` | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class CommandsManager { | ||||
|   client: CommandClient | ||||
|   list: Collection<string, Command> = new Collection() | ||||
|   disabled: Set<string> = new Set() | ||||
| 
 | ||||
|   constructor(client: CommandClient) { | ||||
|     this.client = client | ||||
|   } | ||||
| 
 | ||||
|   /** Number of loaded Commands */ | ||||
|   get count(): number { return this.list.size } | ||||
| 
 | ||||
|   /** Find a Command by name/alias */ | ||||
|   find(search: string): Command | undefined { | ||||
|     if (this.client.caseSensitive === false) search = search.toLowerCase() | ||||
|     return this.list.find((cmd: Command): boolean => { | ||||
|       const name = | ||||
|         this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase() | ||||
|       if (name === search) return true | ||||
|       else if (cmd.aliases !== undefined) { | ||||
|         let aliases: string[] | ||||
|         if (typeof cmd.aliases === 'string') aliases = [cmd.aliases] | ||||
|         else aliases = cmd.aliases | ||||
|         if (this.client.caseSensitive === false) | ||||
|           aliases = aliases.map(e => e.toLowerCase()) | ||||
|         return aliases.includes(search) | ||||
|       } else return false | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   /** Fetch a Command including disable checks */ | ||||
|   fetch(name: string, bypassDisable?: boolean): Command | undefined { | ||||
|     const cmd = this.find(name) | ||||
|     if (cmd === undefined) return | ||||
|     if (this.isDisabled(cmd) && bypassDisable !== true) return | ||||
|     return cmd | ||||
|   } | ||||
| 
 | ||||
|   /** Check whether a Command exists or not */ | ||||
|   exists(search: Command | string): boolean { | ||||
|     let exists = false | ||||
|     if (typeof search === 'string') return this.find(search) !== undefined | ||||
|     else { | ||||
|       exists = this.find(search.name) !== undefined | ||||
|       if (search.aliases !== undefined) { | ||||
|         const aliases: string[] = | ||||
|           typeof search.aliases === 'string' ? [search.aliases] : search.aliases | ||||
|         exists = | ||||
|           aliases.map(alias => this.find(alias) !== undefined).find(e => e) ?? | ||||
|           false | ||||
|       } | ||||
|       return exists | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** Add a Command */ | ||||
|   add(cmd: Command | typeof Command): boolean { | ||||
|     // eslint-disable-next-line new-cap
 | ||||
|     if (!(cmd instanceof Command)) cmd = new cmd() | ||||
|     if (this.exists(cmd)) throw new Error(`Failed to add Command '${cmd.toString()}' with name/alias already exists.`) | ||||
|     this.list.set(cmd.name, cmd) | ||||
|     return true | ||||
|   } | ||||
| 
 | ||||
|   /** Delete a Command */ | ||||
|   delete(cmd: string | Command): boolean { | ||||
|     const find = typeof cmd === 'string' ? this.find(cmd) : cmd | ||||
|     if (find === undefined) return false | ||||
|     else return this.list.delete(find.name) | ||||
|   } | ||||
| 
 | ||||
|   /** Check whether a Command is disabled or not */ | ||||
|   isDisabled(name: string | Command): boolean { | ||||
|     const cmd = typeof name === "string" ? this.find(name) : name | ||||
|     if (cmd === undefined) return false | ||||
|     const exists = this.exists(name) | ||||
|     if (!exists) return false | ||||
|     return this.disabled.has(cmd.name) | ||||
|   } | ||||
| 
 | ||||
|   /** Disable a Command */ | ||||
|   disable(name: string | Command): boolean { | ||||
|     const cmd = typeof name === "string" ? this.find(name) : name | ||||
|     if (cmd === undefined) return false | ||||
|     if (this.isDisabled(cmd)) return false | ||||
|     this.disabled.add(cmd.name) | ||||
|     return true | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export interface ParsedCommand { | ||||
|   name: string | ||||
|   args: string[] | ||||
|   argString: string | ||||
| } | ||||
| 
 | ||||
| export const parseCommand = ( | ||||
|   client: CommandClient, | ||||
|   msg: Message, | ||||
|   prefix: string | ||||
| ): ParsedCommand => { | ||||
|   let content = msg.content.slice(prefix.length) | ||||
|   if (client.spacesAfterPrefix === true) content = content.trim() | ||||
|   const args = content.split(client.betterArgs === true ? /[\S\s]*/ : / +/) | ||||
|   const name = args.shift() as string | ||||
|   const argString = content.slice(name.length).trim() | ||||
| 
 | ||||
|   return { | ||||
|     name, | ||||
|     args, | ||||
|     argString | ||||
|   } | ||||
| } | ||||
| import { Guild } from '../structures/guild.ts' | ||||
| import { Message } from '../structures/message.ts' | ||||
| import { TextChannel } from '../structures/textChannel.ts' | ||||
| import { User } from '../structures/user.ts' | ||||
| import { Collection } from '../utils/collection.ts' | ||||
| import { CommandClient } from './commandClient.ts' | ||||
| import { Extension } from "./extensions.ts" | ||||
| 
 | ||||
| export interface CommandContext { | ||||
|   /** The Client object */ | ||||
|   client: CommandClient | ||||
|   /** Message which was parsed for Command */ | ||||
|   message: Message | ||||
|   /** The Author of the Message */ | ||||
|   author: User | ||||
|   /** The Channel in which Command was used */ | ||||
|   channel: TextChannel | ||||
|   /** Prefix which was used */ | ||||
|   prefix: string | ||||
|   /** Oject of Command which was used */ | ||||
|   command: Command | ||||
|   /** Name of Command which was used */ | ||||
|   name: string | ||||
|   /** Array of Arguments used with Command */ | ||||
|   args: string[] | ||||
|   /** Complete Raw String of Arguments */ | ||||
|   argString: string | ||||
|   /** Guild which the command has called */ | ||||
|   guild?: Guild | ||||
| } | ||||
| 
 | ||||
| export class Command { | ||||
|   /** Name of the Command */ | ||||
|   name: string = '' | ||||
|   /** Description of the Command */ | ||||
|   description?: string | ||||
|   /** Array of Aliases of Command, or only string */ | ||||
|   aliases?: string | string[] | ||||
|   /** Extension (Parent) of the Command */ | ||||
|   extension?: Extension | ||||
|   /** Usage of Command, only Argument Names */ | ||||
|   usage?: string | string[] | ||||
|   /** Usage Example of Command, only Arguments (without Prefix and Name) */ | ||||
|   examples?: string | string[] | ||||
|   /** Does the Command take Arguments? Maybe number of required arguments? */ | ||||
|   args?: number | boolean | ||||
|   /** Permission(s) required for using Command */ | ||||
|   permissions?: string | string[] | ||||
|   /** Permission(s) bot will need in order to execute Command */ | ||||
|   botPermissions?: string | string[] | ||||
|   /** Role(s) user will require in order to use Command. List or one of ID or name */ | ||||
|   roles?: string | string[] | ||||
|   /** Whitelisted Guilds. Only these Guild(s) can execute Command. (List or one of IDs) */ | ||||
|   whitelistedGuilds?: string | string[] | ||||
|   /** Whitelisted Channels. Command can be executed only in these channels. (List or one of IDs) */ | ||||
|   whitelistedChannels?: string | string[] | ||||
|   /** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */ | ||||
|   whitelistedUsers?: string | string[] | ||||
|   /** Whether the Command can only be used in Guild (if allowed in DMs) */ | ||||
|   guildOnly?: boolean | ||||
|   /** Whether the Command can only be used in Bot's DMs (if allowed) */ | ||||
|   dmOnly?: boolean | ||||
|   /** Whether the Command can only be used by Bot Owners */ | ||||
|   ownerOnly?: boolean | ||||
| 
 | ||||
|   /** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */ | ||||
|   beforeExecute(ctx: CommandContext): boolean | Promise<boolean> { return true } | ||||
|   /** Actual command code, which is executed when all checks have passed. */ | ||||
|   execute(ctx: CommandContext): any { } | ||||
|   /** Method executed after executing command, passes on CommandContext and the value returned by execute too. (optional) */ | ||||
|   afterExecute(ctx: CommandContext, executeResult: any): any { } | ||||
| 
 | ||||
|   toString(): string { | ||||
|     return `Command: ${this.name}${this.extension !== undefined ? ` [${this.extension.name}]` : ''}` | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class CommandsManager { | ||||
|   client: CommandClient | ||||
|   list: Collection<string, Command> = new Collection() | ||||
|   disabled: Set<string> = new Set() | ||||
| 
 | ||||
|   constructor(client: CommandClient) { | ||||
|     this.client = client | ||||
|   } | ||||
| 
 | ||||
|   /** Number of loaded Commands */ | ||||
|   get count(): number { return this.list.size } | ||||
| 
 | ||||
|   /** Find a Command by name/alias */ | ||||
|   find(search: string): Command | undefined { | ||||
|     if (this.client.caseSensitive === false) search = search.toLowerCase() | ||||
|     return this.list.find((cmd: Command): boolean => { | ||||
|       const name = | ||||
|         this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase() | ||||
|       if (name === search) return true | ||||
|       else if (cmd.aliases !== undefined) { | ||||
|         let aliases: string[] | ||||
|         if (typeof cmd.aliases === 'string') aliases = [cmd.aliases] | ||||
|         else aliases = cmd.aliases | ||||
|         if (this.client.caseSensitive === false) | ||||
|           aliases = aliases.map(e => e.toLowerCase()) | ||||
|         return aliases.includes(search) | ||||
|       } else return false | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   /** Fetch a Command including disable checks */ | ||||
|   fetch(name: string, bypassDisable?: boolean): Command | undefined { | ||||
|     const cmd = this.find(name) | ||||
|     if (cmd === undefined) return | ||||
|     if (this.isDisabled(cmd) && bypassDisable !== true) return | ||||
|     return cmd | ||||
|   } | ||||
| 
 | ||||
|   /** Check whether a Command exists or not */ | ||||
|   exists(search: Command | string): boolean { | ||||
|     let exists = false | ||||
|     if (typeof search === 'string') return this.find(search) !== undefined | ||||
|     else { | ||||
|       exists = this.find(search.name) !== undefined | ||||
|       if (search.aliases !== undefined) { | ||||
|         const aliases: string[] = | ||||
|           typeof search.aliases === 'string' ? [search.aliases] : search.aliases | ||||
|         exists = | ||||
|           aliases.map(alias => this.find(alias) !== undefined).find(e => e) ?? | ||||
|           false | ||||
|       } | ||||
|       return exists | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** Add a Command */ | ||||
|   add(cmd: Command | typeof Command): boolean { | ||||
|     // eslint-disable-next-line new-cap
 | ||||
|     if (!(cmd instanceof Command)) cmd = new cmd() | ||||
|     if (this.exists(cmd)) throw new Error(`Failed to add Command '${cmd.toString()}' with name/alias already exists.`) | ||||
|     this.list.set(cmd.name, cmd) | ||||
|     return true | ||||
|   } | ||||
| 
 | ||||
|   /** Delete a Command */ | ||||
|   delete(cmd: string | Command): boolean { | ||||
|     const find = typeof cmd === 'string' ? this.find(cmd) : cmd | ||||
|     if (find === undefined) return false | ||||
|     else return this.list.delete(find.name) | ||||
|   } | ||||
| 
 | ||||
|   /** Check whether a Command is disabled or not */ | ||||
|   isDisabled(name: string | Command): boolean { | ||||
|     const cmd = typeof name === "string" ? this.find(name) : name | ||||
|     if (cmd === undefined) return false | ||||
|     const exists = this.exists(name) | ||||
|     if (!exists) return false | ||||
|     return this.disabled.has(cmd.name) | ||||
|   } | ||||
| 
 | ||||
|   /** Disable a Command */ | ||||
|   disable(name: string | Command): boolean { | ||||
|     const cmd = typeof name === "string" ? this.find(name) : name | ||||
|     if (cmd === undefined) return false | ||||
|     if (this.isDisabled(cmd)) return false | ||||
|     this.disabled.add(cmd.name) | ||||
|     return true | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export interface ParsedCommand { | ||||
|   name: string | ||||
|   args: string[] | ||||
|   argString: string | ||||
| } | ||||
| 
 | ||||
| export const parseCommand = ( | ||||
|   client: CommandClient, | ||||
|   msg: Message, | ||||
|   prefix: string | ||||
| ): ParsedCommand => { | ||||
|   let content = msg.content.slice(prefix.length) | ||||
|   if (client.spacesAfterPrefix === true) content = content.trim() | ||||
|   const args = content.split(client.betterArgs === true ? /[\S\s]*/ : / +/) | ||||
|   const name = args.shift() as string | ||||
|   const argString = content.slice(name.length).trim() | ||||
| 
 | ||||
|   return { | ||||
|     name, | ||||
|     args, | ||||
|     argString | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,10 +1,26 @@ | |||
| import { Guild } from "../structures/guild.ts" | ||||
| import { VoiceChannel } from "../structures/guildVoiceChannel.ts" | ||||
| import { Client } from './client.ts' | ||||
| 
 | ||||
| export interface VoiceOptions { | ||||
|   guild: Guild, | ||||
|   channel: VoiceChannel | ||||
| } | ||||
| 
 | ||||
| export class VoiceClient { | ||||
|   client: Client | ||||
|   ws?: WebSocket | ||||
|   guild: Guild | ||||
|   channel: VoiceChannel | ||||
| 
 | ||||
|   constructor(client: Client) { | ||||
|   constructor(client: Client, options: VoiceOptions) { | ||||
|     this.client = client | ||||
|     this.guild = options.guild | ||||
|     this.channel = options.channel | ||||
|   } | ||||
| 
 | ||||
|   async connect(): Promise<VoiceClient> { | ||||
|      | ||||
|     return this | ||||
|   } | ||||
| } | ||||
|  | @ -2,7 +2,6 @@ import { Client } from '../models/client.ts' | |||
| import { GuildFeatures, GuildIntegrationPayload, GuildPayload, IntegrationAccountPayload, IntegrationExpireBehavior } from '../types/guild.ts' | ||||
| import { PresenceUpdatePayload } from '../types/gateway.ts' | ||||
| import { Base } from './base.ts' | ||||
| import { VoiceState } from './voiceState.ts' | ||||
| import { RolesManager } from '../managers/roles.ts' | ||||
| import { GuildChannelsManager } from '../managers/guildChannels.ts' | ||||
| import { MembersManager } from '../managers/members.ts' | ||||
|  | @ -12,6 +11,7 @@ import { Member } from "./member.ts" | |||
| import { User } from "./user.ts" | ||||
| import { Application } from "./application.ts" | ||||
| import { GUILD_INTEGRATIONS } from "../types/endpoint.ts" | ||||
| import { GuildVoiceStatesManager } from "../managers/guildVoiceStates.ts" | ||||
| 
 | ||||
| export class Guild extends Base { | ||||
|   id: string | ||||
|  | @ -43,7 +43,7 @@ export class Guild extends Base { | |||
|   large?: boolean | ||||
|   unavailable: boolean | ||||
|   memberCount?: number | ||||
|   voiceStates?: VoiceState[] | ||||
|   voiceStates: GuildVoiceStatesManager | ||||
|   members: MembersManager | ||||
|   channels: GuildChannelsManager | ||||
|   presences?: PresenceUpdatePayload[] | ||||
|  | @ -65,6 +65,7 @@ export class Guild extends Base { | |||
|     this.id = data.id | ||||
|     this.unavailable = data.unavailable | ||||
|     this.members = new MembersManager(this.client, this) | ||||
|     this.voiceStates = new GuildVoiceStatesManager(client, this) | ||||
|     this.channels = new GuildChannelsManager( | ||||
|       this.client,  | ||||
|       this.client.channels,  | ||||
|  |  | |||
|  | @ -1,49 +1,53 @@ | |||
| import { Client } from '../models/client.ts' | ||||
| import { MemberPayload } from '../types/guild.ts' | ||||
| import { VoiceStatePayload } from '../types/voice.ts' | ||||
| import { Base } from './base.ts' | ||||
| 
 | ||||
| export class VoiceState extends Base { | ||||
|   guildID?: string | ||||
|   channelID?: string | ||||
|   userID: string | ||||
|   member?: MemberPayload | ||||
|   sessionID: string | ||||
|   deaf: boolean | ||||
|   mute: boolean | ||||
|   selfDeaf: boolean | ||||
|   selfMute: boolean | ||||
|   selfStream?: boolean | ||||
|   selfVideo: boolean | ||||
|   suppress: boolean | ||||
| 
 | ||||
|   constructor (client: Client, data: VoiceStatePayload) { | ||||
|     super(client, data) | ||||
|     this.channelID = data.channel_id | ||||
|     this.sessionID = data.session_id | ||||
|     this.userID = data.user_id | ||||
|     this.deaf = data.deaf | ||||
|     this.mute = data.mute | ||||
|     this.selfDeaf = data.self_deaf | ||||
|     this.selfMute = data.self_mute | ||||
|     this.selfStream = data.self_stream | ||||
|     this.selfVideo = data.self_video | ||||
|     this.suppress = data.suppress | ||||
|     // TODO: Cache in Gateway Event Code
 | ||||
|     // cache.set('voiceState', `${this.guildID}:${this.userID}`, this)
 | ||||
|   } | ||||
| 
 | ||||
|   protected readFromData (data: VoiceStatePayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.channelID = data.channel_id ?? this.channelID | ||||
|     this.sessionID = data.session_id ?? this.sessionID | ||||
|     this.userID = data.user_id ?? this.userID | ||||
|     this.deaf = data.deaf ?? this.deaf | ||||
|     this.mute = data.mute ?? this.mute | ||||
|     this.selfDeaf = data.self_deaf ?? this.selfDeaf | ||||
|     this.selfMute = data.self_mute ?? this.selfMute | ||||
|     this.selfStream = data.self_stream ?? this.selfStream | ||||
|     this.selfVideo = data.self_video ?? this.selfVideo | ||||
|     this.suppress = data.suppress ?? this.suppress | ||||
|   } | ||||
| } | ||||
| import { Client } from '../models/client.ts' | ||||
| import { VoiceStatePayload } from '../types/voice.ts' | ||||
| import { Base } from './base.ts' | ||||
| import { Guild } from "./guild.ts" | ||||
| import { VoiceChannel } from "./guildVoiceChannel.ts" | ||||
| import { Member } from "./member.ts" | ||||
| import { User } from "./user.ts" | ||||
| 
 | ||||
| export class VoiceState extends Base { | ||||
|   guild?: Guild | ||||
|   channel: VoiceChannel | null | ||||
|   user: User | ||||
|   member?: Member | ||||
|   sessionID: string | ||||
|   deaf: boolean | ||||
|   mute: boolean | ||||
|   stream?: boolean | ||||
|   video: boolean | ||||
|   suppress: boolean | ||||
| 
 | ||||
|   constructor (client: Client, data: VoiceStatePayload, _data: { | ||||
|     user: User, | ||||
|     channel: VoiceChannel | null, | ||||
|     member?: Member, | ||||
|     guild?: Guild | ||||
|   }) { | ||||
|     super(client, data) | ||||
|     this.channel = _data.channel | ||||
|     this.sessionID = data.session_id | ||||
|     this.user = _data.user | ||||
|     this.member = _data.member | ||||
|     this.guild = _data.guild | ||||
|     this.deaf = data.deaf | ||||
|     this.mute = data.mute | ||||
|     this.deaf = data.self_deaf | ||||
|     this.mute = data.self_mute | ||||
|     this.stream = data.self_stream | ||||
|     this.video = data.self_video | ||||
|     this.suppress = data.suppress | ||||
|   } | ||||
| 
 | ||||
|   protected readFromData (data: VoiceStatePayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.sessionID = data.session_id ?? this.sessionID | ||||
|     this.deaf = data.deaf ?? this.deaf | ||||
|     this.mute = data.mute ?? this.mute | ||||
|     this.deaf = data.self_deaf ?? this.deaf | ||||
|     this.mute = data.self_mute ?? this.mute | ||||
|     this.stream = data.self_stream ?? this.stream | ||||
|     this.video = data.self_video ?? this.video | ||||
|     this.suppress = data.suppress ?? this.suppress | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -92,6 +92,14 @@ client.on('typingStart', (user, channel, at, guildData) => { | |||
|   console.log(`${user.tag} started typing in ${channel.id} at ${at}${guildData !== undefined ? `\nGuild: ${guildData.guild.name}` : ''}`) | ||||
| }) | ||||
| 
 | ||||
| client.on('voiceStateAdd', (state) => { | ||||
|   console.log('VC Join', state) | ||||
| }) | ||||
| 
 | ||||
| client.on('voiceStateRemove', (state) => { | ||||
|   console.log('VC Leave', state) | ||||
| }) | ||||
| 
 | ||||
| // client.on('raw', (evt: string) => console.log(`EVENT: ${evt}`))
 | ||||
| 
 | ||||
| const files = Deno.readDirSync('./src/test/cmds') | ||||
|  |  | |||
|  | @ -104,6 +104,7 @@ export enum GatewayEvents { | |||
|   Typing_Start = 'TYPING_START', | ||||
|   User_Update = 'USER_UPDATE', | ||||
|   Voice_Server_Update = 'VOICE_SERVER_UPDATE', | ||||
|   Voice_State_Update = 'VOICE_STATE_UPDATE', | ||||
|   Webhooks_Update = 'WEBHOOKS_UPDATE' | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,45 +1,45 @@ | |||
| // https://discord.com/developers/docs/topics/opcodes-and-status-codes#voice
 | ||||
| import { MemberPayload } from './guild.ts' | ||||
| 
 | ||||
| export enum VoiceOpcodes { // VoiceOpcodes 추가 - UnderC -
 | ||||
|   IDENTIFY = 0, | ||||
|   SELECT_PROTOCOL = 1, | ||||
|   READY = 2, | ||||
|   HEARTBEAT = 3, | ||||
|   SESSION_DESCRIPTION = 4, | ||||
|   SPEAKING = 6, | ||||
|   HEARTBEAT_ACK = 6, | ||||
|   RESUME = 7, | ||||
|   HELLO = 8, | ||||
|   RESUMED = 9, | ||||
|   CLIENT_DISCONNECT = 13 | ||||
| } | ||||
| 
 | ||||
| export enum VoiceCloseCodes { | ||||
|   UNKNOWN_OPCODE = 4001, | ||||
|   NOT_AUTHENTICATED = 4003, | ||||
|   AUTHENTICATION_FAILED = 4004, | ||||
|   ALREADY_AUTHENTICATED = 4005, | ||||
|   SESSION_NO_LONGER_VALID = 4006, | ||||
|   SESSION_TIMEOUT = 4009, | ||||
|   SERVER_NOT_FOUNT = 4011, | ||||
|   UNKNOWN_PROTOCOL = 4012, | ||||
|   DISCONNECTED = 4014, | ||||
|   VOICE_SERVER_CRASHED = 4015, | ||||
|   UNKNOWN_ENCRYPTION_MODE = 4016 | ||||
| } | ||||
| 
 | ||||
| export interface VoiceStatePayload { | ||||
|   guild_id?: string | ||||
|   channel_id?: string | ||||
|   user_id: string | ||||
|   member?: MemberPayload | ||||
|   session_id: string | ||||
|   deaf: boolean | ||||
|   mute: boolean | ||||
|   self_deaf: boolean | ||||
|   self_mute: boolean | ||||
|   self_stream?: boolean | ||||
|   self_video: boolean | ||||
|   suppress: boolean | ||||
| } | ||||
| // https://discord.com/developers/docs/topics/opcodes-and-status-codes#voice
 | ||||
| import { MemberPayload } from './guild.ts' | ||||
| 
 | ||||
| export enum VoiceOpcodes { // VoiceOpcodes 추가 - UnderC -
 | ||||
|   IDENTIFY = 0, | ||||
|   SELECT_PROTOCOL = 1, | ||||
|   READY = 2, | ||||
|   HEARTBEAT = 3, | ||||
|   SESSION_DESCRIPTION = 4, | ||||
|   SPEAKING = 6, | ||||
|   HEARTBEAT_ACK = 6, | ||||
|   RESUME = 7, | ||||
|   HELLO = 8, | ||||
|   RESUMED = 9, | ||||
|   CLIENT_DISCONNECT = 13 | ||||
| } | ||||
| 
 | ||||
| export enum VoiceCloseCodes { | ||||
|   UNKNOWN_OPCODE = 4001, | ||||
|   NOT_AUTHENTICATED = 4003, | ||||
|   AUTHENTICATION_FAILED = 4004, | ||||
|   ALREADY_AUTHENTICATED = 4005, | ||||
|   SESSION_NO_LONGER_VALID = 4006, | ||||
|   SESSION_TIMEOUT = 4009, | ||||
|   SERVER_NOT_FOUNT = 4011, | ||||
|   UNKNOWN_PROTOCOL = 4012, | ||||
|   DISCONNECTED = 4014, | ||||
|   VOICE_SERVER_CRASHED = 4015, | ||||
|   UNKNOWN_ENCRYPTION_MODE = 4016 | ||||
| } | ||||
| 
 | ||||
| export interface VoiceStatePayload { | ||||
|   guild_id?: string | ||||
|   channel_id: string | null | ||||
|   user_id: string | ||||
|   member?: MemberPayload | ||||
|   session_id: string | ||||
|   deaf: boolean | ||||
|   mute: boolean | ||||
|   self_deaf: boolean | ||||
|   self_mute: boolean | ||||
|   self_stream?: boolean | ||||
|   self_video: boolean | ||||
|   suppress: boolean | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue