Use sdk for item download url

This commit is contained in:
Bill Thornton
2025-12-09 18:22:13 -05:00
parent 15644cb097
commit 3e93be0292
7 changed files with 49 additions and 31 deletions

1
src/apiclient.d.ts vendored
View File

@@ -136,6 +136,7 @@ declare module 'jellyfin-apiclient' {
getInstantMixFromItem(itemId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getIntros(itemId: string): Promise<BaseItemDtoQueryResult>;
getItemCounts(userId?: string): Promise<ItemCounts>;
/** @deprecated This function returns a URL with a legacy auth parameter.*/
getItemDownloadUrl(itemId: string): string;
getItemImageInfos(itemId: string): Promise<ImageInfo[]>;
getItems(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;

View File

@@ -1,4 +1,8 @@
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api';
import { AppFeature } from 'constants/appFeature';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import browser from '../scripts/browser';
import { copy } from '../scripts/clipboard';
@@ -12,7 +16,6 @@ import itemHelper, { canEditPlaylist } from './itemHelper';
import { playbackManager } from './playback/playbackmanager';
import toast from './toast/toast';
import * as userSettings from '../scripts/settings/userSettings';
import { AppFeature } from 'constants/appFeature';
/** Item types that support downloading all children. */
const DOWNLOAD_ALL_TYPES = [
@@ -387,6 +390,7 @@ function executeCommand(item, id, options) {
const itemId = item.Id;
const serverId = item.ServerId;
const apiClient = ServerConnections.getApiClient(serverId);
const api = toApi(apiClient);
return new Promise(function (resolve, reject) {
// eslint-disable-next-line sonarjs/max-switch-cases
@@ -411,9 +415,9 @@ function executeCommand(item, id, options) {
break;
case 'download':
import('../scripts/fileDownloader').then((fileDownloader) => {
const downloadHref = apiClient.getItemDownloadUrl(itemId);
const url = getLibraryApi(api).getDownloadUrl({ itemId });
fileDownloader.download([{
url: downloadHref,
url,
item,
itemId,
serverId,
@@ -429,9 +433,9 @@ function executeCommand(item, id, options) {
const downloads = items
.filter(i => i.CanDownload)
.map(i => {
const downloadHref = apiClient.getItemDownloadUrl(i.Id);
const url = getLibraryApi(api).getDownloadUrl({ itemId: i.Id });
return {
url: downloadHref,
url,
item: i,
itemId: i.Id,
serverId,
@@ -478,7 +482,7 @@ function executeCommand(item, id, options) {
break;
}
case 'copy-stream': {
const downloadHref = apiClient.getItemDownloadUrl(itemId);
const downloadHref = getLibraryApi(api).getDownloadUrl({ itemId });
copy(downloadHref).then(() => {
toast(globalize.translate('CopyStreamURLSuccess'));
}).catch(() => {

View File

@@ -2,9 +2,15 @@
* Image viewer component
* @module components/slideshow/slideshow
*/
import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api';
import screenfull from 'screenfull';
import { AppFeature } from 'constants/appFeature';
import dialogHelper from '../dialogHelper/dialogHelper';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import { randomInt } from 'utils/number';
import dialogHelper from '../dialogHelper/dialogHelper';
import inputManager from '../../scripts/inputManager';
import layoutManager from '../layoutManager';
import focusManager from '../focusManager';
@@ -15,8 +21,6 @@ import dom from '../../utils/dom';
import './style.scss';
import 'material-design-icons-iconfont';
import '../../elements/emby-button/paper-icon-button-light';
import screenfull from 'screenfull';
import { randomInt } from '../../utils/number.ts';
/**
* Name of transition event.
@@ -88,14 +92,15 @@ function getBackdropImageUrl(item, options, apiClient) {
* @returns {string} URL of the item's image.
*/
function getImgUrl(item, user) {
const apiClient = ServerConnections.getApiClient(item.ServerId);
const apiClient = ServerConnections.getApiClient(item);
const api = toApi(apiClient);
const imageOptions = {};
if (item.BackdropImageTags?.length) {
return getBackdropImageUrl(item, imageOptions, apiClient);
} else {
if (item.MediaType === 'Photo' && user?.Policy.EnableContentDownloading) {
return apiClient.getItemDownloadUrl(item.Id);
return getLibraryApi(api).getDownloadUrl({ itemId: item.Id });
}
imageOptions.type = 'Primary';
return getImageUrl(item, imageOptions, apiClient);

View File

@@ -1,5 +1,6 @@
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
import { PersonKind } from '@jellyfin/sdk/lib/generated-client/models/person-kind';
import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api';
import { intervalToDuration } from 'date-fns';
import DOMPurify from 'dompurify';
import escapeHtml from 'escape-html';
@@ -35,6 +36,7 @@ import { getPortraitShape, getSquareShape } from 'utils/card';
import Dashboard from 'utils/dashboard';
import Events from 'utils/events';
import { getItemBackdropImageUrl } from 'utils/jellyfin-apiclient/backdropImage';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import 'elements/emby-itemscontainer/emby-itemscontainer';
import 'elements/emby-checkbox/emby-checkbox';
@@ -2027,9 +2029,10 @@ export default function (view, params) {
}
function onDownloadClick() {
const downloadHref = getApiClient().getItemDownloadUrl(currentItem.Id);
const api = toApi(getApiClient());
const url = getLibraryApi(api).getDownloadUrl({ itemId: currentItem.Id });
download([{
url: downloadHref,
url,
item: currentItem,
itemId: currentItem.Id,
serverId: currentItem.ServerId,

View File

@@ -1,18 +1,21 @@
import 'material-design-icons-iconfont';
import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api';
import Screenfull from 'screenfull';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import browser from 'scripts/browser';
import TouchHelper from 'scripts/touchHelper';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import loading from '../../components/loading/loading';
import keyboardnavigation from '../../scripts/keyboardNavigation';
import dialogHelper from '../../components/dialogHelper/dialogHelper';
import Screenfull from 'screenfull';
import TableOfContents from './tableOfContents';
import { translateHtml } from '../../lib/globalize';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import browser from 'scripts/browser';
import * as userSettings from '../../scripts/settings/userSettings';
import TouchHelper from 'scripts/touchHelper';
import { PluginType } from '../../types/plugin.ts';
import Events from '../../utils/events.ts';
import 'material-design-icons-iconfont';
import '../../elements/emby-button/paper-icon-button-light';
import html from './template.html';
@@ -324,16 +327,14 @@ export class BookPlayer {
}
};
const serverId = item.ServerId;
const apiClient = ServerConnections.getApiClient(serverId);
if (!Screenfull.isEnabled) {
document.getElementById('btnBookplayerFullscreen').display = 'none';
}
return new Promise((resolve, reject) => {
import('epubjs').then(({ default: epubjs }) => {
const downloadHref = apiClient.getItemDownloadUrl(item.Id);
const api = toApi(ServerConnections.getApiClient(item));
const downloadHref = getLibraryApi(api).getDownloadUrl({ itemId: item.Id });
const book = epubjs(downloadHref, { openAs: 'epub' });
// We need to calculate the height of the window beforehand because using 100% is not accurate when the dialog is opening.

View File

@@ -1,9 +1,13 @@
import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api';
import { Archive } from 'libarchive.js';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import loading from '../../components/loading/loading';
import dialogHelper from '../../components/dialogHelper/dialogHelper';
import keyboardnavigation from '../../scripts/keyboardNavigation';
import { appRouter } from '../../components/router/appRouter';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import * as userSettings from '../../scripts/settings/userSettings';
import { PluginType } from '../../types/plugin.ts';
@@ -287,14 +291,12 @@ export class ComicsPlayer {
loading.show();
const serverId = item.ServerId;
const apiClient = ServerConnections.getApiClient(serverId);
Archive.init({
workerUrl: appRouter.baseUrl() + '/libraries/worker-bundle.js'
});
const downloadUrl = apiClient.getItemDownloadUrl(item.Id);
const api = toApi(ServerConnections.getApiClient(item));
const downloadUrl = getLibraryApi(api).getDownloadUrl({ itemId: item.Id });
this.archiveSource = new ArchiveSource(downloadUrl);
//eslint-disable-next-line import/no-unresolved

View File

@@ -1,3 +1,7 @@
import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import loading from '../../components/loading/loading';
import keyboardnavigation from '../../scripts/keyboardNavigation';
import dialogHelper from '../../components/dialogHelper/dialogHelper';
@@ -205,11 +209,9 @@ export class PdfPlayer {
}
};
const serverId = item.ServerId;
const apiClient = ServerConnections.getApiClient(serverId);
return import('pdfjs-dist').then(({ GlobalWorkerOptions, getDocument }) => {
const downloadHref = apiClient.getItemDownloadUrl(item.Id);
const api = toApi(ServerConnections.getApiClient(item));
const downloadHref = getLibraryApi(api).getDownloadUrl({ itemId: item.Id });
this.bindEvents();
GlobalWorkerOptions.workerSrc = appRouter.baseUrl() + '/libraries/pdf.worker.js';