diff --git a/src/series/repository/season.ts b/src/series/repository/season.ts index 88c16dd..8906044 100644 --- a/src/series/repository/season.ts +++ b/src/series/repository/season.ts @@ -24,10 +24,38 @@ export default class SeasonRepository { private mergeEpisodes = ( tmdbEpisodes: TmdbEpisode[], skyhookEpisodes: SkyhookEpisode[], - ): MergedEpisode[] => - zip(tmdbEpisodes, skyhookEpisodes).map((data) => - deepmerge(data[0], data[1]) as MergedEpisode - ); + ): MergedEpisode[] => { + const zipped = zip(tmdbEpisodes, skyhookEpisodes).map(( + [tmdbEpisode, skyhookEpisode], + ) => ({ + id: tmdbEpisode.id, + tvdbShowId: skyhookEpisode.tvdbShowId, + tvdbId: skyhookEpisode.tvdbId, + tmdbShowId: tmdbEpisode.show_id, + seasonNumber: skyhookEpisode.seasonNumber ?? tmdbEpisode.season_number, + episodeNumber: skyhookEpisode.episodeNumber ?? tmdbEpisode.episode_number, + absoluteEpisodeNumber: skyhookEpisode.absoluteEpisodeNumber, + airedBeforeSeasonNumber: skyhookEpisode.airedBeforeSeasonNumber, + airedBeforeEpisodeNumber: skyhookEpisode.airedBeforeEpisodeNumber, + airedAfterSeasonNumber: skyhookEpisode.airedAfterSeasonNumber, + airedAfterEpisodeNumber: skyhookEpisode.airedAfterEpisodeNumber, + title: skyhookEpisode.title, + airDate: skyhookEpisode.airDate ?? tmdbEpisode.air_date, + airDateUtc: skyhookEpisode.airDateUtc, + runtime: skyhookEpisode.runtime ?? tmdbEpisode.runtime ?? 0, + finaleType: skyhookEpisode.finaleType, + overview: skyhookEpisode.overview ?? tmdbEpisode.overview, + image: skyhookEpisode.image, + name: tmdbEpisode.name, + productionCode: tmdbEpisode.production_code, + stillPath: tmdbEpisode.still_path, + voteAverage: tmdbEpisode.vote_average, + voteCount: tmdbEpisode.vote_count, + crew: tmdbEpisode.crew, + guestStars: tmdbEpisode.guest_stars, + })); + return zipped; + }; private mergeSeasons = ( tmdbSeasons: TmdbSeason[], @@ -38,20 +66,17 @@ export default class SeasonRepository { .map((data) => deepmerge(data[0], data[1])) .map((mergedSeason) => ({ ...mergedSeason, - episodes: Array.isArray(mergedSeason?.episodes) - ? this.mergeEpisodes(mergedSeason!.episodes, skyhookEpisodes) + episodes: mergedSeason?.episodes + ? this.mergeEpisodes( + mergedSeason.episodes, + skyhookEpisodes.filter((episode) => + episode.seasonNumber == mergedSeason.season_number + ), + ) : [], })) as MergedSeason[]; }; - private mergeSeasonWithAnimeIds = ( - _mergedSeasons: MergedSeason[], - _relations: AnimeRelationId[], - ): MergedSeason[] => { - // find relationships between mergedSeason[x].tmdbId and relations[x].themoviedb - throw new Error('Not implemented'); - }; - getSeasons = async ( notify?: NotifyAnime, skyhook?: SkyhookShow, diff --git a/src/series/service/arm/types.ts b/src/series/service/arm/types.ts index ceb29b4..52a045d 100644 --- a/src/series/service/arm/types.ts +++ b/src/series/service/arm/types.ts @@ -1,4 +1,4 @@ -export interface AnimeRelationId { +export type AnimeRelationId = { anidb?: number; anilist?: number; animePlanet?: string; @@ -10,4 +10,4 @@ export interface AnimeRelationId { themoviedb?: number; thetvdb?: number; myanimelist?: number; -} +}; diff --git a/src/series/service/skyhook/remote/types.ts b/src/series/service/skyhook/remote/types.ts index 73c767f..4b1835d 100644 --- a/src/series/service/skyhook/remote/types.ts +++ b/src/series/service/skyhook/remote/types.ts @@ -1,9 +1,10 @@ interface ActorModel { name: string; character: string; + image?: string; } -interface EpisodeModel { +export interface EpisodeModel { tvdbShowId: number; tvdbId: number; seasonNumber: number; @@ -11,16 +12,19 @@ interface EpisodeModel { absoluteEpisodeNumber?: number; airedBeforeSeasonNumber?: number; airedBeforeEpisodeNumber?: number; + airedAfterSeasonNumber?: number; + airedAfterEpisodeNumber?: number; title?: string; airDate: Date; airDateUtc: Date; runtime?: number; + finaleType?: string | 'season'; overview?: string; image?: string; } interface ImageModel { - coverType: string | 'Banner' | 'Poster' | 'Fanart'; + coverType: string | 'Banner' | 'Poster' | 'Fanart' | 'Clearlogo'; url: string; } @@ -35,14 +39,25 @@ interface TimeOfDayModel { minutes: number; } -export interface SkyhookModel { +interface RatingModel { + count: number, + value: string +} + +interface AlternativeTitlesModel { + title: string +} + +export type SkyhookModel = { tvdbId: number; title: string; overview: string; slug: string; + originalCountry: string; originalLanguage: string; language: string; firstAired: Date; + lastAired: Date; tvMazeId: number; lastUpdated: Date; status: string; @@ -50,9 +65,11 @@ export interface SkyhookModel { timeOfDay: TimeOfDayModel; originalNetwork: string; network: string; - imdbId: string; genres: string[]; contentRating: string; + rating?: RatingModel; + alternativeTitles?: AlternativeTitlesModel; + imdbId: string; actors: ActorModel[]; images: ImageModel[]; seasons: SeasonModel[]; diff --git a/src/series/service/skyhook/transformer/index.ts b/src/series/service/skyhook/transformer/index.ts index d2df6d9..644163c 100644 --- a/src/series/service/skyhook/transformer/index.ts +++ b/src/series/service/skyhook/transformer/index.ts @@ -1,41 +1,19 @@ import { Transform } from '../../../../common/transformer/types.ts'; import { SkyhookModel } from '../remote/types.ts'; -import { Show } from './types.ts'; import { toInstant } from '../../../../common/helpers/date.ts'; +import { SkyhookShow } from '../types.ts'; -export const transform: Transform = ( +export const transform: Transform = ( sourceData, ) => ({ - tvdbId: sourceData.tvdbId, - tvMazeId: sourceData.tvMazeId, - title: sourceData.title, - overview: sourceData.overview, - slug: sourceData.slug, + ...sourceData, firstAired: toInstant(sourceData.firstAired), lastUpdated: toInstant(sourceData.lastUpdated), - status: sourceData.status, - runtime: sourceData.runtime, - originalNetwork: sourceData.originalNetwork, - network: sourceData.network, - imdbId: sourceData.imdbId, - contentRating: sourceData.contentRating, banner: sourceData.images.find((item) => item.coverType == 'Banner')?.url, poster: sourceData.images.find((item) => item.coverType == 'Poster')?.url, fanart: sourceData.images.find((item) => item.coverType == 'Fanart')?.url, seasons: sourceData.seasons.map((season) => ({ + ...season, poster: season?.images?.find((item) => item.coverType == 'Poster')?.url, - seasonNumber: season.seasonNumber, - })), - episodes: sourceData.episodes.map((episode) => ({ - tvdbShowId: episode.tvdbShowId, - tvdbId: episode.tvdbId, - seasonNumber: episode.seasonNumber, - episodeNumber: episode.episodeNumber, - absoluteEpisodeNumber: episode.absoluteEpisodeNumber, - title: episode.title, - airDate: toInstant(episode.airDateUtc), - runtime: episode.runtime, - overview: episode.overview, - image: episode.image, })), }); diff --git a/src/series/service/skyhook/transformer/types.ts b/src/series/service/skyhook/transformer/types.ts index be86329..b803ded 100644 --- a/src/series/service/skyhook/transformer/types.ts +++ b/src/series/service/skyhook/transformer/types.ts @@ -1,44 +1,9 @@ import { Instant } from '../../../../common/helpers/date.ts'; -interface Episode { - tvdbShowId: number; - tvdbId: number; - seasonNumber: number; - episodeNumber: number; - absoluteEpisodeNumber?: number; - airedBeforeSeasonNumber?: number; - airedBeforeEpisodeNumber?: number; - title?: string; - airDate: Instant; - runtime?: number; - overview?: string; - image?: string; -} - -interface Season { - seasonNumber: number; - poster?: string; - banner?: string; - fanart?: string; -} - -export interface Show { - tvdbId: number; - tvMazeId: number; - title: string; - overview: string; - slug: string; +export type Show = { firstAired: Instant; lastUpdated: Instant; - status: string; - runtime: number; - originalNetwork: string; - network: string; - imdbId: string; - contentRating: string; banner?: string; poster?: string; fanart?: string; - seasons: Season[]; - episodes: Episode[]; } diff --git a/src/series/service/skyhook/types.ts b/src/series/service/skyhook/types.ts index 191d486..1b6ce6a 100644 --- a/src/series/service/skyhook/types.ts +++ b/src/series/service/skyhook/types.ts @@ -1,44 +1,6 @@ -import { Instant } from '../../../common/helpers/date.ts'; +import { EpisodeModel, SkyhookModel } from './remote/types.ts'; +import { Show } from './transformer/types.ts'; -export interface SkyhookEpisode { - tvdbShowId: number; - tvdbId: number; - seasonNumber: number; - episodeNumber: number; - absoluteEpisodeNumber?: number; - airedBeforeSeasonNumber?: number; - airedBeforeEpisodeNumber?: number; - title?: string; - airDate: Instant; - runtime?: number; - overview?: string; - image?: string; -} +export type SkyhookEpisode = EpisodeModel -interface SkyhookSeason { - seasonNumber: number; - poster?: string; - banner?: string; - fanart?: string; -} - -export interface SkyhookShow { - tvdbId: number; - tvMazeId: number; - title: string; - overview: string; - slug: string; - firstAired: Instant; - lastUpdated: Instant; - status: string; - runtime: number; - originalNetwork: string; - network: string; - imdbId: string; - contentRating: string; - banner?: string; - poster?: string; - fanart?: string; - seasons: SkyhookSeason[]; - episodes: SkyhookEpisode[]; -} +export type SkyhookShow = Omit & Show diff --git a/src/series/service/tmdb/remote/types.ts b/src/series/service/tmdb/remote/types.ts index 441ca1b..6830190 100644 --- a/src/series/service/tmdb/remote/types.ts +++ b/src/series/service/tmdb/remote/types.ts @@ -40,7 +40,7 @@ export interface Season { overview: string; poster_path: string | null; season_number: number; - episodes: Episode | null; + episodes: Episode[] | null; images: Images | null; } @@ -89,7 +89,7 @@ interface Episode { name: string; overview: string; production_code: string; - runtime: string; + runtime: number; season_number: number; show_id: string; still_path: string; diff --git a/src/series/service/tmdb/types.ts b/src/series/service/tmdb/types.ts index 9b116e1..16fcd27 100644 --- a/src/series/service/tmdb/types.ts +++ b/src/series/service/tmdb/types.ts @@ -41,7 +41,7 @@ export interface TmdbSeason { overview: string; poster_path: string | null; season_number: number; - episodes: TmdbEpisode | null; + episodes: TmdbEpisode[] | null; images: TmdbImages | null; } @@ -90,7 +90,7 @@ export interface TmdbEpisode { name: string; overview: string; production_code: string; - runtime: string; + runtime: number; season_number: number; show_id: string; still_path: string; diff --git a/src/series/transformer/season.ts b/src/series/transformer/season.ts index de9c277..690204f 100644 --- a/src/series/transformer/season.ts +++ b/src/series/transformer/season.ts @@ -19,11 +19,11 @@ const transformImage = ( height: data.height, width: data.width, url: provider.getUrl(data, imageType), - })); + })) ?? []; const transformCrew = (crew: TmdbCrew): SeriesEpisodeCrew => ({ - job: crew.job ?? null, - department: crew.department ?? null, + job: crew.job, + department: crew.department, creditId: crew.credit_id, adult: crew.adult, id: crew.id, @@ -32,30 +32,30 @@ const transformCrew = (crew: TmdbCrew): SeriesEpisodeCrew => ({ originalName: crew.original_name, popularity: crew.popularity, image: provider.getImageUrl('original', crew.profile_path), - character: crew.character ?? null, - order: crew.order ?? null, + character: crew.character, + order: crew.order, }); const transformEpisode = (episode: MergedEpisode): SeriesEpisode => ({ + id: episode.id, tvdbShowId: episode.tvdbShowId, tvdbId: episode.tvdbId, - tmdbId: episode.id, seasonNumber: episode.seasonNumber, episodeNumber: episode.episodeNumber, - absoluteEpisodeNumber: episode.absoluteEpisodeNumber ?? null, - airedBeforeSeasonNumber: episode.airedBeforeSeasonNumber ?? null, - airedBeforeEpisodeNumber: episode.airedBeforeEpisodeNumber ?? null, - title: episode.title ?? null, - airDate: episode.airDate, - runtime: Number(episode.runtime) ?? 0, - overview: episode.overview ?? null, - image: episode.image ?? null, + absoluteEpisodeNumber: episode.absoluteEpisodeNumber, + airedBeforeSeasonNumber: episode.airedBeforeSeasonNumber, + airedBeforeEpisodeNumber: episode.airedBeforeEpisodeNumber, + airedAfterSeasonNumber: episode.airedAfterSeasonNumber, + airedAfterEpisodeNumber: episode.airedAfterEpisodeNumber, + title: episode.title, + airDate: episode.airDateUtc, + runtime: episode.runtime, + overview: episode.overview, + image: episode.image, name: episode.name, - poster: episode.still_path != null - ? provider.getImageUrl('original', episode.still_path) - : null, + poster: provider.getImageUrl('original', episode.stillPath), crew: episode.crew.map(transformCrew), - guests: episode.guest_stars.map(transformCrew), + guests: episode.guestStars.map(transformCrew), }); export const seasonTransformer = ( diff --git a/src/series/transformer/series.ts b/src/series/transformer/series.ts index 6fd08bd..bbd7807 100644 --- a/src/series/transformer/series.ts +++ b/src/series/transformer/series.ts @@ -186,20 +186,17 @@ const seriesTrailers = (notify?: NotifyAnime): SeriesTrailer[] => notify?.trailers?.map((trailer) => ({ id: trailer.id, site: trailer.site, - thumbnail: trailer.thumbnail ?? null, + thumbnail: trailer.thumbnail, })) ?? []; const seriesCover = ( notify?: NotifyAnime, jikan?: Jikan, ): SeriesCoverImage => ({ - color: notify?.poster?.color ?? null, - extraLarge: jikan?.images?.jpg?.large_image_url ?? - notify?.poster?.large ?? null, - large: jikan?.images?.jpg?.large_image_url ?? notify?.poster?.large ?? - null, - medium: jikan?.images?.jpg?.small_image_url ?? notify?.poster?.large ?? - null, + color: notify?.poster?.color, + extraLarge: jikan?.images?.jpg?.large_image_url ?? notify?.poster?.large, + large: jikan?.images?.jpg?.large_image_url ?? notify?.poster?.large, + medium: jikan?.images?.jpg?.small_image_url ?? notify?.poster?.large, }); export const seriesTransform = ( diff --git a/src/series/transformer/types.ts b/src/series/transformer/types.ts index 4d84268..c44c776 100644 --- a/src/series/transformer/types.ts +++ b/src/series/transformer/types.ts @@ -1,32 +1,17 @@ -import { Instant } from '../../common/helpers/date.ts'; +import { SkyhookEpisode } from '../service/skyhook/types.ts'; import { TmdbCrew, TmdbImages } from '../service/tmdb/types.ts'; export type MergedEpisode = { - air_date: string; - episode_number: string; id: number; name: string; - production_code: string; - season_number: number; - show_id: string; - still_path: string; - vote_average: number; - vote_count: number; + tmdbShowId: string; + productionCode: string; + stillPath: string; + voteAverage: number; + voteCount: number; crew: TmdbCrew[]; - guest_stars: TmdbCrew[]; - tvdbShowId: number; - tvdbId: number; - seasonNumber: number; - episodeNumber: number; - absoluteEpisodeNumber?: number; - airedBeforeSeasonNumber?: number; - airedBeforeEpisodeNumber?: number; - title?: string; - airDate: Instant; - runtime?: number | string; - overview?: string; - image?: string; -}; + guestStars: TmdbCrew[]; +} & SkyhookEpisode; export type MergedSeason = { episodes: MergedEpisode[]; diff --git a/src/series/types.ts b/src/series/types.ts index 3925c59..6af91be 100644 --- a/src/series/types.ts +++ b/src/series/types.ts @@ -75,36 +75,38 @@ export type SeriesImage = { }; export interface SeriesEpisodeCrew { - job: string | null; - department: string | null; + job?: string; + department?: string; creditId: string; - adult: boolean | null; + adult?: boolean; id: number; knownFor: string; name: string; originalName: string; popularity: number; - image: string | null; - character: string | null; - order: number | null; + image?: string; + character?: string; + order?: number; } export type SeriesEpisode = { + id: number; tvdbShowId: number; tvdbId: number; - tmdbId: number; seasonNumber: number; episodeNumber: number; - absoluteEpisodeNumber: number | null; - airedBeforeSeasonNumber: number | null; - airedBeforeEpisodeNumber: number | null; - title: string | null; - airDate: Instant; - runtime: number | null; - overview: string | null; - image: string | null; - name: string; - poster: string | null; + absoluteEpisodeNumber?: number; + airedBeforeSeasonNumber?: number; + airedBeforeEpisodeNumber?: number; + airedAfterSeasonNumber?: number; + airedAfterEpisodeNumber?: number; + title?: string; + airDate: Date; + runtime?: number; + overview?: string; + image?: string; + name?: string; + poster?: string; crew: SeriesEpisodeCrew[]; guests: SeriesEpisodeCrew[]; }; @@ -116,7 +118,7 @@ export type SeriesSeason = { name: string; overview: string; number: number; - cover: string | null; + cover?: string; image: SeriesImage; episodes: SeriesEpisode[]; }; @@ -124,14 +126,14 @@ export type SeriesSeason = { export type SeriesTrailer = { id: string; site: string; - thumbnail: string | null; + thumbnail?: string; }; export type SeriesCoverImage = { - extraLarge: string | null; - large: string | null; - medium: string | null; - color: string | null; + extraLarge?: string; + large?: string; + medium?: string; + color?: string; }; export interface Media {