Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87f1f8be8d | ||
|
|
4405647b33 |
No files matched your search
@@ -271,7 +271,7 @@ function connectWatch(
|
|||||||
handleUdpMessage(watchKey, netAny, uidProps, msg);
|
handleUdpMessage(watchKey, netAny, uidProps, msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
net.on("stateChange", (newState, oldState) => {
|
net.on("stateChange", (oldState, newState) => {
|
||||||
const s = newState as { code?: number };
|
const s = newState as { code?: number };
|
||||||
const code = s?.code;
|
const code = s?.code;
|
||||||
const oldCode = (oldState as { code?: number })?.code;
|
const oldCode = (oldState as { code?: number })?.code;
|
||||||
|
|||||||
@@ -78,6 +78,36 @@ export function setVideoRecorderClient(client: Client | undefined) {
|
|||||||
/** Register a channel whose audio recording is active (video should follow). */
|
/** Register a channel whose audio recording is active (video should follow). */
|
||||||
export function trackChannel(guildId: string, channel: VoiceChannel) {
|
export function trackChannel(guildId: string, channel: VoiceChannel) {
|
||||||
watchedChannels.set(guildId, channel);
|
watchedChannels.set(guildId, channel);
|
||||||
|
// When the bot joins a channel that ALREADY has people streaming (screen
|
||||||
|
// share / camera on BEFORE the bot joined), no voiceStateUpdate with
|
||||||
|
// streaming:true fires for them. Scan every member now and start watching
|
||||||
|
// anyone already streaming, so we don't miss a live stream in progress.
|
||||||
|
scanExistingStreamers(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan all members currently in `channel` and start watching anyone whose
|
||||||
|
* voice state has `streaming` set (screen share / camera already on when the
|
||||||
|
* bot joined). Fire-and-forget per member — idempotent (startStreamWatch is
|
||||||
|
* a no-op if a watch already exists for that user).
|
||||||
|
*/
|
||||||
|
export function scanExistingStreamers(channel: VoiceChannel): void {
|
||||||
|
const members = channel.members;
|
||||||
|
if (!members || members.size === 0) return;
|
||||||
|
let watched = 0;
|
||||||
|
for (const [, member] of members) {
|
||||||
|
const vs = member.voice?.streaming;
|
||||||
|
if (vs && member.id !== _client?.user?.id) {
|
||||||
|
startVideoRecording(channel, member.id);
|
||||||
|
watched++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (watched > 0) {
|
||||||
|
logger.info(
|
||||||
|
{ guildId: channel.guild.id, watched },
|
||||||
|
"Scanned pre-existing streamers on join",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unregister a channel (voice stopped). Tear down any video watches. */
|
/** Unregister a channel (voice stopped). Tear down any video watches. */
|
||||||
|
|||||||
@@ -101,4 +101,29 @@ describe("videoRecorder (stream-watch orchestration)", () => {
|
|||||||
listener(null, { id: "u1", guild: { id: "g1" }, channelId: "c1", streaming: false });
|
listener(null, { id: "u1", guild: { id: "g1" }, channelId: "c1", streaming: false });
|
||||||
expect(stopSpy).toHaveBeenCalledWith("g1", "u1");
|
expect(stopSpy).toHaveBeenCalledWith("g1", "u1");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("trackChannel scans pre-existing streamers already in the channel (bot join case)", () => {
|
||||||
|
const client = makeClient() as any;
|
||||||
|
setVideoRecorderClient(client);
|
||||||
|
const spy = vi.spyOn(streamWatch, "startStreamWatch").mockImplementation(() => {});
|
||||||
|
const ch = {
|
||||||
|
id: "c1",
|
||||||
|
guild: { id: "g1" },
|
||||||
|
members: new Map([
|
||||||
|
["u1", { id: "u1", voice: { streaming: true } }], // already streaming
|
||||||
|
["u2", { id: "u2", voice: { streaming: false } }], // not streaming
|
||||||
|
["bot1", { id: "bot1", voice: { streaming: true } }], // bot itself
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
trackChannel("g1", ch as any);
|
||||||
|
// only the already-streaming non-bot member gets watched
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(spy).toHaveBeenCalledWith(ch, "u1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("trackChannel is a no-op when the channel has no members (or none streaming)", () => {
|
||||||
|
const spy = vi.spyOn(streamWatch, "startStreamWatch").mockImplementation(() => {});
|
||||||
|
trackChannel("g1", makeChannel()); // no members
|
||||||
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user