Add JellyfinClient

This commit is contained in:
2026-08-12 21:04:47 +02:00
parent ef037d25fe
commit 9683d65a1f
3 changed files with 179 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import { ApiClient } from '../../../core/http/ApiClient';
import type { Movie } from '../../models';
import { ItemsEndpoint } from './endpoints/ItemsEndpoint';
export class JellyfinClient extends ApiClient {
private readonly endpoint = new ItemsEndpoint();
constructor(
baseUrl: string,
private readonly apiKey: string,
private readonly userId: string
) {
super(baseUrl);
}
protected buildHeaders(): Record<string, string> {
return {
...super.buildHeaders(),
Authorization: `MediaBrowser Token="${this.apiKey}"`,
};
}
getFavoriteMovies(): Promise<Movie[]> {
return this.request(this.endpoint, {
userId: this.userId,
query: {
IncludeItemTypes: 'Movie',
Recursive: 'true',
IsFavorite: 'true',
Fields: 'ProviderIds,Genres,CommunityRating,UserData',
},
});
}
getRecentlyWatched(): Promise<Movie[]> {
return this.request(this.endpoint, {
userId: this.userId,
query: {
IncludeItemTypes: 'Movie',
Recursive: 'true',
Filters: 'IsPlayed',
SortBy: 'DatePlayed',
SortOrder: 'Descending',
Limit: '50',
Fields: 'ProviderIds,Genres,CommunityRating,UserData',
},
});
}
getAllMovies(): Promise<Movie[]> {
return this.request(this.endpoint, {
userId: this.userId,
query: {
IncludeItemTypes: 'Movie',
Recursive: 'true',
Fields: 'ProviderIds',
Limit: '10000',
},
});
}
}

View File

@@ -0,0 +1,46 @@
import { Endpoint, type HttpMethod } from '../../../../core/http/Endpoint';
import type { Movie } from '../../../models';
interface JellyfinItem {
Name: string;
ProductionYear: number;
ProviderIds: Record<string, string>;
Genres: string[];
CommunityRating: number;
UserData: { IsFavorite: boolean; PlayCount: number };
}
interface JellyfinItemsResponse {
Items: JellyfinItem[];
}
export interface ItemsParams {
userId: string;
query: Record<string, string>;
}
export class ItemsEndpoint extends Endpoint<Movie[], ItemsParams> {
readonly method: HttpMethod = 'GET';
path(params: ItemsParams): string {
return `/Users/${params.userId}/Items`;
}
query(params: ItemsParams): Record<string, string> {
return params.query;
}
parseResponse(json: unknown): Movie[] {
const response = json as JellyfinItemsResponse;
return response.Items.map((item) => ({
name: item.Name,
year: item.ProductionYear,
imdbId: item.ProviderIds?.Imdb ?? '',
tmdbId: item.ProviderIds?.Tmdb ?? '',
genres: item.Genres ?? [],
communityRating: item.CommunityRating ?? 0,
isFavorite: item.UserData?.IsFavorite ?? false,
playCount: item.UserData?.PlayCount ?? 0,
}));
}
}