feat: Emby support (#234)

* fix: support credential extraction from Emby

* fix: minor compatibility with emby for retrieving albums

* fix: rename credentials and save credentials type

* fix: weird issue when changing libraries

* fix: correctly map platform names in auth header

* chore: properly carry over old settings

* fix: only enable playlists on jellyfin

* fix: remove jellyfin mentions

* fix: incorporate jellyfin and emby as mentions
This commit is contained in:
Lei Nelissen
2024-07-25 23:37:00 +02:00
committed by GitHub
parent c15f8fe1fc
commit a6452f0a5e
35 changed files with 294 additions and 168 deletions

View File

@@ -36,7 +36,9 @@ export async function retrieveAlbum(id: string): Promise<Album> {
const latestAlbumsOptions = {
IncludeItemTypes: 'MusicAlbum',
Fields: 'DateCreated',
SortOrder: 'Ascending',
SortOrder: 'Descending',
SortBy: 'DateCreated',
Recursive: 'true',
};
/**
@@ -51,7 +53,8 @@ export async function retrieveRecentAlbums(numberOfAlbums = 24) {
const params = new URLSearchParams(options).toString();
// Retrieve albums
return fetchApi<Album[]>(({ user_id }) => `/Users/${user_id}/Items/Latest?${params}`);
return fetchApi<{ Items: Album[] }>(({ user_id }) => `/Users/${user_id}/Items?${params}`)
.then((d) => d.Items);
}
/**

View File

@@ -1,6 +1,17 @@
import type { AppState, Store } from '@/store';
import { Platform } from 'react-native';
import { version } from '../../../package.json';
type Credentials = AppState['settings']['jellyfin'];
type Credentials = AppState['settings']['credentials'];
/** Map the output of `Platform.OS`, so that Jellyfin can understand it. */
const deviceMap: Record<typeof Platform['OS'], string> = {
ios: 'iOS',
android: 'Android',
macos: 'macOS',
web: 'Web',
windows: 'Windows',
};
/**
* This is a convenience function that converts a set of Jellyfin credentials
@@ -10,7 +21,7 @@ type Credentials = AppState['settings']['jellyfin'];
function generateConfig(credentials: Credentials): RequestInit {
return {
headers: {
'X-Emby-Authorization': `MediaBrowser Client="", Device="", DeviceId="", Version="", Token="${credentials?.access_token}"`
'X-Emby-Authorization': `MediaBrowser Client="Fintunes", Device="${deviceMap[Platform.OS]}", DeviceId="${credentials?.device_id}", Version="${version}", Token="${credentials?.access_token}"`
}
};
}
@@ -36,7 +47,7 @@ export async function fetchApi<T>(
parseResponse = true
) {
// Retrieve the latest credentials from the Redux store
const credentials = asyncFetchStore().getState().settings.jellyfin;
const credentials = asyncFetchStore().getState().settings.credentials;
// GUARD: Check that the credentials are present
if (!credentials) {
@@ -95,7 +106,7 @@ export async function fetchApi<T>(
* Retrieve an image URL for a given ItemId
*/
export function getImage(ItemId: string): string {
const credentials = asyncFetchStore().getState().settings.jellyfin;
const credentials = asyncFetchStore().getState().settings.credentials;
const uri = encodeURI(`${credentials?.uri}/Items/${ItemId}/Images/Primary?format=jpeg`);
return uri;
}

View File

@@ -48,6 +48,7 @@ export async function sendPlaybackEvent(
ItemId: activeTrack.backendId,
CanSeek: true,
PlaybackStartTimeTicks: null,
PlaySessionId: activeTrack?.backendId || 'fintunes',
};
// Generate a config from the credentials and dispatch the request

View File

@@ -27,7 +27,7 @@ export async function retrieveAllPlaylists() {
* Retrieve all albums that are available on the Jellyfin server
*/
export async function retrievePlaylistTracks(ItemId: string) {
const credentials = asyncFetchStore().getState().settings.jellyfin;
const credentials = asyncFetchStore().getState().settings.credentials;
const singlePlaylistOptions = {
SortBy: 'IndexNumber,SortName',
UserId: credentials?.user_id || '',

View File

@@ -30,7 +30,7 @@ const baseTrackOptions: Record<string, string> = {
* Generate the track streaming url from the trackId
*/
export function generateTrackUrl(trackId: string) {
const credentials = store.getState().settings.jellyfin;
const credentials = store.getState().settings.credentials;
const trackOptions = {
...baseTrackOptions,
UserId: credentials?.user_id || '',