import * as fileType from 'file-type' ; import { inject , injectable } from 'inversify' ; import * as path from 'path' ; import * as apid from '../../../../api' ; import IRecordedDB from '../../db/IRecordedDB' ; import IVideoFileDB from '../../db/IVideoFileDB' ; import IConfiguration from '../../IConfiguration' ; import IIPCClient from '../../ipc/IIPCClient' ; import IApiUtil from '../IApiUtil' ; import IPlayList from '../IPlayList' ; import IVideoApiModel , { VideoFilePathInfo } from './IVideoApiModel' ; import IVideoUtil from './IVideoUtil' ; @ injectable ( ) export default class VideoApiModel implements IVideoApiModel { private configuration : IConfiguration ; private videoFileDB : IVideoFileDB ; private recordedDB : IRecordedDB ; private apiUtil : IApiUtil ; private videoUtil : IVideoUtil ; private ipc : IIPCClient ; constructor ( @ inject ( 'IConfiguration' ) configuration , @ inject ( 'IVideoFileDB' ) videoFileDB , @ inject ( 'IRecordedDB' ) recordedDB , @ inject ( 'IApiUtil' ) apiUtil , @ inject ( 'IVideoUtil' ) videoUtil , @ inject ( 'IIPCClient' ) ipc ) { this . configuration = configuration ; this . videoFileDB = videoFileDB ; this . recordedDB = recordedDB ; this . apiUtil = apiUtil ; this . videoUtil = videoUtil ; this . ipc = ipc ; } param videoFileId return public async getFullFilePath ( videoFileId ) { const fullPath = await this . videoUtil . getFullFilePathFromId ( videoFileId ) ; return fullPath === null ? null : { path : fullPath , mime : await this . createMime ( fullPath ) , } ; } param filePath return private async createMime ( filePath ) { const mime = await fileType . fromFile ( filePath ) ; if ( typeof mime !== 'undefined' ) { return mime . mime ; } switch ( path . extname ( filePath ) ) { case '.m2ts' : case '.ts' : return 'video/mp2t' ; default : throw new Error ( 'MimeTypeError' ) ; } } param host param isSecure param videoFileId return public async getM3u8 ( host , isSecure , videoFileId ) { const video = await this . videoFileDB . findId ( videoFileId ) ; if ( video === null || typeof video . recordedId === 'undefined' ) { return null ; } const recorded = await this . recordedDB . findId ( video ?. recordedId ) ; if ( recorded === null ) { return null ; } return { name : encodeURIComponent ( path . basename ( video . filePath ) + '.m3u8' ) , playList : this . apiUtil . createM3U8PlayListStr ( { host : host , isSecure : isSecure , name : recorded . name , duration : Math . floor ( recorded . duration / 1000 ) , baseUrl : `/api/videos/${ videoFileId }` , } ) , } ; } param videoFileId return public async deleteVideoFile ( videoFileId ) { await this . ipc . recorded . deleteVideoFile ( videoFileId ) ; } param videoFileId return public async getDuration ( videoFileId ) { const filePath = await this . videoUtil . getFullFilePathFromId ( videoFileId ) ; if ( filePath === null ) { throw new Error ( 'VideoFileIsUndefined' ) ; } const videoInfo = await this . videoUtil . getInfo ( filePath ) ; return videoInfo . duration ; } public async sendToKodi ( host , isSecure , kodiName , videoFileId ) { host = this . apiUtil . getHost ( host ) ; const config = this . configuration . getConfig ( ) ; if ( typeof config . kodiHosts === 'undefined' ) { throw new Error ( 'KodiHostsIsUndefined' ) ; } const kodi = config . kodiHosts . find ( k => { return k . name === kodiName ; } ) ; if ( typeof kodi === 'undefined' ) { throw new Error ( 'KodiHostIsUndefined' ) ; } const videoFile = await this . videoFileDB . findId ( videoFileId ) ; if ( videoFile === null ) { throw new Error ( 'VideoFileIsUndefined' ) ; } const source = `${ isSecure ? 'https' : 'http' }://${ host }/api/videos/${ videoFileId }` ; return this . apiUtil . sendToKodi ( source , kodi ) ; } }