diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c867d81580..2e7aac76de 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 16c8312867..59fb12dc28 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 ffcd0e4d91..4894f4dbd3 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 9044cd3e30..121add1339 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 38cdf179e8..701af96c7e 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 0000000000..3eee2ff36f --- /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); +}