import LidarrAPI from '@server/api/servarr/lidarr'; import RadarrAPI from '@server/api/servarr/radarr'; import SonarrAPI from '@server/api/servarr/sonarr'; import { MediaStatus, MediaType } from '@server/constants/media'; import { getRepository } from '@server/datasource'; import type { DownloadingItem } from '@server/lib/downloadtracker'; import downloadTracker from '@server/lib/downloadtracker'; import { getSettings } from '@server/lib/settings'; import logger from '@server/logger'; import { AfterLoad, Column, CreateDateColumn, Entity, In, Index, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; import Issue from './Issue'; import { MediaRequest } from './MediaRequest'; import Season from './Season'; @Entity() class Media { public static async getRelatedMedia( tmdbIds: number | number[] = [], mbIds: string | string[] = [] ): Promise { const mediaRepository = getRepository(Media); try { let finalTmdbIds: number[] = []; if (!Array.isArray(tmdbIds)) { finalTmdbIds = [tmdbIds]; } else { finalTmdbIds = tmdbIds; } let finalMusicBrainzIds: string[] = []; if (!Array.isArray(mbIds)) { finalMusicBrainzIds = [mbIds]; } else { finalMusicBrainzIds = mbIds; } const media = await mediaRepository.find({ where: [ { tmdbId: In(finalTmdbIds) }, { mbId: In(finalMusicBrainzIds) }, ], }); return media; } catch (e) { logger.error(e.message); return []; } } public static async getMedia( id: number | string, mediaType: MediaType ): Promise { const mediaRepository = getRepository(Media); try { let media: Media | null = null; if (mediaType === MediaType.MOVIE || mediaType === MediaType.TV) { media = await mediaRepository.findOne({ where: { tmdbId: Number(id), mediaType }, relations: { requests: true, issues: true }, }); } else if (mediaType === MediaType.MUSIC) { media = await mediaRepository.findOne({ where: { mbId: String(id), mediaType }, relations: { requests: true, issues: true }, }); } return media ?? undefined; } catch (e) { logger.error(e.message); return undefined; } } @PrimaryGeneratedColumn() public id: number; @Column({ type: 'varchar' }) public mediaType: MediaType; @Column({ type: 'varchar', nullable: true }) public secondaryType?: string; @Column({ nullable: true }) @Index() public tmdbId?: number; @Column({ nullable: true }) @Index() public mbId?: string; @Column({ nullable: true }) @Index() public tvdbId?: number; @Column({ nullable: true }) @Index() public musicdbId?: number; @Column({ nullable: true }) @Index() public imdbId?: string; @Column({ type: 'int', default: MediaStatus.UNKNOWN }) public status: MediaStatus; @Column({ type: 'int', default: MediaStatus.UNKNOWN }) public status4k: MediaStatus; @OneToMany(() => MediaRequest, (request) => request.media, { cascade: true }) public requests: MediaRequest[]; @OneToMany(() => Season, (season) => season.media, { cascade: true, eager: true, }) public seasons: Season[]; @OneToMany(() => Issue, (issue) => issue.media, { cascade: true }) public issues: Issue[]; @CreateDateColumn() public createdAt: Date; @UpdateDateColumn() public updatedAt: Date; @Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' }) public lastSeasonChange: Date; @Column({ type: 'datetime', nullable: true }) public mediaAddedAt: Date; @Column({ nullable: true, type: 'int' }) public serviceId?: number | null; @Column({ nullable: true, type: 'int' }) public serviceId4k?: number | null; @Column({ nullable: true, type: 'int' }) public externalServiceId?: number | null; @Column({ nullable: true, type: 'int' }) public externalServiceId4k?: number | null; @Column({ nullable: true, type: 'varchar' }) public externalServiceSlug?: string | null; @Column({ nullable: true, type: 'varchar' }) public externalServiceSlug4k?: string | null; @Column({ nullable: true, type: 'varchar' }) public ratingKey?: string | null; @Column({ nullable: true, type: 'varchar' }) public ratingKey4k?: string | null; public serviceUrl?: string; public serviceUrl4k?: string; public downloadStatus?: DownloadingItem[] = []; public downloadStatus4k?: DownloadingItem[] = []; public plexUrl?: string; public plexUrl4k?: string; public iOSPlexUrl?: string; public iOSPlexUrl4k?: string; public tautulliUrl?: string; public tautulliUrl4k?: string; constructor(init?: Partial) { Object.assign(this, init); } @AfterLoad() public setPlexUrls(): void { const { machineId, webAppUrl } = getSettings().plex; const { externalUrl: tautulliUrl } = getSettings().tautulli; if (this.ratingKey) { this.plexUrl = `${ webAppUrl ? webAppUrl : 'https://app.plex.tv/desktop' }#!/server/${machineId}/details?key=%2Flibrary%2Fmetadata%2F${ this.ratingKey }`; this.iOSPlexUrl = `plex://preplay/?metadataKey=%2Flibrary%2Fmetadata%2F${this.ratingKey}&server=${machineId}`; if (tautulliUrl) { this.tautulliUrl = `${tautulliUrl}/info?rating_key=${this.ratingKey}`; } } if (this.ratingKey4k) { this.plexUrl4k = `${ webAppUrl ? webAppUrl : 'https://app.plex.tv/desktop' }#!/server/${machineId}/details?key=%2Flibrary%2Fmetadata%2F${ this.ratingKey4k }`; this.iOSPlexUrl4k = `plex://preplay/?metadataKey=%2Flibrary%2Fmetadata%2F${this.ratingKey4k}&server=${machineId}`; if (tautulliUrl) { this.tautulliUrl4k = `${tautulliUrl}/info?rating_key=${this.ratingKey4k}`; } } } @AfterLoad() public setServiceUrl(): void { if (this.mediaType === MediaType.MOVIE) { if (this.serviceId !== null && this.externalServiceSlug !== null) { const settings = getSettings(); const server = settings.radarr.find( (radarr) => radarr.id === this.serviceId ); if (server) { this.serviceUrl = server.externalUrl ? `${server.externalUrl}/movie/${this.externalServiceSlug}` : RadarrAPI.buildUrl(server, `/movie/${this.externalServiceSlug}`); } } if (this.serviceId4k !== null && this.externalServiceSlug4k !== null) { const settings = getSettings(); const server = settings.radarr.find( (radarr) => radarr.id === this.serviceId4k ); if (server) { this.serviceUrl4k = server.externalUrl ? `${server.externalUrl}/movie/${this.externalServiceSlug4k}` : RadarrAPI.buildUrl( server, `/movie/${this.externalServiceSlug4k}` ); } } } if (this.mediaType === MediaType.TV) { if (this.serviceId !== null && this.externalServiceSlug !== null) { const settings = getSettings(); const server = settings.sonarr.find( (sonarr) => sonarr.id === this.serviceId ); if (server) { this.serviceUrl = server.externalUrl ? `${server.externalUrl}/series/${this.externalServiceSlug}` : SonarrAPI.buildUrl(server, `/series/${this.externalServiceSlug}`); } } if (this.serviceId4k !== null && this.externalServiceSlug4k !== null) { const settings = getSettings(); const server = settings.sonarr.find( (sonarr) => sonarr.id === this.serviceId4k ); if (server) { this.serviceUrl4k = server.externalUrl ? `${server.externalUrl}/series/${this.externalServiceSlug4k}` : SonarrAPI.buildUrl( server, `/series/${this.externalServiceSlug4k}` ); } } } if (this.mediaType === MediaType.MUSIC) { if (this.serviceId !== null && this.externalServiceSlug !== null) { const settings = getSettings(); const server = settings.lidarr.find( (lidarr) => lidarr.id === this.serviceId ); if (server) { this.serviceUrl = server.externalUrl ? `${server.externalUrl}/movie/${this.externalServiceSlug}` : LidarrAPI.buildUrl(server, `/movie/${this.externalServiceSlug}`); } } } } @AfterLoad() public getDownloadingItem(): void { if (this.mediaType === MediaType.MOVIE) { if ( this.externalServiceId !== undefined && this.externalServiceId !== null && this.serviceId !== undefined && this.serviceId !== null ) { this.downloadStatus = downloadTracker.getMovieProgress( this.serviceId, this.externalServiceId ); } if ( this.externalServiceId4k !== undefined && this.externalServiceId4k !== null && this.serviceId4k !== undefined && this.serviceId4k !== null ) { this.downloadStatus4k = downloadTracker.getMovieProgress( this.serviceId4k, this.externalServiceId4k ); } } if (this.mediaType === MediaType.TV) { if ( this.externalServiceId !== undefined && this.externalServiceId !== null && this.serviceId !== undefined && this.serviceId !== null ) { this.downloadStatus = downloadTracker.getSeriesProgress( this.serviceId, this.externalServiceId ); } if ( this.externalServiceId4k !== undefined && this.externalServiceId4k !== null && this.serviceId4k !== undefined && this.serviceId4k !== null ) { this.downloadStatus4k = downloadTracker.getSeriesProgress( this.serviceId4k, this.externalServiceId4k ); } } if (this.mediaType === MediaType.MUSIC) { if ( this.externalServiceId !== undefined && this.externalServiceId !== null && this.serviceId !== undefined && this.serviceId !== null ) { this.downloadStatus = downloadTracker.getMusicProgress( this.serviceId, this.externalServiceId ); } } } } export default Media;