import TheMovieDb from '@server/api/themoviedb'; import { IssueStatus, IssueType, IssueTypeName } from '@server/constants/issue'; import { MediaType } from '@server/constants/media'; import Issue from '@server/entity/Issue'; import notificationManager, { Notification } from '@server/lib/notifications'; import { Permission } from '@server/lib/permissions'; import logger from '@server/logger'; import { sortBy } from 'lodash'; import type { EntitySubscriberInterface, InsertEvent, UpdateEvent, } from 'typeorm'; import { EventSubscriber } from 'typeorm'; @EventSubscriber() export class IssueSubscriber implements EntitySubscriberInterface { public listenTo(): typeof Issue { return Issue; } private async sendIssueNotification(entity: Issue, type: Notification) { let title: string; let image: string; const tmdb = new TheMovieDb(); try { if (entity.media.mediaType === MediaType.MOVIE) { const movie = await tmdb.getMovie({ movieId: entity.media.tmdbId }); title = `${movie.title}${ movie.release_date ? ` (${movie.release_date.slice(0, 4)})` : '' }`; image = `https://image.tmdb.org/t/p/w600_and_h900_bestv2${movie.poster_path}`; } else { const tvshow = await tmdb.getTvShow({ tvId: entity.media.tmdbId }); title = `${tvshow.name}${ tvshow.first_air_date ? ` (${tvshow.first_air_date.slice(0, 4)})` : '' }`; image = `https://image.tmdb.org/t/p/w600_and_h900_bestv2${tvshow.poster_path}`; } const [firstComment] = sortBy(entity.comments, 'id'); const extra: { name: string; value: string }[] = []; if (entity.media.mediaType === MediaType.TV && entity.problemSeason > 0) { extra.push({ name: 'Affected Season', value: entity.problemSeason.toString(), }); if (entity.problemEpisode > 0) { extra.push({ name: 'Affected Episode', value: entity.problemEpisode.toString(), }); } } notificationManager.sendNotification(type, { event: type === Notification.ISSUE_CREATED ? `New ${ entity.issueType !== IssueType.OTHER ? `${IssueTypeName[entity.issueType]} ` : '' }Issue Reported` : type === Notification.ISSUE_RESOLVED ? `${ entity.issueType !== IssueType.OTHER ? `${IssueTypeName[entity.issueType]} ` : '' }Issue Resolved` : `${ entity.issueType !== IssueType.OTHER ? `${IssueTypeName[entity.issueType]} ` : '' }Issue Reopened`, subject: title, message: firstComment.message, issue: entity, media: entity.media, image, extra, notifyAdmin: true, notifySystem: true, notifyUser: !entity.createdBy.hasPermission(Permission.MANAGE_ISSUES) && entity.modifiedBy?.id !== entity.createdBy.id && (type === Notification.ISSUE_RESOLVED || type === Notification.ISSUE_REOPENED) ? entity.createdBy : undefined, }); } catch (e) { logger.error('Something went wrong sending issue notification(s)', { label: 'Notifications', errorMessage: e.message, issueId: entity.id, }); } } public afterInsert(event: InsertEvent): void { if (!event.entity) { return; } this.sendIssueNotification(event.entity, Notification.ISSUE_CREATED); } public beforeUpdate(event: UpdateEvent): void { if (!event.entity) { return; } if ( event.entity.status === IssueStatus.RESOLVED && event.databaseEntity.status !== IssueStatus.RESOLVED ) { this.sendIssueNotification( event.entity as Issue, Notification.ISSUE_RESOLVED ); } else if ( event.entity.status === IssueStatus.OPEN && event.databaseEntity.status !== IssueStatus.OPEN ) { this.sendIssueNotification( event.entity as Issue, Notification.ISSUE_REOPENED ); } } }