feat: void -- start work
This commit is contained in:
parent
6f60bd5040
commit
a6697a75a7
13 changed files with 485 additions and 365 deletions
|
@ -5,3 +5,5 @@ 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,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'
|
||||
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 {
|
||||
guildID?: string
|
||||
channelID?: string
|
||||
userID: string
|
||||
member?: MemberPayload
|
||||
guild?: Guild
|
||||
channel: VoiceChannel | null
|
||||
user: User
|
||||
member?: Member
|
||||
sessionID: string
|
||||
deaf: boolean
|
||||
mute: boolean
|
||||
selfDeaf: boolean
|
||||
selfMute: boolean
|
||||
selfStream?: boolean
|
||||
selfVideo: boolean
|
||||
stream?: boolean
|
||||
video: boolean
|
||||
suppress: boolean
|
||||
|
||||
constructor (client: Client, data: VoiceStatePayload) {
|
||||
constructor (client: Client, data: VoiceStatePayload, _data: {
|
||||
user: User,
|
||||
channel: VoiceChannel | null,
|
||||
member?: Member,
|
||||
guild?: Guild
|
||||
}) {
|
||||
super(client, data)
|
||||
this.channelID = data.channel_id
|
||||
this.channel = _data.channel
|
||||
this.sessionID = data.session_id
|
||||
this.userID = data.user_id
|
||||
this.user = _data.user
|
||||
this.member = _data.member
|
||||
this.guild = _data.guild
|
||||
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.deaf = data.self_deaf
|
||||
this.mute = data.self_mute
|
||||
this.stream = data.self_stream
|
||||
this.video = 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.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'
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ export enum VoiceCloseCodes {
|
|||
|
||||
export interface VoiceStatePayload {
|
||||
guild_id?: string
|
||||
channel_id?: string
|
||||
channel_id: string | null
|
||||
user_id: string
|
||||
member?: MemberPayload
|
||||
session_id: string
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
// "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. */
|
||||
/* 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. */,
|
||||
/* Advanced Options */
|
||||
"skipLibCheck": true,
|
||||
|
|
Loading…
Reference in a new issue