Merge pull request #660 from sel10ut/bugfix/jellyfin-multiple-sessions

(Jellyfin) Allow multiple sessions from the same user with different instances
This commit is contained in:
Jeff 2024-07-03 14:49:41 -07:00 committed by GitHub
commit 42bcc4190c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 38 additions and 38 deletions

View file

@ -6,8 +6,9 @@ import qs from 'qs';
import { ServerListItem } from '/@/renderer/api/types'; import { ServerListItem } from '/@/renderer/api/types';
import omitBy from 'lodash/omitBy'; import omitBy from 'lodash/omitBy';
import { z } from 'zod'; import { z } from 'zod';
import { authenticationFailure } from '/@/renderer/api/utils'; import { authenticationFailure, getClientType } from '/@/renderer/api/utils';
import i18n from '/@/i18n/i18n'; import i18n from '/@/i18n/i18n';
import packageJson from '../../../../package.json';
const c = initContract(); const c = initContract();
@ -24,9 +25,6 @@ export const contract = c.router({
}, },
authenticate: { authenticate: {
body: jfType._parameters.authenticate, body: jfType._parameters.authenticate,
headers: z.object({
'X-Emby-Authorization': z.string(),
}),
method: 'POST', method: 'POST',
path: 'users/authenticatebyname', path: 'users/authenticatebyname',
responses: { 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: { export const jfApiClient = (args: {
server: ServerListItem | null; server: ServerListItem | null;
signal?: AbortSignal; signal?: AbortSignal;
@ -359,7 +363,9 @@ export const jfApiClient = (args: {
data: body, data: body,
headers: { headers: {
...headers, ...headers,
...(token && { 'X-MediaBrowser-Token': token }), ...(token
? { Authorization: createAuthHeader().concat(`, Token="${token}"`) }
: { Authorization: createAuthHeader() }),
}, },
method: method as Method, method: method as Method,
params, params,

View file

@ -57,10 +57,8 @@ import {
import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api'; import { jfApiClient } from '/@/renderer/api/jellyfin/jellyfin-api';
import { jfNormalize } from './jellyfin-normalize'; import { jfNormalize } from './jellyfin-normalize';
import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types'; import { jfType } from '/@/renderer/api/jellyfin/jellyfin-types';
import packageJson from '../../../../package.json';
import { z } from 'zod'; import { z } from 'zod';
import { JFSongListSort, JFSortOrder } from '/@/renderer/api/jellyfin.types'; import { JFSongListSort, JFSortOrder } from '/@/renderer/api/jellyfin.types';
import isElectron from 'is-electron';
import { ServerFeature } from '/@/renderer/api/features-types'; import { ServerFeature } from '/@/renderer/api/features-types';
import { VersionInfo, getFeatures } from '/@/renderer/api/utils'; import { VersionInfo, getFeatures } from '/@/renderer/api/utils';
import chunk from 'lodash/chunk'; import chunk from 'lodash/chunk';
@ -69,31 +67,6 @@ const formatCommaDelimitedString = (value: string[]) => {
return value.join(','); 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 ( const authenticate = async (
url: string, url: string,
body: { body: {
@ -108,11 +81,6 @@ const authenticate = async (
Pw: body.password, Pw: body.password,
Username: body.username, 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) { if (res.status !== 200) {

View file

@ -30,7 +30,7 @@ const getStreamUrl = (args: {
`?userId=${server?.userId}` + `?userId=${server?.userId}` +
`&deviceId=${deviceId}` + `&deviceId=${deviceId}` +
'&audioCodec=aac' + '&audioCodec=aac' +
`&api_key=${server?.credential}` + `&apiKey=${server?.credential}` +
`&playSessionId=${deviceId}` + `&playSessionId=${deviceId}` +
'&container=opus,mp3,aac,m4a,m4b,flac,wav,ogg' + '&container=opus,mp3,aac,m4a,m4b,flac,wav,ogg' +
'&transcodingContainer=ts' + '&transcodingContainer=ts' +

View file

@ -1,4 +1,5 @@
import { AxiosHeaders } from 'axios'; import { AxiosHeaders } from 'axios';
import isElectron from 'is-electron';
import semverCoerce from 'semver/functions/coerce'; import semverCoerce from 'semver/functions/coerce';
import semverGte from 'semver/functions/gte'; import semverGte from 'semver/functions/gte';
import { z } from 'zod'; import { z } from 'zod';
@ -99,4 +100,29 @@ export const getFeatures = (
return features; 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 = ' · '; export const SEPARATOR_STRING = ' · ';