From d356958c6faacfb26458180204e08140406a5a6d Mon Sep 17 00:00:00 2001 From: slav-fyi Date: Mon, 6 Oct 2025 21:45:54 +1100 Subject: [PATCH] refactor(xtream): allow fallback extension when user profile is undefined --- src/xtream.ts | 12 +++++++---- tests/main.test.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/xtream.ts b/src/xtream.ts index 9073380..778b617 100644 --- a/src/xtream.ts +++ b/src/xtream.ts @@ -268,11 +268,15 @@ export class Xtream { } // Check if requested format is allowed for the user - // Fall back to first allowed format if not - if (!this.userProfile!.allowed_output_formats.includes(stream.extension)) { - format = this.userProfile!.allowed_output_formats[0]; + // If not, fall back to first allowed format for the user + // Otherwise, if no allowed formats are specified, fall back to requested format + // Some services may return empty objects for userProfile + if ( + !this.userProfile?.allowed_output_formats.includes(stream.extension) + ) { + format = + this.userProfile?.allowed_output_formats[0] ?? stream.extension; } - return `${this.baseUrl}/live/${this.#username}/${this.#password}/${stream.streamId}.${format}`; } diff --git a/tests/main.test.ts b/tests/main.test.ts index 8659448..636053b 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -264,6 +264,56 @@ describe('Xtream API', () => { expect(url).toBe('http://example.com/timeshift/test/password/60/2021-01-01:00-00/1.ts'); }); + + test('Falls back to requested extension when userProfile has empty allowed_output_formats', async () => { + const xtream = new Xtream({ + url: 'http://example.com', + username: 'test', + password: 'password', + }); + + // Set userProfile with empty allowed_output_formats array + xtream.userProfile = { + username: 'test', + password: 'password', + message: '', + auth: 1, + status: 'Active', + exp_date: '1767542400', + is_trial: '0', + active_cons: 0, + created_at: '1735084800', + max_connections: '5', + allowed_output_formats: [], + }; + + const url = xtream.generateStreamUrl({ + type: 'channel', + streamId: '123', + extension: 'm3u8', + }); + + expect(url).toBe('http://example.com/live/test/password/123.m3u8'); + }); + + test('Falls back to requested extension when userProfile is undefined', () => { + const xtream = new Xtream({ + url: 'http://example.com', + username: 'test', + password: 'password', + }); + + // Ensure userProfile is undefined + xtream.userProfile = undefined; + + const url = xtream.generateStreamUrl({ + type: 'channel', + streamId: '456', + extension: 'ts', + }); + + expect(url).toBe('http://example.com/live/test/password/456.ts'); + }); }); describe('JSON:API serializer', () => {