diff --git a/src/gateway/opcodes/RequestChannelInfo.ts b/src/gateway/opcodes/RequestChannelInfo.ts new file mode 100644 index 000000000..116841f37 --- /dev/null +++ b/src/gateway/opcodes/RequestChannelInfo.ts @@ -0,0 +1,49 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2025 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { WebSocket, Payload, OPCODES, Send } from "@spacebar/gateway"; +import { ChannelType } from "@spacebar/schemas"; +import { Channel } from "@spacebar/util"; + +export async function onRequestChannelInfo(this: WebSocket, { d }: Payload) { + // Schema validation can only accept either string or array, so transforming it here to support both + if (!d.guild_id) throw new Error('"guild_id" is required'); + if (!d.fields) throw new Error('"fields" is required'); + + const channels = ( + await Channel.find({ + where: { type: ChannelType.GUILD_VOICE }, + relations: { + voice_states: true, + }, + }) + ).filter((c) => c.voice_states && c.voice_states.length > 0); + + await Send(this, { + op: OPCODES.Dispatch, + t: "CHANNEL_INFO", // This is an educated guess... + d: { + guild_id: d.guild_id, + channels: channels.map((c) => ({ + id: c.id, + status: null, // TODO: we dont track this + voice_start_time: new Date().toISOString(), // TODO: we dont track this + })), + }, + }); +} diff --git a/src/gateway/opcodes/RequestChannelStatuses.ts b/src/gateway/opcodes/RequestChannelStatuses.ts index 507cfd57c..533ece229 100644 --- a/src/gateway/opcodes/RequestChannelStatuses.ts +++ b/src/gateway/opcodes/RequestChannelStatuses.ts @@ -19,7 +19,6 @@ import { WebSocket, Payload, OPCODES, Send } from "@spacebar/gateway"; export async function onRequestChannelStatuses(this: WebSocket, { d }: Payload) { - const startTime = Date.now(); // Schema validation can only accept either string or array, so transforming it here to support both if (!d.guild_id) throw new Error('"guild_id" is required'); diff --git a/src/gateway/opcodes/index.ts b/src/gateway/opcodes/index.ts index 358a9420d..fb594237d 100644 --- a/src/gateway/opcodes/index.ts +++ b/src/gateway/opcodes/index.ts @@ -30,6 +30,7 @@ import { onStreamDelete } from "./StreamDelete"; import { onStreamWatch } from "./StreamWatch"; import { onGuildSync } from "./GuildSync"; import { onRequestChannelStatuses } from "./RequestChannelStatuses"; +import { onRequestChannelInfo } from "./RequestChannelInfo"; export type OPCodeHandler = (this: WebSocket, data: Payload) => unknown; @@ -54,4 +55,5 @@ export default { 37: onGuildSubscriptionsBulk, 40: onHeartbeat, // same as 1, except with extra data 41: () => {}, // "Update Time Spent Session ID", just tracking nonsense + 43: onRequestChannelInfo, // extended op36...? } as { [key: number]: OPCodeHandler };