Skip to content

Commit

Permalink
Merge pull request #690 from 3flex/remove-ItemQuery
Browse files Browse the repository at this point in the history
Remove ItemQuery interface
  • Loading branch information
nielsvanvelzen authored Nov 10, 2024
2 parents 47a0b6b + 64af602 commit 6d2cf98
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 103 deletions.
8 changes: 2 additions & 6 deletions src/components/maincontroller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,11 +565,7 @@ export async function translateItems(
): Promise<void> {
const playNow = method != 'PlayNext' && method != 'PlayLast';

const result = await translateRequestedItems(
data.userId,
options.items,
playNow
);
const result = await translateRequestedItems(options.items, playNow);

if (result.Items) {
options.items = result.Items;
Expand Down Expand Up @@ -616,7 +612,7 @@ export async function shuffle(
options: PlayRequest,
item: BaseItemDto
): Promise<void> {
const result = await getShuffleItems(data.userId, item);
const result = await getShuffleItems(item);

options.items = result.Items ?? [];
PlaybackManager.playFromOptions(data.options);
Expand Down
137 changes: 62 additions & 75 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import type {
InstantMixApiGetInstantMixFromAlbumRequest,
InstantMixApiGetInstantMixFromPlaylistRequest,
InstantMixApiGetInstantMixFromArtistsRequest,
InstantMixApiGetInstantMixFromSongRequest
InstantMixApiGetInstantMixFromSongRequest,
ItemFields,
ItemsApiGetItemsRequest
} from '@jellyfin/sdk/lib/generated-client';
import { getInstantMixApi, getTvShowsApi } from '@jellyfin/sdk/lib/utils/api';
import {
getInstantMixApi,
getItemsApi,
getTvShowsApi
} from '@jellyfin/sdk/lib/utils/api';
import { JellyfinApi } from './components/jellyfinApi';
import { PlaybackManager, PlaybackState } from './components/playbackManager';
import { BusMessage, ItemQuery } from './types/global';
import { BusMessage } from './types/global';

type InstantMixApiRequest =
| InstantMixApiGetInstantMixFromAlbumRequest
Expand Down Expand Up @@ -464,7 +470,7 @@ export function getStreamByIndex(
}

// defined for use in the 3 next functions
const requiredItemFields = 'MediaSources,Chapters';
const requiredItemFields: ItemFields[] = ['MediaSources', 'Chapters'];

/**
* Get a random selection of items given one item,
Expand All @@ -473,42 +479,45 @@ const requiredItemFields = 'MediaSources,Chapters';
* of the provided one.
*
* It's used only in maincomponents.shuffle.
*
* TODO: JellyfinApi.userId should be fine for this.
* @param userId - User ID to look up items with
* @param item - Parent item of shuffle search
* @returns items for the queue
*/
export function getShuffleItems(
userId: string,
item: BaseItemDto
): Promise<BaseItemDtoQueryResult> {
const query: ItemQuery = {
Fields: requiredItemFields,
Filters: 'IsNotFolder',
Limit: 50,
Recursive: true,
SortBy: 'Random',
UserId: userId
let query: ItemsApiGetItemsRequest = {
fields: requiredItemFields,
filters: ['IsNotFolder'],
limit: 50,
recursive: true,
sortBy: ['Random']
};

if (item.Type == 'MusicArtist') {
query.MediaTypes = 'Audio';
query.ArtistIds = item.Id;
query = {
...query,
artistIds: item.Id ? [item.Id] : undefined,
mediaTypes: ['Audio']
};
} else if (item.Type == 'MusicGenre') {
query.MediaTypes = 'Audio';
query.Genres = item.Name ?? undefined;
query = {
...query,
genres: item.Name ? [item.Name] : undefined,
mediaTypes: ['Audio']
};
} else {
query.ParentId = item.Id;
query = {
...query,
parentId: item.Id
};
}

return getItemsForPlayback(userId, query);
return getItemsForPlayback(query);
}

/**
* Get an "Instant Mix" given an item, which can be a
* music artist, genre, album, playlist
*
* @param item - Parent item of the search
* @returns items for the queue
*/
Expand Down Expand Up @@ -549,39 +558,20 @@ export async function getInstantMixItems(

/**
* Get items to be played back
* @param userId - user for the search
* @param query - specification on what to search for
* @returns items to be played back
*/
export async function getItemsForPlayback(
userId: string,
query: ItemQuery
query: ItemsApiGetItemsRequest
): Promise<BaseItemDtoQueryResult> {
query.UserId = userId;
query.Limit = query.Limit ?? 100;
query.Fields = requiredItemFields;
query.ExcludeLocationTypes = 'Virtual';

if (query.Ids && query.Ids.split(',').length == 1) {
const item = await JellyfinApi.authAjaxUser(
`Items/${query.Ids.split(',')[0]}`,
{
dataType: 'json',
type: 'GET'
}
);
const response = await getItemsApi(JellyfinApi.jellyfinApi).getItems({
...query,
excludeLocationTypes: ['Virtual'],
fields: requiredItemFields,
limit: query.limit ?? 100
});

return {
Items: [item],
TotalRecordCount: 1
};
} else {
return JellyfinApi.authAjaxUser('Items', {
dataType: 'json',
query: query,
type: 'GET'
});
}
return response.data;
}

/**
Expand Down Expand Up @@ -613,46 +603,44 @@ export function getUser(): Promise<UserDto> {
/**
* Process a list of items for playback
* by resolving things like folders to playable items.
* @param userId - userId to use
* @param items - items to resolve
* @param smart - If enabled it will try to find the next episode given the current one,
* if the connected user has enabled that in their settings
* @returns Promise for search result containing items to play
*/
export async function translateRequestedItems(
userId: string,
items: BaseItemDto[],
smart = false
): Promise<BaseItemDtoQueryResult> {
const firstItem = items[0];

if (firstItem.Type == 'Playlist') {
return await getItemsForPlayback(userId, {
ParentId: firstItem.Id
return await getItemsForPlayback({
parentId: firstItem.Id
});
} else if (firstItem.Type == 'MusicArtist') {
return await getItemsForPlayback(userId, {
ArtistIds: firstItem.Id,
Filters: 'IsNotFolder',
MediaTypes: 'Audio',
Recursive: true,
SortBy: 'SortName'
return await getItemsForPlayback({
artistIds: firstItem.Id ? [firstItem.Id] : undefined,
filters: ['IsNotFolder'],
mediaTypes: ['Audio'],
recursive: true,
sortBy: ['SortName']
});
} else if (firstItem.Type == 'MusicGenre') {
return await getItemsForPlayback(userId, {
Filters: 'IsNotFolder',
Genres: firstItem.Name ?? undefined,
MediaTypes: 'Audio',
Recursive: true,
SortBy: 'SortName'
return await getItemsForPlayback({
filters: ['IsNotFolder'],
genres: firstItem.Name ? [firstItem.Name] : undefined,
mediaTypes: ['Audio'],
recursive: true,
sortBy: ['SortName']
});
} else if (firstItem.IsFolder) {
return await getItemsForPlayback(userId, {
Filters: 'IsNotFolder',
MediaTypes: 'Audio,Video',
ParentId: firstItem.Id,
Recursive: true,
SortBy: 'SortName'
return await getItemsForPlayback({
filters: ['IsNotFolder'],
mediaTypes: ['Audio', 'Video'],
parentId: firstItem.Id,
recursive: true,
sortBy: ['SortName']
});
} else if (smart && firstItem.Type == 'Episode' && items.length == 1) {
const user = await getUser();
Expand All @@ -663,8 +651,8 @@ export async function translateRequestedItems(
};
}

const result = await getItemsForPlayback(userId, {
Ids: firstItem.Id
const result = await getItemsForPlayback({
ids: firstItem.Id ? [firstItem.Id] : undefined
});

if (!result.Items || result.Items.length < 1) {
Expand All @@ -679,8 +667,7 @@ export async function translateRequestedItems(

const episodesResult = await getEpisodesForPlayback({
isMissing: false,
seriesId: episode.SeriesId,
userId: userId
seriesId: episode.SeriesId
});

let foundItem = false;
Expand Down
22 changes: 0 additions & 22 deletions src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,6 @@ import { TextTrackEdgeType } from 'chromecast-caf-receiver/cast.framework.messag

export type Dictionary<T> = Record<string, T>;

// Jellyfin Server
// Why doesn't the API have a type for this?
/* Combined item query.
* Valid for item endpoints */
// TODO: API has an endpoint for this. Replace on https://github.com/jellyfin/jellyfin-chromecast/pull/109
export interface ItemQuery {
UserId?: string;
Limit?: number;
Fields?: string;
Filters?: string;
Recursive?: boolean;
ExcludeLocationTypes?: string;
Ids?: string;
SortBy?: string;
IsVirtualUnaired?: boolean;
IsMissing?: boolean;
ParentId?: string;
MediaTypes?: string;
Genres?: string;
ArtistIds?: string;
}

// Messagebus message
export interface BusMessage {
type: string;
Expand Down

0 comments on commit 6d2cf98

Please sign in to comment.