feat(api): plex Sync (Movies)

Also adds winston logging
This commit is contained in:
sct
2020-09-27 14:05:32 +00:00
parent 5a43ec5405
commit 1be8b18361
19 changed files with 656 additions and 23 deletions

View File

@@ -1,8 +1,49 @@
import NodePlexAPI from 'plex-api';
import { getSettings } from '../lib/settings';
export interface PlexLibraryItem {
ratingKey: string;
title: string;
guid: string;
type: 'movie' | 'show';
}
interface PlexLibraryResponse {
MediaContainer: {
Metadata: PlexLibraryItem[];
};
}
export interface PlexLibrary {
type: 'show' | 'movie';
key: string;
title: string;
}
interface PlexLibrariesResponse {
MediaContainer: {
Directory: PlexLibrary[];
};
}
export interface PlexMetadata {
ratingKey: string;
guid: string;
type: 'movie' | 'show';
title: string;
Guid: {
id: string;
}[];
}
interface PlexMetadataResponse {
MediaContainer: {
Metadata: PlexMetadata[];
};
}
class PlexAPI {
private plexClient: typeof NodePlexAPI;
private plexClient: NodePlexAPI;
constructor({ plexToken }: { plexToken?: string }) {
const settings = getSettings();
@@ -13,7 +54,7 @@ class PlexAPI {
token: plexToken,
authenticator: {
authenticate: (
_plexApi: typeof PlexAPI,
_plexApi,
cb: (err?: string, token?: string) => void
) => {
if (!plexToken) {
@@ -34,6 +75,36 @@ class PlexAPI {
public async getStatus() {
return await this.plexClient.query('/');
}
public async getLibraries(): Promise<PlexLibrary[]> {
const response = await this.plexClient.query<PlexLibrariesResponse>(
'/library/sections'
);
return response.MediaContainer.Directory;
}
public async getLibraryContents(id: string): Promise<PlexLibraryItem[]> {
const response = await this.plexClient.query<PlexLibraryResponse>(
`/library/sections/${id}/all`
);
return response.MediaContainer.Metadata;
}
public async getMetadata(key: string): Promise<PlexMetadata> {
const response = await this.plexClient.query<PlexMetadataResponse>(
`/library/metadata/${key}`
);
return response.MediaContainer.Metadata[0];
}
public async getRecentlyAdded() {
const response = await this.plexClient.query('/library/recentlyAdded');
return response;
}
}
export default PlexAPI;

View File

@@ -1,6 +1,7 @@
import axios, { AxiosInstance } from 'axios';
import xml2js from 'xml2js';
import { getSettings } from '../lib/settings';
import logger from '../logger';
interface PlexAccountResponse {
user: PlexUser;
@@ -79,9 +80,9 @@ class PlexTvAPI {
return account.data.user;
} catch (e) {
console.error(
'Something broke when getting account from plex.tv',
e.message
logger.error(
`Something went wrong getting the account from plex.tv: ${e.message}`,
{ label: 'Plex.tv API' }
);
throw new Error('Invalid auth token');
}
@@ -124,7 +125,7 @@ class PlexTvAPI {
(server) => server.$.machineIdentifier === settings.plex.machineId
);
} catch (e) {
console.log(`Error checking user access: ${e.message}`);
logger.error(`Error checking user access: ${e.message}`);
return false;
}
}

View File

@@ -100,6 +100,11 @@ interface TmdbSearchTvResponse extends TmdbPaginatedResponse {
results: TmdbTvResult[];
}
interface TmdbExternalIdResponse {
movie_results: TmdbMovieResult[];
tv_results: TmdbTvResult[];
}
export interface TmdbCreditCast {
cast_id: number;
character: string;
@@ -549,6 +554,70 @@ class TheMovieDb {
throw new Error(`[TMDB] Failed to fetch all trending: ${e.message}`);
}
};
public async getByExternalId({
externalId,
type,
language = 'en-US',
}:
| {
externalId: string;
type: 'imdb';
language?: string;
}
| {
externalId: number;
type: 'tvdb';
language?: string;
}): Promise<TmdbExternalIdResponse> {
try {
const response = await this.axios.get<TmdbExternalIdResponse>(
`/find/${externalId}`,
{
params: {
external_source: type === 'imdb' ? 'imdb_id' : 'tvdb_id',
language,
},
}
);
return response.data;
} catch (e) {
throw new Error(`[TMDB] Failed to find by external ID: ${e.message}`);
}
}
public async getMovieByImdbId({
imdbId,
language = 'en-US',
}: {
imdbId: string;
language?: string;
}): Promise<TmdbMovieDetails> {
try {
const extResponse = await this.getByExternalId({
externalId: imdbId,
type: 'imdb',
});
if (extResponse.movie_results[0]) {
const movie = await this.getMovie({
movieId: extResponse.movie_results[0].id,
language,
});
return movie;
}
throw new Error(
'[TMDB] Failed to find a title with the provided IMDB id'
);
} catch (e) {
throw new Error(
`[TMDB] Failed to get movie by external imdb ID: ${e.message}`
);
}
}
}
export default TheMovieDb;