feat: implement media echo fix and YouTube screenshare design
- Introduced a new `ScreenShareController` to manage YouTube screenshare functionality. - Updated `DiscordPlayer` to track ownership of audio streams, preventing conflicts between music playback and screenshare. - Added error handling for various states including voice connection checks and media busy states. - Created unit tests for `ScreenShareController` and `DiscordPlayer` ownership rules to ensure correct functionality. - Added documentation for the new media echo fix and screenshare design.
This commit is contained in:
@@ -14,7 +14,12 @@ function getHandler(
|
||||
describe("createMediaRoutes", () => {
|
||||
it("returns media status", async () => {
|
||||
const controller = {
|
||||
getState: vi.fn(() => ({ playing: false, current: null, queue: [] })),
|
||||
getState: vi.fn(() => ({
|
||||
playing: false,
|
||||
activeMode: null,
|
||||
current: null,
|
||||
queue: [],
|
||||
})),
|
||||
queue: vi.fn(),
|
||||
skip: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
@@ -30,13 +35,14 @@ describe("createMediaRoutes", () => {
|
||||
|
||||
expect(json).toHaveBeenCalledWith({
|
||||
playing: false,
|
||||
activeMode: null,
|
||||
current: null,
|
||||
queue: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("queues a source", async () => {
|
||||
const state = { playing: true, current: null, queue: [] };
|
||||
const state = { playing: true, activeMode: null, current: null, queue: [] };
|
||||
const controller = {
|
||||
getState: vi.fn(),
|
||||
queue: vi.fn(async () => state),
|
||||
@@ -58,10 +64,71 @@ describe("createMediaRoutes", () => {
|
||||
|
||||
expect(controller.queue).toHaveBeenCalledWith(
|
||||
"https://example.com/song.mp3",
|
||||
{ mode: "music" },
|
||||
);
|
||||
expect(json).toHaveBeenCalledWith(state);
|
||||
});
|
||||
|
||||
it("queues a screen source", async () => {
|
||||
const state = {
|
||||
playing: true,
|
||||
activeMode: "screen" as const,
|
||||
current: null,
|
||||
queue: [],
|
||||
};
|
||||
const controller = {
|
||||
getState: vi.fn(),
|
||||
queue: vi.fn(async () => state),
|
||||
skip: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
};
|
||||
const handler = getHandler(
|
||||
createMediaRoutes(controller),
|
||||
"/media/queue",
|
||||
"post",
|
||||
);
|
||||
const json = vi.fn();
|
||||
|
||||
await handler?.(
|
||||
{ body: { source: "https://youtu.be/video", mode: "screen" } } as Request,
|
||||
{ json } as unknown as Response,
|
||||
vi.fn(),
|
||||
);
|
||||
|
||||
expect(controller.queue).toHaveBeenCalledWith("https://youtu.be/video", {
|
||||
mode: "screen",
|
||||
});
|
||||
expect(json).toHaveBeenCalledWith(state);
|
||||
});
|
||||
|
||||
it("passes invalid mode errors to Express", async () => {
|
||||
const controller = {
|
||||
getState: vi.fn(),
|
||||
queue: vi.fn(),
|
||||
skip: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
};
|
||||
const handler = getHandler(
|
||||
createMediaRoutes(controller),
|
||||
"/media/queue",
|
||||
"post",
|
||||
);
|
||||
const next = vi.fn();
|
||||
|
||||
await handler?.(
|
||||
{
|
||||
body: { source: "https://example.com/song.mp3", mode: "video" },
|
||||
} as Request,
|
||||
{ json: vi.fn() } as unknown as Response,
|
||||
next,
|
||||
);
|
||||
|
||||
expect(next.mock.calls[0][0]).toMatchObject({
|
||||
code: "INVALID_MEDIA_MODE",
|
||||
statusCode: 400,
|
||||
});
|
||||
});
|
||||
|
||||
it("passes missing source errors to Express", async () => {
|
||||
const controller = {
|
||||
getState: vi.fn(),
|
||||
|
||||
Reference in New Issue
Block a user