From d5e9541010f806f1cf55fc4cccca8687d7e0adf5 Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Thu, 9 Feb 2023 03:14:48 +0100 Subject: [PATCH 01/18] Fix too long URLs on getItems with many ids --- CONTRIBUTORS.md | 1 + src/components/notifications/notifications.js | 5 +- src/components/playback/playbackmanager.js | 5 +- src/plugins/chromecastPlayer/plugin.js | 5 +- src/plugins/syncPlay/core/Helper.js | 5 +- .../jellyfin-apiclient/getItemsHelper.ts | 63 +++++++++++++++++++ 6 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/utils/jellyfin-apiclient/getItemsHelper.ts diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c867d8158..2e7aac76d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -59,6 +59,7 @@ - [Vankerkom](https://github.com/vankerkom) - [edvwib](https://github.com/edvwib) - [Rob Farraher](https://github.com/farraherbg) + - [Merlin Sievers](https://github.com/dann-merlin) # Emby Contributors diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 16c831286..59fb12dc2 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -2,6 +2,7 @@ import serverNotifications from '../../scripts/serverNotifications'; import { playbackManager } from '../playback/playbackmanager'; import Events from '../../utils/events.ts'; import globalize from '../../scripts/globalize'; +import { getItems } from '../../utils/jellyfin-apiclient/getItemsHelper.ts'; import NotificationIcon from './notificationicon.png'; @@ -130,7 +131,9 @@ function onLibraryChanged(data, apiClient) { newItems.length = 12; } - apiClient.getItems(apiClient.getCurrentUserId(), { + // call getItems from getItemsHelper instead of apiClient.getItems() + // to split up into multiple requests if necessary (URL might get too long) + getItems(apiClient, apiClient.getCurrentUserId(), { Recursive: true, Limit: 3, diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index ffcd0e4d9..4894f4dbd 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -12,6 +12,7 @@ import Screenfull from 'screenfull'; import ServerConnections from '../ServerConnections'; import alert from '../alert'; import { includesAny } from '../../utils/container.ts'; +import { getItems } from '../../utils/jellyfin-apiclient/getItemsHelper.ts'; const UNLIMITED_ITEMS = -1; @@ -126,7 +127,9 @@ function getItemsForPlayback(serverId, query) { query.EnableTotalRecordCount = false; query.CollapseBoxSetItems = false; - return apiClient.getItems(apiClient.getCurrentUserId(), query); + // call getItems from getItemsHelper instead of apiClient.getItems() + // to split up into multiple requests if necessary (URL might get too long) + return getItems(apiClient, apiClient.getCurrentUserId(), query); } } diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index 9044cd3e3..121add133 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -6,6 +6,7 @@ import castSenderApiLoader from './castSenderApi'; import ServerConnections from '../../components/ServerConnections'; import alert from '../../components/alert'; import Events from '../../utils/events.ts'; +import { getItems } from '../../utils/jellyfin-apiclient/getItemsHelper.ts'; // Based on https://github.com/googlecast/CastVideos-chrome/blob/master/CastVideos.js @@ -481,7 +482,9 @@ function getItemsForPlayback(apiClient, query) { query.ExcludeLocationTypes = 'Virtual'; query.EnableTotalRecordCount = false; - return apiClient.getItems(userId, query); + // call getItems from getItemsHelper instead of apiClient.getItems() + // to split up into multiple requests if necessary (URL might get too long) + return getItems(apiClient, userId, query); } } diff --git a/src/plugins/syncPlay/core/Helper.js b/src/plugins/syncPlay/core/Helper.js index 38cdf179e..701af96c7 100644 --- a/src/plugins/syncPlay/core/Helper.js +++ b/src/plugins/syncPlay/core/Helper.js @@ -4,6 +4,7 @@ */ import Events from '../../../utils/events.ts'; +import { getItems } from '../../../utils/jellyfin-apiclient/getItemsHelper.ts'; /** * Constants @@ -88,7 +89,9 @@ export function getItemsForPlayback(apiClient, query) { query.EnableTotalRecordCount = false; query.CollapseBoxSetItems = false; - return apiClient.getItems(apiClient.getCurrentUserId(), query); + // call getItems from getItemsHelper instead of apiClient.getItems() + // to split up into multiple requests if necessary (URL might get too long) + return getItems(apiClient, apiClient.getCurrentUserId(), query); } } diff --git a/src/utils/jellyfin-apiclient/getItemsHelper.ts b/src/utils/jellyfin-apiclient/getItemsHelper.ts new file mode 100644 index 000000000..3eee2ff36 --- /dev/null +++ b/src/utils/jellyfin-apiclient/getItemsHelper.ts @@ -0,0 +1,63 @@ +import type {BaseItemDtoQueryResult} from '@jellyfin/sdk/lib/generated-client'; +import {ApiClient} from 'jellyfin-apiclient'; + +const idsPerItemRequestLimit = 25; + +function getItemsSplit(apiClient: ApiClient, userId: string, options: any) { + const optionsTemplate = {...options}; + const ids = options.Ids.split(','); + const results = []; + + let nextI; + for (let i = 0; i < ids.length && i < options.Limit; i = nextI) { + nextI = i + idsPerItemRequestLimit; + if (nextI > options.Limit) { + nextI = options.Limit; + } + const idsSlice = ids.slice(i, nextI); + console.log(idsSlice); + optionsTemplate.Ids = idsSlice.join(','); + results.push(apiClient.getItems(userId, optionsTemplate)); + } + + return results; +} + +function mergeResults(results: BaseItemDtoQueryResult[]) { + const merged: BaseItemDtoQueryResult = {}; + merged.Items = []; + merged.TotalRecordCount = 0; + merged.StartIndex = 0; + + for (const result of results) { + if (result.Items == null) { + console.log(`Retrieved Items array is invalid: ${result.Items}`); + continue; + } + if (result.TotalRecordCount == null) { + console.log(`Retrieved TotalRecordCount is invalid: ${ + result.TotalRecordCount}`); + continue; + } + if (result.StartIndex == null) { + console.log( + `Retrieved StartIndex is invalid: ${result.StartIndex}`); + continue; + } + merged.Items = merged.Items.concat(result.Items); + merged.TotalRecordCount += result.TotalRecordCount; + merged.StartIndex = Math.min(merged.StartIndex, result.StartIndex); + } + return merged; +} + +export function getItems(apiClient: ApiClient, userId: string, options?: any): + Promise { + if (options.Ids === undefined || + options.Ids.split(',').ength <= idsPerItemRequestLimit) { + return apiClient.getItems(apiClient.getCurrentUserId(), options); + } + const results = getItemsSplit(apiClient, userId, options); + + return Promise.all(results).then(mergeResults); +} From aede0fa8caaeece2d44272e299ada75b1415a9c8 Mon Sep 17 00:00:00 2001 From: dann-merlin <55287004+dann-merlin@users.noreply.github.com> Date: Tue, 7 Mar 2023 23:49:40 +0000 Subject: [PATCH 02/18] Fixing type in getItems.ts Co-authored-by: Bill Thornton --- src/utils/jellyfin-apiclient/getItemsHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/jellyfin-apiclient/getItemsHelper.ts b/src/utils/jellyfin-apiclient/getItemsHelper.ts index 3eee2ff36..bef989d34 100644 --- a/src/utils/jellyfin-apiclient/getItemsHelper.ts +++ b/src/utils/jellyfin-apiclient/getItemsHelper.ts @@ -54,7 +54,7 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { export function getItems(apiClient: ApiClient, userId: string, options?: any): Promise { if (options.Ids === undefined || - options.Ids.split(',').ength <= idsPerItemRequestLimit) { + options.Ids.split(',').length <= idsPerItemRequestLimit) { return apiClient.getItems(apiClient.getCurrentUserId(), options); } const results = getItemsSplit(apiClient, userId, options); From baa4f0a29d01bd2dcc706f6f43a830d6d029f26f Mon Sep 17 00:00:00 2001 From: dann-merlin <55287004+dann-merlin@users.noreply.github.com> Date: Tue, 7 Mar 2023 23:52:34 +0000 Subject: [PATCH 03/18] Improve log message for invalid TotalRecordCount in getItems Co-authored-by: Bill Thornton --- src/utils/jellyfin-apiclient/getItemsHelper.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItemsHelper.ts b/src/utils/jellyfin-apiclient/getItemsHelper.ts index bef989d34..b783abb5a 100644 --- a/src/utils/jellyfin-apiclient/getItemsHelper.ts +++ b/src/utils/jellyfin-apiclient/getItemsHelper.ts @@ -35,8 +35,7 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { continue; } if (result.TotalRecordCount == null) { - console.log(`Retrieved TotalRecordCount is invalid: ${ - result.TotalRecordCount}`); + console.log('[getItems] Retrieved TotalRecordCount is invalid', result.TotalRecordCount); continue; } if (result.StartIndex == null) { From e6937240553c07405078acda30b09d6f2bc503ae Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 8 Mar 2023 00:53:26 +0100 Subject: [PATCH 04/18] Remove leftover debugging log in getItems --- src/utils/jellyfin-apiclient/getItemsHelper.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/jellyfin-apiclient/getItemsHelper.ts b/src/utils/jellyfin-apiclient/getItemsHelper.ts index b783abb5a..0f19ac8ae 100644 --- a/src/utils/jellyfin-apiclient/getItemsHelper.ts +++ b/src/utils/jellyfin-apiclient/getItemsHelper.ts @@ -15,7 +15,6 @@ function getItemsSplit(apiClient: ApiClient, userId: string, options: any) { nextI = options.Limit; } const idsSlice = ids.slice(i, nextI); - console.log(idsSlice); optionsTemplate.Ids = idsSlice.join(','); results.push(apiClient.getItems(userId, optionsTemplate)); } From 1a069b49bebc6e0e10d3c0cb144a2230155d235b Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 8 Mar 2023 01:29:14 +0100 Subject: [PATCH 05/18] Rename getItemsHelper.ts to getItems.ts --- src/components/notifications/notifications.js | 4 ++-- src/components/playback/playbackmanager.js | 4 ++-- src/plugins/chromecastPlayer/plugin.js | 4 ++-- src/plugins/syncPlay/core/Helper.js | 4 ++-- .../jellyfin-apiclient/{getItemsHelper.ts => getItems.ts} | 0 5 files changed, 8 insertions(+), 8 deletions(-) rename src/utils/jellyfin-apiclient/{getItemsHelper.ts => getItems.ts} (100%) diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 59fb12dc2..13c4ffd8d 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -2,7 +2,7 @@ import serverNotifications from '../../scripts/serverNotifications'; import { playbackManager } from '../playback/playbackmanager'; import Events from '../../utils/events.ts'; import globalize from '../../scripts/globalize'; -import { getItems } from '../../utils/jellyfin-apiclient/getItemsHelper.ts'; +import { getItems } from '../../utils/jellyfin-apiclient/getItems.ts'; import NotificationIcon from './notificationicon.png'; @@ -131,7 +131,7 @@ function onLibraryChanged(data, apiClient) { newItems.length = 12; } - // call getItems from getItemsHelper instead of apiClient.getItems() + // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() // to split up into multiple requests if necessary (URL might get too long) getItems(apiClient, apiClient.getCurrentUserId(), { diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 4894f4dbd..6088ad821 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -12,7 +12,7 @@ import Screenfull from 'screenfull'; import ServerConnections from '../ServerConnections'; import alert from '../alert'; import { includesAny } from '../../utils/container.ts'; -import { getItems } from '../../utils/jellyfin-apiclient/getItemsHelper.ts'; +import { getItems } from '../../utils/jellyfin-apiclient/getItems.ts'; const UNLIMITED_ITEMS = -1; @@ -127,7 +127,7 @@ function getItemsForPlayback(serverId, query) { query.EnableTotalRecordCount = false; query.CollapseBoxSetItems = false; - // call getItems from getItemsHelper instead of apiClient.getItems() + // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() // to split up into multiple requests if necessary (URL might get too long) return getItems(apiClient, apiClient.getCurrentUserId(), query); } diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index 121add133..ebc682cbb 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -6,7 +6,7 @@ import castSenderApiLoader from './castSenderApi'; import ServerConnections from '../../components/ServerConnections'; import alert from '../../components/alert'; import Events from '../../utils/events.ts'; -import { getItems } from '../../utils/jellyfin-apiclient/getItemsHelper.ts'; +import { getItems } from '../../utils/jellyfin-apiclient/getItems.ts'; // Based on https://github.com/googlecast/CastVideos-chrome/blob/master/CastVideos.js @@ -482,7 +482,7 @@ function getItemsForPlayback(apiClient, query) { query.ExcludeLocationTypes = 'Virtual'; query.EnableTotalRecordCount = false; - // call getItems from getItemsHelper instead of apiClient.getItems() + // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() // to split up into multiple requests if necessary (URL might get too long) return getItems(apiClient, userId, query); } diff --git a/src/plugins/syncPlay/core/Helper.js b/src/plugins/syncPlay/core/Helper.js index 701af96c7..364217e98 100644 --- a/src/plugins/syncPlay/core/Helper.js +++ b/src/plugins/syncPlay/core/Helper.js @@ -4,7 +4,7 @@ */ import Events from '../../../utils/events.ts'; -import { getItems } from '../../../utils/jellyfin-apiclient/getItemsHelper.ts'; +import { getItems } from '../../../utils/jellyfin-apiclient/getItems.ts'; /** * Constants @@ -89,7 +89,7 @@ export function getItemsForPlayback(apiClient, query) { query.EnableTotalRecordCount = false; query.CollapseBoxSetItems = false; - // call getItems from getItemsHelper instead of apiClient.getItems() + // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() // to split up into multiple requests if necessary (URL might get too long) return getItems(apiClient, apiClient.getCurrentUserId(), query); } diff --git a/src/utils/jellyfin-apiclient/getItemsHelper.ts b/src/utils/jellyfin-apiclient/getItems.ts similarity index 100% rename from src/utils/jellyfin-apiclient/getItemsHelper.ts rename to src/utils/jellyfin-apiclient/getItems.ts From 96febf9f254aad9571600d61498638a39202262c Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 29 Mar 2023 06:29:37 +0200 Subject: [PATCH 06/18] Rename file level constant to conform naming conv. Renames idsPerItemRequestLimit to ITEMS_PER_REQUEST_LIMIT as it as a file level constant. --- src/utils/jellyfin-apiclient/getItems.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 0f19ac8ae..c17d9a50c 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -1,7 +1,7 @@ import type {BaseItemDtoQueryResult} from '@jellyfin/sdk/lib/generated-client'; import {ApiClient} from 'jellyfin-apiclient'; -const idsPerItemRequestLimit = 25; +const ITEMS_PER_REQUEST_LIMIT = 25; function getItemsSplit(apiClient: ApiClient, userId: string, options: any) { const optionsTemplate = {...options}; @@ -10,7 +10,7 @@ function getItemsSplit(apiClient: ApiClient, userId: string, options: any) { let nextI; for (let i = 0; i < ids.length && i < options.Limit; i = nextI) { - nextI = i + idsPerItemRequestLimit; + nextI = i + ITEMS_PER_REQUEST_LIMIT; if (nextI > options.Limit) { nextI = options.Limit; } @@ -52,7 +52,7 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { export function getItems(apiClient: ApiClient, userId: string, options?: any): Promise { if (options.Ids === undefined || - options.Ids.split(',').length <= idsPerItemRequestLimit) { + options.Ids.split(',').length <= ITEMS_PER_REQUEST_LIMIT) { return apiClient.getItems(apiClient.getCurrentUserId(), options); } const results = getItemsSplit(apiClient, userId, options); From 117dd153945c76ed3ebb9c249d698b76da6bffb2 Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 29 Mar 2023 06:50:15 +0200 Subject: [PATCH 07/18] Rename variable in getItemsSplit loop --- src/utils/jellyfin-apiclient/getItems.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index c17d9a50c..3b394fbbd 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -8,13 +8,13 @@ function getItemsSplit(apiClient: ApiClient, userId: string, options: any) { const ids = options.Ids.split(','); const results = []; - let nextI; - for (let i = 0; i < ids.length && i < options.Limit; i = nextI) { - nextI = i + ITEMS_PER_REQUEST_LIMIT; - if (nextI > options.Limit) { - nextI = options.Limit; + let end; + for (let start = 0; start < ids.length && start < options.Limit; start = end) { + end = start + ITEMS_PER_REQUEST_LIMIT; + if (end > options.Limit) { + end = options.Limit; } - const idsSlice = ids.slice(i, nextI); + const idsSlice = ids.slice(start, end); optionsTemplate.Ids = idsSlice.join(','); results.push(apiClient.getItems(userId, optionsTemplate)); } From eca7cc7cedb2e3e5bac2b7361b1759dd8425d1ad Mon Sep 17 00:00:00 2001 From: dann-merlin <55287004+dann-merlin@users.noreply.github.com> Date: Wed, 29 Mar 2023 04:59:20 +0000 Subject: [PATCH 08/18] Update src/utils/jellyfin-apiclient/getItems.ts Co-authored-by: Bill Thornton --- src/utils/jellyfin-apiclient/getItems.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 3b394fbbd..00c8290b2 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -23,10 +23,11 @@ function getItemsSplit(apiClient: ApiClient, userId: string, options: any) { } function mergeResults(results: BaseItemDtoQueryResult[]) { - const merged: BaseItemDtoQueryResult = {}; - merged.Items = []; - merged.TotalRecordCount = 0; - merged.StartIndex = 0; + const merged: BaseItemDtoQueryResult = { + Items: [], + TotalRecordCount: 0, + StartIndex: 0 + }; for (const result of results) { if (result.Items == null) { From da4f890adfdb2338b78ed4856fb3703c9ff2514d Mon Sep 17 00:00:00 2001 From: dann-merlin <55287004+dann-merlin@users.noreply.github.com> Date: Wed, 29 Mar 2023 05:00:04 +0000 Subject: [PATCH 09/18] Update src/utils/jellyfin-apiclient/getItems.ts Co-authored-by: Bill Thornton --- src/utils/jellyfin-apiclient/getItems.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 00c8290b2..4323f64ee 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -31,7 +31,7 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { for (const result of results) { if (result.Items == null) { - console.log(`Retrieved Items array is invalid: ${result.Items}`); + console.log('[getItems] Retrieved Items array is invalid', result.Items); continue; } if (result.TotalRecordCount == null) { From 5932decce5d8b9fcd1ba0897d1df3ee737322f06 Mon Sep 17 00:00:00 2001 From: dann-merlin <55287004+dann-merlin@users.noreply.github.com> Date: Wed, 29 Mar 2023 05:00:40 +0000 Subject: [PATCH 10/18] Update src/utils/jellyfin-apiclient/getItems.ts Co-authored-by: Bill Thornton --- src/utils/jellyfin-apiclient/getItems.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 4323f64ee..ddbebb5b7 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -39,8 +39,7 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { continue; } if (result.StartIndex == null) { - console.log( - `Retrieved StartIndex is invalid: ${result.StartIndex}`); + console.log('[getItems] Retrieved StartIndex is invalid', result.StartIndex); continue; } merged.Items = merged.Items.concat(result.Items); From 2154ea64adb5535933929632d2527daa5c0dd368 Mon Sep 17 00:00:00 2001 From: dann-merlin <55287004+dann-merlin@users.noreply.github.com> Date: Wed, 29 Mar 2023 05:02:23 +0000 Subject: [PATCH 11/18] Update src/utils/jellyfin-apiclient/getItems.ts Co-authored-by: Bill Thornton --- src/utils/jellyfin-apiclient/getItems.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index ddbebb5b7..ebdeeca8d 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -49,8 +49,7 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { return merged; } -export function getItems(apiClient: ApiClient, userId: string, options?: any): - Promise { +export function getItems(apiClient: ApiClient, userId: string, options?: any) { if (options.Ids === undefined || options.Ids.split(',').length <= ITEMS_PER_REQUEST_LIMIT) { return apiClient.getItems(apiClient.getCurrentUserId(), options); From 762feba94c696665f84910b96ceaf0f396dc53ea Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 29 Mar 2023 07:06:29 +0200 Subject: [PATCH 12/18] Use syntactic sugar to check if Ids is undefined --- src/utils/jellyfin-apiclient/getItems.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index ebdeeca8d..b08fefe8d 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -50,8 +50,7 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { } export function getItems(apiClient: ApiClient, userId: string, options?: any) { - if (options.Ids === undefined || - options.Ids.split(',').length <= ITEMS_PER_REQUEST_LIMIT) { + if (options.Ids?.split(',').length <= ITEMS_PER_REQUEST_LIMIT) { return apiClient.getItems(apiClient.getCurrentUserId(), options); } const results = getItemsSplit(apiClient, userId, options); From d8bbba2dc9be586813a414eb11fb3b2fd9946d3f Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 29 Mar 2023 07:26:22 +0200 Subject: [PATCH 13/18] Add handling of undefined cases for tsc The handled cases are never going to actually be undefined, as the affected variables are defined before. tsc however was not satisfied so these changed had to be made. --- src/utils/jellyfin-apiclient/getItems.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index b08fefe8d..c47e707cc 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -42,9 +42,9 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { console.log('[getItems] Retrieved StartIndex is invalid', result.StartIndex); continue; } - merged.Items = merged.Items.concat(result.Items); - merged.TotalRecordCount += result.TotalRecordCount; - merged.StartIndex = Math.min(merged.StartIndex, result.StartIndex); + merged.Items = merged.Items?.concat(result.Items); + merged.TotalRecordCount! += result.TotalRecordCount; + merged.StartIndex = Math.min(merged.StartIndex || 0, result.StartIndex); } return merged; } From 06c4f0f258cfb444775442cea69f6c9de63649c0 Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 29 Mar 2023 07:44:21 +0200 Subject: [PATCH 14/18] Add JSDoc comment to getItems helper In return the comments at each usage are removed. --- src/components/notifications/notifications.js | 2 -- src/components/playback/playbackmanager.js | 2 -- src/plugins/chromecastPlayer/plugin.js | 2 -- src/plugins/syncPlay/core/Helper.js | 2 -- src/utils/jellyfin-apiclient/getItems.ts | 8 ++++++++ 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 13c4ffd8d..2d11691e9 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -131,8 +131,6 @@ function onLibraryChanged(data, apiClient) { newItems.length = 12; } - // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() - // to split up into multiple requests if necessary (URL might get too long) getItems(apiClient, apiClient.getCurrentUserId(), { Recursive: true, diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 0d0434c97..14c841bea 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -128,8 +128,6 @@ function getItemsForPlayback(serverId, query) { query.EnableTotalRecordCount = false; query.CollapseBoxSetItems = false; - // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() - // to split up into multiple requests if necessary (URL might get too long) return getItems(apiClient, apiClient.getCurrentUserId(), query); } } diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index d4aca76a3..a656337d6 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -483,8 +483,6 @@ function getItemsForPlayback(apiClient, query) { query.ExcludeLocationTypes = 'Virtual'; query.EnableTotalRecordCount = false; - // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() - // to split up into multiple requests if necessary (URL might get too long) return getItems(apiClient, userId, query); } } diff --git a/src/plugins/syncPlay/core/Helper.js b/src/plugins/syncPlay/core/Helper.js index 364217e98..47f25578a 100644 --- a/src/plugins/syncPlay/core/Helper.js +++ b/src/plugins/syncPlay/core/Helper.js @@ -89,8 +89,6 @@ export function getItemsForPlayback(apiClient, query) { query.EnableTotalRecordCount = false; query.CollapseBoxSetItems = false; - // call getItems from jellyfin-apiclient/getItems.ts instead of apiClient.getItems() - // to split up into multiple requests if necessary (URL might get too long) return getItems(apiClient, apiClient.getCurrentUserId(), query); } } diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index c47e707cc..03f242ac0 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -49,6 +49,14 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { return merged; } +/** + * Transparently handles the call to apiClient.getItems splitting the + * call into multiple ones if the URL might get too long. + * @param apiClient The ApiClient to use + * @param userId User id to pass to actual getItems call + * @param options Options object to specify getItems option. This includes a possibly long Items list that will be split up. + * @returns A promise that resolves to the merged result of all getItems calls + */ export function getItems(apiClient: ApiClient, userId: string, options?: any) { if (options.Ids?.split(',').length <= ITEMS_PER_REQUEST_LIMIT) { return apiClient.getItems(apiClient.getCurrentUserId(), options); From 4fe4ed2b0a245cb1a58c8d0a243f3762cae81537 Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Mon, 3 Apr 2023 14:34:57 +0200 Subject: [PATCH 15/18] Define interface for getItems options --- src/utils/jellyfin-apiclient/getItems.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 03f242ac0..1d0562f2c 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -1,18 +1,24 @@ import type {BaseItemDtoQueryResult} from '@jellyfin/sdk/lib/generated-client'; import {ApiClient} from 'jellyfin-apiclient'; +interface GetItemsRequest { + Ids?: string; + Limit?: number; +} + const ITEMS_PER_REQUEST_LIMIT = 25; -function getItemsSplit(apiClient: ApiClient, userId: string, options: any) { +function getItemsSplit(apiClient: ApiClient, userId: string, options: GetItemsRequest) { const optionsTemplate = {...options}; - const ids = options.Ids.split(','); + const ids = options.Ids!.split(','); const results = []; + const limit = options.Limit ?? Infinity; let end; - for (let start = 0; start < ids.length && start < options.Limit; start = end) { + for (let start: number = 0; start < ids.length && start < limit; start = end) { end = start + ITEMS_PER_REQUEST_LIMIT; - if (end > options.Limit) { - end = options.Limit; + if (end > limit) { + end = limit; } const idsSlice = ids.slice(start, end); optionsTemplate.Ids = idsSlice.join(','); @@ -57,8 +63,9 @@ function mergeResults(results: BaseItemDtoQueryResult[]) { * @param options Options object to specify getItems option. This includes a possibly long Items list that will be split up. * @returns A promise that resolves to the merged result of all getItems calls */ -export function getItems(apiClient: ApiClient, userId: string, options?: any) { - if (options.Ids?.split(',').length <= ITEMS_PER_REQUEST_LIMIT) { +export function getItems(apiClient: ApiClient, userId: string, options?: GetItemsRequest) { + const ids = options?.Ids?.split(','); + if (!options || !ids || ids.length <= ITEMS_PER_REQUEST_LIMIT) { return apiClient.getItems(apiClient.getCurrentUserId(), options); } const results = getItemsSplit(apiClient, userId, options); From 840fbed68a96d23a3b97fc2a5e3de3fb5f9dba12 Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Thu, 13 Apr 2023 13:15:53 +0200 Subject: [PATCH 16/18] Fix eslint errors (syntax) --- src/utils/jellyfin-apiclient/getItems.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 1d0562f2c..550d00525 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -1,5 +1,5 @@ -import type {BaseItemDtoQueryResult} from '@jellyfin/sdk/lib/generated-client'; -import {ApiClient} from 'jellyfin-apiclient'; +import type { BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client'; +import { ApiClient } from 'jellyfin-apiclient'; interface GetItemsRequest { Ids?: string; @@ -9,13 +9,13 @@ interface GetItemsRequest { const ITEMS_PER_REQUEST_LIMIT = 25; function getItemsSplit(apiClient: ApiClient, userId: string, options: GetItemsRequest) { - const optionsTemplate = {...options}; + const optionsTemplate = { ...options }; const ids = options.Ids!.split(','); const results = []; const limit = options.Limit ?? Infinity; let end; - for (let start: number = 0; start < ids.length && start < limit; start = end) { + for (let start = 0; start < ids.length && start < limit; start = end) { end = start + ITEMS_PER_REQUEST_LIMIT; if (end > limit) { end = limit; From 3629e826dff36c316a3ada759d78bd7e922ddc60 Mon Sep 17 00:00:00 2001 From: dann-merlin <55287004+dann-merlin@users.noreply.github.com> Date: Wed, 19 Apr 2023 00:43:21 +0000 Subject: [PATCH 17/18] Update src/utils/jellyfin-apiclient/getItems.ts Co-authored-by: Bill Thornton --- src/utils/jellyfin-apiclient/getItems.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 550d00525..79bdcbbca 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -10,7 +10,7 @@ const ITEMS_PER_REQUEST_LIMIT = 25; function getItemsSplit(apiClient: ApiClient, userId: string, options: GetItemsRequest) { const optionsTemplate = { ...options }; - const ids = options.Ids!.split(','); + const ids = options.Ids?.split(',') || []; const results = []; const limit = options.Limit ?? Infinity; From 012c28161546b36037c319fd001649f1afe41bf1 Mon Sep 17 00:00:00 2001 From: Merlin Danner Date: Wed, 19 Apr 2023 02:43:47 +0200 Subject: [PATCH 18/18] Bump ITEMS_PER_REQUEST_LIMIT to 40 (getItems call) --- src/utils/jellyfin-apiclient/getItems.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/jellyfin-apiclient/getItems.ts b/src/utils/jellyfin-apiclient/getItems.ts index 79bdcbbca..dee681a5d 100644 --- a/src/utils/jellyfin-apiclient/getItems.ts +++ b/src/utils/jellyfin-apiclient/getItems.ts @@ -6,7 +6,7 @@ interface GetItemsRequest { Limit?: number; } -const ITEMS_PER_REQUEST_LIMIT = 25; +const ITEMS_PER_REQUEST_LIMIT = 40; function getItemsSplit(apiClient: ApiClient, userId: string, options: GetItemsRequest) { const optionsTemplate = { ...options };