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_API_URL: string = 'https://discord.com/api'
|
||||||
|
|
||||||
export const DISCORD_GATEWAY_URL: string = 'wss://gateway.discord.gg'
|
export const DISCORD_GATEWAY_URL: string = 'wss://gateway.discord.gg'
|
||||||
|
|
||||||
export const DISCORD_CDN_URL: string = 'https://cdn.discordapp.com'
|
export const DISCORD_CDN_URL: string = 'https://cdn.discordapp.com'
|
||||||
|
|
||||||
export const DISCORD_API_VERSION: number = 8
|
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 { Role } from "../../structures/role.ts"
|
||||||
import { Message } from "../../structures/message.ts"
|
import { Message } from "../../structures/message.ts"
|
||||||
import { Collection } from "../../utils/collection.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: {
|
export const gatewayHandlers: {
|
||||||
[eventCode in GatewayEvents]: GatewayEventHandler | undefined
|
[eventCode in GatewayEvents]: GatewayEventHandler | undefined
|
||||||
|
@ -74,7 +77,8 @@ export const gatewayHandlers: {
|
||||||
PRESENCE_UPDATE: undefined,
|
PRESENCE_UPDATE: undefined,
|
||||||
TYPING_START: typingStart,
|
TYPING_START: typingStart,
|
||||||
USER_UPDATE: userUpdate,
|
USER_UPDATE: userUpdate,
|
||||||
VOICE_SERVER_UPDATE: undefined,
|
VOICE_STATE_UPDATE: voiceStateUpdate,
|
||||||
|
VOICE_SERVER_UPDATE: voiceServerUpdate,
|
||||||
WEBHOOKS_UPDATE: webhooksUpdate
|
WEBHOOKS_UPDATE: webhooksUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +86,12 @@ export interface EventTypes {
|
||||||
[name: string]: (...args: any[]) => void
|
[name: string]: (...args: any[]) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VoiceServerUpdateData {
|
||||||
|
token: string
|
||||||
|
endpoint: string
|
||||||
|
guild: Guild
|
||||||
|
}
|
||||||
|
|
||||||
export interface ClientEvents extends EventTypes {
|
export interface ClientEvents extends EventTypes {
|
||||||
'ready': () => void
|
'ready': () => void
|
||||||
'reconnect': () => void
|
'reconnect': () => void
|
||||||
|
@ -111,5 +121,9 @@ export interface ClientEvents extends EventTypes {
|
||||||
'messageUpdate': (before: Message, after: Message) => void
|
'messageUpdate': (before: Message, after: Message) => void
|
||||||
'typingStart': (user: User, channel: TextChannel, at: Date, guildData?: TypingStartGuildData) => void
|
'typingStart': (user: User, channel: TextChannel, at: Date, guildData?: TypingStartGuildData) => void
|
||||||
'userUpdate': (before: User, after: User) => 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
|
'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 { Guild } from '../structures/guild.ts'
|
||||||
import { Message } from '../structures/message.ts'
|
import { Message } from '../structures/message.ts'
|
||||||
import { TextChannel } from '../structures/textChannel.ts'
|
import { TextChannel } from '../structures/textChannel.ts'
|
||||||
import { User } from '../structures/user.ts'
|
import { User } from '../structures/user.ts'
|
||||||
import { Collection } from '../utils/collection.ts'
|
import { Collection } from '../utils/collection.ts'
|
||||||
import { CommandClient } from './commandClient.ts'
|
import { CommandClient } from './commandClient.ts'
|
||||||
import { Extension } from "./extensions.ts"
|
import { Extension } from "./extensions.ts"
|
||||||
|
|
||||||
export interface CommandContext {
|
export interface CommandContext {
|
||||||
/** The Client object */
|
/** The Client object */
|
||||||
client: CommandClient
|
client: CommandClient
|
||||||
/** Message which was parsed for Command */
|
/** Message which was parsed for Command */
|
||||||
message: Message
|
message: Message
|
||||||
/** The Author of the Message */
|
/** The Author of the Message */
|
||||||
author: User
|
author: User
|
||||||
/** The Channel in which Command was used */
|
/** The Channel in which Command was used */
|
||||||
channel: TextChannel
|
channel: TextChannel
|
||||||
/** Prefix which was used */
|
/** Prefix which was used */
|
||||||
prefix: string
|
prefix: string
|
||||||
/** Oject of Command which was used */
|
/** Oject of Command which was used */
|
||||||
command: Command
|
command: Command
|
||||||
/** Name of Command which was used */
|
/** Name of Command which was used */
|
||||||
name: string
|
name: string
|
||||||
/** Array of Arguments used with Command */
|
/** Array of Arguments used with Command */
|
||||||
args: string[]
|
args: string[]
|
||||||
/** Complete Raw String of Arguments */
|
/** Complete Raw String of Arguments */
|
||||||
argString: string
|
argString: string
|
||||||
/** Guild which the command has called */
|
/** Guild which the command has called */
|
||||||
guild?: Guild
|
guild?: Guild
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Command {
|
export class Command {
|
||||||
/** Name of the Command */
|
/** Name of the Command */
|
||||||
name: string = ''
|
name: string = ''
|
||||||
/** Description of the Command */
|
/** Description of the Command */
|
||||||
description?: string
|
description?: string
|
||||||
/** Array of Aliases of Command, or only string */
|
/** Array of Aliases of Command, or only string */
|
||||||
aliases?: string | string[]
|
aliases?: string | string[]
|
||||||
/** Extension (Parent) of the Command */
|
/** Extension (Parent) of the Command */
|
||||||
extension?: Extension
|
extension?: Extension
|
||||||
/** Usage of Command, only Argument Names */
|
/** Usage of Command, only Argument Names */
|
||||||
usage?: string | string[]
|
usage?: string | string[]
|
||||||
/** Usage Example of Command, only Arguments (without Prefix and Name) */
|
/** Usage Example of Command, only Arguments (without Prefix and Name) */
|
||||||
examples?: string | string[]
|
examples?: string | string[]
|
||||||
/** Does the Command take Arguments? Maybe number of required arguments? */
|
/** Does the Command take Arguments? Maybe number of required arguments? */
|
||||||
args?: number | boolean
|
args?: number | boolean
|
||||||
/** Permission(s) required for using Command */
|
/** Permission(s) required for using Command */
|
||||||
permissions?: string | string[]
|
permissions?: string | string[]
|
||||||
/** Permission(s) bot will need in order to execute Command */
|
/** Permission(s) bot will need in order to execute Command */
|
||||||
botPermissions?: string | string[]
|
botPermissions?: string | string[]
|
||||||
/** Role(s) user will require in order to use Command. List or one of ID or name */
|
/** Role(s) user will require in order to use Command. List or one of ID or name */
|
||||||
roles?: string | string[]
|
roles?: string | string[]
|
||||||
/** Whitelisted Guilds. Only these Guild(s) can execute Command. (List or one of IDs) */
|
/** Whitelisted Guilds. Only these Guild(s) can execute Command. (List or one of IDs) */
|
||||||
whitelistedGuilds?: string | string[]
|
whitelistedGuilds?: string | string[]
|
||||||
/** Whitelisted Channels. Command can be executed only in these channels. (List or one of IDs) */
|
/** Whitelisted Channels. Command can be executed only in these channels. (List or one of IDs) */
|
||||||
whitelistedChannels?: string | string[]
|
whitelistedChannels?: string | string[]
|
||||||
/** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */
|
/** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */
|
||||||
whitelistedUsers?: string | string[]
|
whitelistedUsers?: string | string[]
|
||||||
/** Whether the Command can only be used in Guild (if allowed in DMs) */
|
/** Whether the Command can only be used in Guild (if allowed in DMs) */
|
||||||
guildOnly?: boolean
|
guildOnly?: boolean
|
||||||
/** Whether the Command can only be used in Bot's DMs (if allowed) */
|
/** Whether the Command can only be used in Bot's DMs (if allowed) */
|
||||||
dmOnly?: boolean
|
dmOnly?: boolean
|
||||||
/** Whether the Command can only be used by Bot Owners */
|
/** Whether the Command can only be used by Bot Owners */
|
||||||
ownerOnly?: boolean
|
ownerOnly?: boolean
|
||||||
|
|
||||||
/** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */
|
/** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */
|
||||||
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> { return true }
|
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> { return true }
|
||||||
/** Actual command code, which is executed when all checks have passed. */
|
/** Actual command code, which is executed when all checks have passed. */
|
||||||
execute(ctx: CommandContext): any { }
|
execute(ctx: CommandContext): any { }
|
||||||
/** Method executed after executing command, passes on CommandContext and the value returned by execute too. (optional) */
|
/** Method executed after executing command, passes on CommandContext and the value returned by execute too. (optional) */
|
||||||
afterExecute(ctx: CommandContext, executeResult: any): any { }
|
afterExecute(ctx: CommandContext, executeResult: any): any { }
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return `Command: ${this.name}${this.extension !== undefined ? ` [${this.extension.name}]` : ''}`
|
return `Command: ${this.name}${this.extension !== undefined ? ` [${this.extension.name}]` : ''}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CommandsManager {
|
export class CommandsManager {
|
||||||
client: CommandClient
|
client: CommandClient
|
||||||
list: Collection<string, Command> = new Collection()
|
list: Collection<string, Command> = new Collection()
|
||||||
disabled: Set<string> = new Set()
|
disabled: Set<string> = new Set()
|
||||||
|
|
||||||
constructor(client: CommandClient) {
|
constructor(client: CommandClient) {
|
||||||
this.client = client
|
this.client = client
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Number of loaded Commands */
|
/** Number of loaded Commands */
|
||||||
get count(): number { return this.list.size }
|
get count(): number { return this.list.size }
|
||||||
|
|
||||||
/** Find a Command by name/alias */
|
/** Find a Command by name/alias */
|
||||||
find(search: string): Command | undefined {
|
find(search: string): Command | undefined {
|
||||||
if (this.client.caseSensitive === false) search = search.toLowerCase()
|
if (this.client.caseSensitive === false) search = search.toLowerCase()
|
||||||
return this.list.find((cmd: Command): boolean => {
|
return this.list.find((cmd: Command): boolean => {
|
||||||
const name =
|
const name =
|
||||||
this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase()
|
this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase()
|
||||||
if (name === search) return true
|
if (name === search) return true
|
||||||
else if (cmd.aliases !== undefined) {
|
else if (cmd.aliases !== undefined) {
|
||||||
let aliases: string[]
|
let aliases: string[]
|
||||||
if (typeof cmd.aliases === 'string') aliases = [cmd.aliases]
|
if (typeof cmd.aliases === 'string') aliases = [cmd.aliases]
|
||||||
else aliases = cmd.aliases
|
else aliases = cmd.aliases
|
||||||
if (this.client.caseSensitive === false)
|
if (this.client.caseSensitive === false)
|
||||||
aliases = aliases.map(e => e.toLowerCase())
|
aliases = aliases.map(e => e.toLowerCase())
|
||||||
return aliases.includes(search)
|
return aliases.includes(search)
|
||||||
} else return false
|
} else return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fetch a Command including disable checks */
|
/** Fetch a Command including disable checks */
|
||||||
fetch(name: string, bypassDisable?: boolean): Command | undefined {
|
fetch(name: string, bypassDisable?: boolean): Command | undefined {
|
||||||
const cmd = this.find(name)
|
const cmd = this.find(name)
|
||||||
if (cmd === undefined) return
|
if (cmd === undefined) return
|
||||||
if (this.isDisabled(cmd) && bypassDisable !== true) return
|
if (this.isDisabled(cmd) && bypassDisable !== true) return
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check whether a Command exists or not */
|
/** Check whether a Command exists or not */
|
||||||
exists(search: Command | string): boolean {
|
exists(search: Command | string): boolean {
|
||||||
let exists = false
|
let exists = false
|
||||||
if (typeof search === 'string') return this.find(search) !== undefined
|
if (typeof search === 'string') return this.find(search) !== undefined
|
||||||
else {
|
else {
|
||||||
exists = this.find(search.name) !== undefined
|
exists = this.find(search.name) !== undefined
|
||||||
if (search.aliases !== undefined) {
|
if (search.aliases !== undefined) {
|
||||||
const aliases: string[] =
|
const aliases: string[] =
|
||||||
typeof search.aliases === 'string' ? [search.aliases] : search.aliases
|
typeof search.aliases === 'string' ? [search.aliases] : search.aliases
|
||||||
exists =
|
exists =
|
||||||
aliases.map(alias => this.find(alias) !== undefined).find(e => e) ??
|
aliases.map(alias => this.find(alias) !== undefined).find(e => e) ??
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add a Command */
|
/** Add a Command */
|
||||||
add(cmd: Command | typeof Command): boolean {
|
add(cmd: Command | typeof Command): boolean {
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
if (!(cmd instanceof Command)) cmd = new cmd()
|
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.`)
|
if (this.exists(cmd)) throw new Error(`Failed to add Command '${cmd.toString()}' with name/alias already exists.`)
|
||||||
this.list.set(cmd.name, cmd)
|
this.list.set(cmd.name, cmd)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Delete a Command */
|
/** Delete a Command */
|
||||||
delete(cmd: string | Command): boolean {
|
delete(cmd: string | Command): boolean {
|
||||||
const find = typeof cmd === 'string' ? this.find(cmd) : cmd
|
const find = typeof cmd === 'string' ? this.find(cmd) : cmd
|
||||||
if (find === undefined) return false
|
if (find === undefined) return false
|
||||||
else return this.list.delete(find.name)
|
else return this.list.delete(find.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check whether a Command is disabled or not */
|
/** Check whether a Command is disabled or not */
|
||||||
isDisabled(name: string | Command): boolean {
|
isDisabled(name: string | Command): boolean {
|
||||||
const cmd = typeof name === "string" ? this.find(name) : name
|
const cmd = typeof name === "string" ? this.find(name) : name
|
||||||
if (cmd === undefined) return false
|
if (cmd === undefined) return false
|
||||||
const exists = this.exists(name)
|
const exists = this.exists(name)
|
||||||
if (!exists) return false
|
if (!exists) return false
|
||||||
return this.disabled.has(cmd.name)
|
return this.disabled.has(cmd.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Disable a Command */
|
/** Disable a Command */
|
||||||
disable(name: string | Command): boolean {
|
disable(name: string | Command): boolean {
|
||||||
const cmd = typeof name === "string" ? this.find(name) : name
|
const cmd = typeof name === "string" ? this.find(name) : name
|
||||||
if (cmd === undefined) return false
|
if (cmd === undefined) return false
|
||||||
if (this.isDisabled(cmd)) return false
|
if (this.isDisabled(cmd)) return false
|
||||||
this.disabled.add(cmd.name)
|
this.disabled.add(cmd.name)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ParsedCommand {
|
export interface ParsedCommand {
|
||||||
name: string
|
name: string
|
||||||
args: string[]
|
args: string[]
|
||||||
argString: string
|
argString: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const parseCommand = (
|
export const parseCommand = (
|
||||||
client: CommandClient,
|
client: CommandClient,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
prefix: string
|
prefix: string
|
||||||
): ParsedCommand => {
|
): ParsedCommand => {
|
||||||
let content = msg.content.slice(prefix.length)
|
let content = msg.content.slice(prefix.length)
|
||||||
if (client.spacesAfterPrefix === true) content = content.trim()
|
if (client.spacesAfterPrefix === true) content = content.trim()
|
||||||
const args = content.split(client.betterArgs === true ? /[\S\s]*/ : / +/)
|
const args = content.split(client.betterArgs === true ? /[\S\s]*/ : / +/)
|
||||||
const name = args.shift() as string
|
const name = args.shift() as string
|
||||||
const argString = content.slice(name.length).trim()
|
const argString = content.slice(name.length).trim()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
argString
|
argString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,26 @@
|
||||||
|
import { Guild } from "../structures/guild.ts"
|
||||||
|
import { VoiceChannel } from "../structures/guildVoiceChannel.ts"
|
||||||
import { Client } from './client.ts'
|
import { Client } from './client.ts'
|
||||||
|
|
||||||
|
export interface VoiceOptions {
|
||||||
|
guild: Guild,
|
||||||
|
channel: VoiceChannel
|
||||||
|
}
|
||||||
|
|
||||||
export class VoiceClient {
|
export class VoiceClient {
|
||||||
client: Client
|
client: Client
|
||||||
|
ws?: WebSocket
|
||||||
|
guild: Guild
|
||||||
|
channel: VoiceChannel
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client, options: VoiceOptions) {
|
||||||
this.client = client
|
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 { GuildFeatures, GuildIntegrationPayload, GuildPayload, IntegrationAccountPayload, IntegrationExpireBehavior } from '../types/guild.ts'
|
||||||
import { PresenceUpdatePayload } from '../types/gateway.ts'
|
import { PresenceUpdatePayload } from '../types/gateway.ts'
|
||||||
import { Base } from './base.ts'
|
import { Base } from './base.ts'
|
||||||
import { VoiceState } from './voiceState.ts'
|
|
||||||
import { RolesManager } from '../managers/roles.ts'
|
import { RolesManager } from '../managers/roles.ts'
|
||||||
import { GuildChannelsManager } from '../managers/guildChannels.ts'
|
import { GuildChannelsManager } from '../managers/guildChannels.ts'
|
||||||
import { MembersManager } from '../managers/members.ts'
|
import { MembersManager } from '../managers/members.ts'
|
||||||
|
@ -12,6 +11,7 @@ import { Member } from "./member.ts"
|
||||||
import { User } from "./user.ts"
|
import { User } from "./user.ts"
|
||||||
import { Application } from "./application.ts"
|
import { Application } from "./application.ts"
|
||||||
import { GUILD_INTEGRATIONS } from "../types/endpoint.ts"
|
import { GUILD_INTEGRATIONS } from "../types/endpoint.ts"
|
||||||
|
import { GuildVoiceStatesManager } from "../managers/guildVoiceStates.ts"
|
||||||
|
|
||||||
export class Guild extends Base {
|
export class Guild extends Base {
|
||||||
id: string
|
id: string
|
||||||
|
@ -43,7 +43,7 @@ export class Guild extends Base {
|
||||||
large?: boolean
|
large?: boolean
|
||||||
unavailable: boolean
|
unavailable: boolean
|
||||||
memberCount?: number
|
memberCount?: number
|
||||||
voiceStates?: VoiceState[]
|
voiceStates: GuildVoiceStatesManager
|
||||||
members: MembersManager
|
members: MembersManager
|
||||||
channels: GuildChannelsManager
|
channels: GuildChannelsManager
|
||||||
presences?: PresenceUpdatePayload[]
|
presences?: PresenceUpdatePayload[]
|
||||||
|
@ -65,6 +65,7 @@ export class Guild extends Base {
|
||||||
this.id = data.id
|
this.id = data.id
|
||||||
this.unavailable = data.unavailable
|
this.unavailable = data.unavailable
|
||||||
this.members = new MembersManager(this.client, this)
|
this.members = new MembersManager(this.client, this)
|
||||||
|
this.voiceStates = new GuildVoiceStatesManager(client, this)
|
||||||
this.channels = new GuildChannelsManager(
|
this.channels = new GuildChannelsManager(
|
||||||
this.client,
|
this.client,
|
||||||
this.client.channels,
|
this.client.channels,
|
||||||
|
|
|
@ -1,49 +1,53 @@
|
||||||
import { Client } from '../models/client.ts'
|
import { Client } from '../models/client.ts'
|
||||||
import { MemberPayload } from '../types/guild.ts'
|
import { VoiceStatePayload } from '../types/voice.ts'
|
||||||
import { VoiceStatePayload } from '../types/voice.ts'
|
import { Base } from './base.ts'
|
||||||
import { Base } from './base.ts'
|
import { Guild } from "./guild.ts"
|
||||||
|
import { VoiceChannel } from "./guildVoiceChannel.ts"
|
||||||
export class VoiceState extends Base {
|
import { Member } from "./member.ts"
|
||||||
guildID?: string
|
import { User } from "./user.ts"
|
||||||
channelID?: string
|
|
||||||
userID: string
|
export class VoiceState extends Base {
|
||||||
member?: MemberPayload
|
guild?: Guild
|
||||||
sessionID: string
|
channel: VoiceChannel | null
|
||||||
deaf: boolean
|
user: User
|
||||||
mute: boolean
|
member?: Member
|
||||||
selfDeaf: boolean
|
sessionID: string
|
||||||
selfMute: boolean
|
deaf: boolean
|
||||||
selfStream?: boolean
|
mute: boolean
|
||||||
selfVideo: boolean
|
stream?: boolean
|
||||||
suppress: boolean
|
video: boolean
|
||||||
|
suppress: boolean
|
||||||
constructor (client: Client, data: VoiceStatePayload) {
|
|
||||||
super(client, data)
|
constructor (client: Client, data: VoiceStatePayload, _data: {
|
||||||
this.channelID = data.channel_id
|
user: User,
|
||||||
this.sessionID = data.session_id
|
channel: VoiceChannel | null,
|
||||||
this.userID = data.user_id
|
member?: Member,
|
||||||
this.deaf = data.deaf
|
guild?: Guild
|
||||||
this.mute = data.mute
|
}) {
|
||||||
this.selfDeaf = data.self_deaf
|
super(client, data)
|
||||||
this.selfMute = data.self_mute
|
this.channel = _data.channel
|
||||||
this.selfStream = data.self_stream
|
this.sessionID = data.session_id
|
||||||
this.selfVideo = data.self_video
|
this.user = _data.user
|
||||||
this.suppress = data.suppress
|
this.member = _data.member
|
||||||
// TODO: Cache in Gateway Event Code
|
this.guild = _data.guild
|
||||||
// cache.set('voiceState', `${this.guildID}:${this.userID}`, this)
|
this.deaf = data.deaf
|
||||||
}
|
this.mute = data.mute
|
||||||
|
this.deaf = data.self_deaf
|
||||||
protected readFromData (data: VoiceStatePayload): void {
|
this.mute = data.self_mute
|
||||||
super.readFromData(data)
|
this.stream = data.self_stream
|
||||||
this.channelID = data.channel_id ?? this.channelID
|
this.video = data.self_video
|
||||||
this.sessionID = data.session_id ?? this.sessionID
|
this.suppress = data.suppress
|
||||||
this.userID = data.user_id ?? this.userID
|
}
|
||||||
this.deaf = data.deaf ?? this.deaf
|
|
||||||
this.mute = data.mute ?? this.mute
|
protected readFromData (data: VoiceStatePayload): void {
|
||||||
this.selfDeaf = data.self_deaf ?? this.selfDeaf
|
super.readFromData(data)
|
||||||
this.selfMute = data.self_mute ?? this.selfMute
|
this.sessionID = data.session_id ?? this.sessionID
|
||||||
this.selfStream = data.self_stream ?? this.selfStream
|
this.deaf = data.deaf ?? this.deaf
|
||||||
this.selfVideo = data.self_video ?? this.selfVideo
|
this.mute = data.mute ?? this.mute
|
||||||
this.suppress = data.suppress ?? this.suppress
|
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}` : ''}`)
|
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}`))
|
// client.on('raw', (evt: string) => console.log(`EVENT: ${evt}`))
|
||||||
|
|
||||||
const files = Deno.readDirSync('./src/test/cmds')
|
const files = Deno.readDirSync('./src/test/cmds')
|
||||||
|
|
|
@ -104,6 +104,7 @@ export enum GatewayEvents {
|
||||||
Typing_Start = 'TYPING_START',
|
Typing_Start = 'TYPING_START',
|
||||||
User_Update = 'USER_UPDATE',
|
User_Update = 'USER_UPDATE',
|
||||||
Voice_Server_Update = 'VOICE_SERVER_UPDATE',
|
Voice_Server_Update = 'VOICE_SERVER_UPDATE',
|
||||||
|
Voice_State_Update = 'VOICE_STATE_UPDATE',
|
||||||
Webhooks_Update = 'WEBHOOKS_UPDATE'
|
Webhooks_Update = 'WEBHOOKS_UPDATE'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
// https://discord.com/developers/docs/topics/opcodes-and-status-codes#voice
|
// https://discord.com/developers/docs/topics/opcodes-and-status-codes#voice
|
||||||
import { MemberPayload } from './guild.ts'
|
import { MemberPayload } from './guild.ts'
|
||||||
|
|
||||||
export enum VoiceOpcodes { // VoiceOpcodes 추가 - UnderC -
|
export enum VoiceOpcodes { // VoiceOpcodes 추가 - UnderC -
|
||||||
IDENTIFY = 0,
|
IDENTIFY = 0,
|
||||||
SELECT_PROTOCOL = 1,
|
SELECT_PROTOCOL = 1,
|
||||||
READY = 2,
|
READY = 2,
|
||||||
HEARTBEAT = 3,
|
HEARTBEAT = 3,
|
||||||
SESSION_DESCRIPTION = 4,
|
SESSION_DESCRIPTION = 4,
|
||||||
SPEAKING = 6,
|
SPEAKING = 6,
|
||||||
HEARTBEAT_ACK = 6,
|
HEARTBEAT_ACK = 6,
|
||||||
RESUME = 7,
|
RESUME = 7,
|
||||||
HELLO = 8,
|
HELLO = 8,
|
||||||
RESUMED = 9,
|
RESUMED = 9,
|
||||||
CLIENT_DISCONNECT = 13
|
CLIENT_DISCONNECT = 13
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum VoiceCloseCodes {
|
export enum VoiceCloseCodes {
|
||||||
UNKNOWN_OPCODE = 4001,
|
UNKNOWN_OPCODE = 4001,
|
||||||
NOT_AUTHENTICATED = 4003,
|
NOT_AUTHENTICATED = 4003,
|
||||||
AUTHENTICATION_FAILED = 4004,
|
AUTHENTICATION_FAILED = 4004,
|
||||||
ALREADY_AUTHENTICATED = 4005,
|
ALREADY_AUTHENTICATED = 4005,
|
||||||
SESSION_NO_LONGER_VALID = 4006,
|
SESSION_NO_LONGER_VALID = 4006,
|
||||||
SESSION_TIMEOUT = 4009,
|
SESSION_TIMEOUT = 4009,
|
||||||
SERVER_NOT_FOUNT = 4011,
|
SERVER_NOT_FOUNT = 4011,
|
||||||
UNKNOWN_PROTOCOL = 4012,
|
UNKNOWN_PROTOCOL = 4012,
|
||||||
DISCONNECTED = 4014,
|
DISCONNECTED = 4014,
|
||||||
VOICE_SERVER_CRASHED = 4015,
|
VOICE_SERVER_CRASHED = 4015,
|
||||||
UNKNOWN_ENCRYPTION_MODE = 4016
|
UNKNOWN_ENCRYPTION_MODE = 4016
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VoiceStatePayload {
|
export interface VoiceStatePayload {
|
||||||
guild_id?: string
|
guild_id?: string
|
||||||
channel_id?: string
|
channel_id: string | null
|
||||||
user_id: string
|
user_id: string
|
||||||
member?: MemberPayload
|
member?: MemberPayload
|
||||||
session_id: string
|
session_id: string
|
||||||
deaf: boolean
|
deaf: boolean
|
||||||
mute: boolean
|
mute: boolean
|
||||||
self_deaf: boolean
|
self_deaf: boolean
|
||||||
self_mute: boolean
|
self_mute: boolean
|
||||||
self_stream?: boolean
|
self_stream?: boolean
|
||||||
self_video: boolean
|
self_video: boolean
|
||||||
suppress: boolean
|
suppress: boolean
|
||||||
}
|
}
|
||||||
|
|
140
tsconfig.json
140
tsconfig.json
|
@ -1,70 +1,70 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
/* Basic Options */
|
/* Basic Options */
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||||
"lib": [
|
"lib": [
|
||||||
"esnext"
|
"esnext"
|
||||||
] /* Specify library files to be included in the compilation. */,
|
] /* Specify library files to be included in the compilation. */,
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
// "outDir": "./", /* Redirect output structure to the directory. */
|
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
// "composite": true, /* Enable project compilation */
|
// "composite": true, /* Enable project compilation */
|
||||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
// "removeComments": true, /* Do not emit comments to output. */
|
// "removeComments": true, /* Do not emit comments to output. */
|
||||||
// "noEmit": true, /* Do not emit outputs. */
|
// "noEmit": true, /* Do not emit outputs. */
|
||||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
"isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,
|
"isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,
|
||||||
/* Strict Type-Checking Options */
|
/* Strict Type-Checking Options */
|
||||||
"strict": true,
|
"strict": true,
|
||||||
/* Enable all strict type-checking options. */
|
/* Enable all strict type-checking options. */
|
||||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
/* Additional Checks */
|
/* Additional Checks */
|
||||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
/* Module Resolution Options */
|
/* Module Resolution Options */
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
/* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
/* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
/* Source Map Options */
|
/* Source Map Options */
|
||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
/* Experimental Options */
|
/* Experimental Options */
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
"emitDecoratorMetadata": false /* Enables experimental support for emitting type metadata for decorators. */,
|
"emitDecoratorMetadata": false /* Enables experimental support for emitting type metadata for decorators. */,
|
||||||
/* Advanced Options */
|
/* Advanced Options */
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
/* Skip type checking of declaration files. */
|
/* Skip type checking of declaration files. */
|
||||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue