diff --git a/src/renderer/api/jellyfin/jellyfin-api.ts b/src/renderer/api/jellyfin/jellyfin-api.ts index 5dbae8a74..f29a01c55 100644 --- a/src/renderer/api/jellyfin/jellyfin-api.ts +++ b/src/renderer/api/jellyfin/jellyfin-api.ts @@ -6,8 +6,9 @@ import qs from 'qs'; import { ServerListItem } from '/@/renderer/api/types'; import omitBy from 'lodash/omitBy'; import { z } from 'zod'; -import { authenticationFailure } from '/@/renderer/api/utils'; +import { authenticationFailure, getClientType } from '/@/renderer/api/utils'; import i18n from '/@/i18n/i18n'; +import packageJson from '../../../../package.json'; const c = initContract(); @@ -24,9 +25,6 @@ export const contract = c.router({ }, authenticate: { body: jfType._parameters.authenticate, - headers: z.object({ - 'X-Emby-Authorization': z.string(), - }), method: 'POST', path: 'users/authenticatebyname', responses: { @@ -333,6 +331,12 @@ const parsePath = (fullPath: string) => { }; }; +export const createAuthHeader = (): string => { + return `MediaBrowser Client="Feishin", Device="${getClientType()}", DeviceId="${ + useAuthStore.getState().deviceId + }", Version="${packageJson.version}"`; +}; + export const jfApiClient = (args: { server: ServerListItem | null; signal?: AbortSignal; @@ -359,7 +363,9 @@ export const jfApiClient = (args: { data: body, headers: { ...headers, - ...(token && { 'X-MediaBrowser-Token': token }), + ...(token + ? { Authorization: createAuthHeader().concat(`, Token="${token}"`) } + : { Authorization: createAuthHeader() }), }, method: method as Method, params, diff --git a/src/renderer/api/jellyfin/jellyfin-controller.ts b/src/renderer/api/jellyfin/jellyfin-controller.ts index ff07ebc5f..2b9081aa3 100644 --- a/src/renderer/api/jellyfin/jellyfin-controller.ts +++ b/src/renderer/api/jellyfin/jellyfin-controller.ts @@ -57,10 +57,8 @@ import { import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api'; import { jfNormalize } from './jellyfin-normalize'; import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types'; -import packageJson from '../../../../package.json'; import { z } from 'zod'; import { JFSongListSort, JFSortOrder } from '/@/renderer/api/jellyfin.types'; -import isElectron from 'is-electron'; import { ServerFeature } from '/@/renderer/api/features-types'; import { VersionInfo, getFeatures } from '/@/renderer/api/utils'; import chunk from 'lodash/chunk'; @@ -69,31 +67,6 @@ const formatCommaDelimitedString = (value: string[]) => { return value.join(','); }; -function getHostname(): string { - if (isElectron()) { - return 'Desktop Client'; - } - const agent = navigator.userAgent; - switch (true) { - case agent.toLowerCase().indexOf('edge') > -1: - return 'Microsoft Edge'; - case agent.toLowerCase().indexOf('edg/') > -1: - return 'Edge Chromium'; // Match also / to avoid matching for the older Edge - case agent.toLowerCase().indexOf('opr') > -1: - return 'Opera'; - case agent.toLowerCase().indexOf('chrome') > -1: - return 'Chrome'; - case agent.toLowerCase().indexOf('trident') > -1: - return 'Internet Explorer'; - case agent.toLowerCase().indexOf('firefox') > -1: - return 'Firefox'; - case agent.toLowerCase().indexOf('safari') > -1: - return 'Safari'; - default: - return 'PC'; - } -} - const authenticate = async ( url: string, body: { @@ -108,11 +81,6 @@ const authenticate = async ( Pw: body.password, Username: body.username, }, - headers: { - 'x-emby-authorization': `MediaBrowser Client="Feishin", Device="${getHostname()}", DeviceId="Feishin-${getHostname()}-${encodeURIComponent( - body.username, - )}", Version="${packageJson.version}"`, - }, }); if (res.status !== 200) { diff --git a/src/renderer/api/jellyfin/jellyfin-normalize.ts b/src/renderer/api/jellyfin/jellyfin-normalize.ts index a17eaa76e..e1ae98134 100644 --- a/src/renderer/api/jellyfin/jellyfin-normalize.ts +++ b/src/renderer/api/jellyfin/jellyfin-normalize.ts @@ -30,7 +30,7 @@ const getStreamUrl = (args: { `?userId=${server?.userId}` + `&deviceId=${deviceId}` + '&audioCodec=aac' + - `&api_key=${server?.credential}` + + `&apiKey=${server?.credential}` + `&playSessionId=${deviceId}` + '&container=opus,mp3,aac,m4a,m4b,flac,wav,ogg' + '&transcodingContainer=ts' + diff --git a/src/renderer/api/utils.ts b/src/renderer/api/utils.ts index 3034d5c4f..314185ae9 100644 --- a/src/renderer/api/utils.ts +++ b/src/renderer/api/utils.ts @@ -1,4 +1,5 @@ import { AxiosHeaders } from 'axios'; +import isElectron from 'is-electron'; import semverCoerce from 'semver/functions/coerce'; import semverGte from 'semver/functions/gte'; import { z } from 'zod'; @@ -99,4 +100,29 @@ export const getFeatures = ( return features; }; +export const getClientType = (): string => { + if (isElectron()) { + return 'Desktop Client'; + } + const agent = navigator.userAgent; + switch (true) { + case agent.toLowerCase().indexOf('edge') > -1: + return 'Microsoft Edge'; + case agent.toLowerCase().indexOf('edg/') > -1: + return 'Edge Chromium'; // Match also / to avoid matching for the older Edge + case agent.toLowerCase().indexOf('opr') > -1: + return 'Opera'; + case agent.toLowerCase().indexOf('chrome') > -1: + return 'Chrome'; + case agent.toLowerCase().indexOf('trident') > -1: + return 'Internet Explorer'; + case agent.toLowerCase().indexOf('firefox') > -1: + return 'Firefox'; + case agent.toLowerCase().indexOf('safari') > -1: + return 'Safari'; + default: + return 'PC'; + } +}; + export const SEPARATOR_STRING = ' ยท ';