1 line
No EOL
19 KiB
JavaScript
1 line
No EOL
19 KiB
JavaScript
import{itemRepository,userActionRepository}from"./../common/servicelocator.js";import LocalAssetManager from"./../localdatabase/localassetmanager.js";let MaxBackdrops=1;function processDownloadStatus(apiClient,options){return console.log("[mediasync] Begin processDownloadStatus"),LocalAssetManager.resyncTransfers().then(function(){return itemRepository.getLibraryItemsBySyncStatus(apiClient.serverId(),["transferring","queued"]).then(function(items){console.log("[mediasync] Begin processDownloadStatus getLibraryItemsBySyncStatus completed");let p=Promise.resolve(),cnt=0;return items.forEach(function(item){p=p.then(function(){return reportTransfer(apiClient,item)}),cnt++}),p.then(function(){return console.log("[mediasync] Exit processDownloadStatus. Items reported: "+cnt.toString()),Promise.resolve()})})})}function reportTransfer(apiClient,item){return LocalAssetManager.getItemFileSize(item.LocalPath).then(function(size){return 0<size?apiClient.reportSyncJobItemTransferred(item.SyncJobItemId).then(function(){return item.SyncStatus="synced",console.log("[mediasync] reportSyncJobItemTransferred called for "+item.LocalPath),itemRepository.updateLibraryItem(item.ServerId,item.Id,item).then(function(){return downloadParentItems(apiClient,item.Item)})},function(error){return console.error("[mediasync] Mediasync error on reportSyncJobItemTransferred",error),item.SyncStatus="error",itemRepository.updateLibraryItem(item.ServerId,item.Id,item)}):LocalAssetManager.isDownloadFileInQueue(item.LocalPath).then(function(result){return result?Promise.resolve():(console.log("[mediasync] reportTransfer: Size is 0 and download no longer in queue. Setting item as failed."),item.SyncStatus="error",itemRepository.updateLibraryItem(item.ServerId,item.Id,item))})},function(error){return console.error("[mediasync] reportTransfer: error on getItemFileSize. Deleting item.",error),LocalAssetManager.removeLocalItem(item).then(function(){return console.log("[mediasync] reportTransfer: Item deleted."),Promise.resolve()},function(err2){return console.log("[mediasync] reportTransfer: Failed to delete item.",err2),Promise.resolve()})})}function mapToId(userAction){return userAction.Id}function reportOfflineActions(apiClient){return console.log("[mediasync] Begin reportOfflineActions"),userActionRepository.getByServerId(apiClient.serverId()).then(function(actions){return actions.length?apiClient.reportOfflineActions(actions).then(function(){return userActionRepository.deleteUserActions(actions.map(mapToId)).then(function(){return console.log("[mediasync] Exit reportOfflineActions (actions reported and deleted.)"),Promise.resolve()})},function(err){return console.error("[mediasync] error on apiClient.reportOfflineActions: "+err.toString()),userActionRepository.deleteUserActions(actions.map(mapToId))}):(console.log("[mediasync] Exit reportOfflineActions (no actions)"),Promise.resolve())})}function syncData(apiClient){console.log("[mediasync] Begin syncData");return itemRepository.getLibraryItemsBySyncStatus(apiClient.serverId(),["synced","error"]).then(function(items){items={TargetId:apiClient.deviceId(),LocalItemIds:items.map(function(xitem){return xitem.ItemId})};return apiClient.syncData(items).then(function(result){return afterSyncData(apiClient,result).then(function(){return console.log("[mediasync] Exit syncData"),Promise.resolve()},function(err){return console.error("[mediasync] Error in syncData: "+err.toString()),Promise.resolve()})})})}function filterDistinct(value,index,self){return self.indexOf(value)===index}function removeObsoleteContainerItems(serverId){return itemRepository.getAllLibraryItems(serverId).then(function(items){var seriesItems=items.filter(function(item){return"series"===(item.Item.Type||"").toLowerCase()}),seasonItems=items.filter(function(item){return"season"===(item.Item.Type||"").toLowerCase()}),albumItems=items.filter(function(item){item=(item.Item.Type||"").toLowerCase();return"musicalbum"===item||"photoalbum"===item});let requiredSeriesIds=items.filter(function(item){return"episode"===(item.Item.Type||"").toLowerCase()}).map(function(item2){return item2.Item.SeriesId}).filter(filterDistinct),requiredSeasonIds=items.filter(function(item){return"episode"===(item.Item.Type||"").toLowerCase()}).map(function(item2){return item2.Item.SeasonId}).filter(filterDistinct),requiredAlbumIds=items.filter(function(item){item=(item.Item.Type||"").toLowerCase();return"audio"===item||"photo"===item}).map(function(item2){return item2.Item.AlbumId}).filter(filterDistinct),obsoleteItems=[],p=(seriesItems.forEach(function(item){requiredSeriesIds.indexOf(item.Item.Id)<0&&obsoleteItems.push(item)}),seasonItems.forEach(function(item){requiredSeasonIds.indexOf(item.Item.Id)<0&&obsoleteItems.push(item)}),albumItems.forEach(function(item){requiredAlbumIds.indexOf(item.Item.Id)<0&&obsoleteItems.push(item)}),Promise.resolve());return obsoleteItems.forEach(function(item){p=p.then(function(){return itemRepository.deleteLibraryItem(item.ServerId,item.ItemId)})}),p})}function afterSyncData(apiClient,syncDataResult){console.log("[mediasync] Begin afterSyncData");let p=Promise.resolve();return syncDataResult.ItemIdsToRemove&&0<syncDataResult.ItemIdsToRemove.length&&syncDataResult.ItemIdsToRemove.forEach(function(itemId){p=p.then(function(){return removeLocalItem(itemId,apiClient.serverId())})}),(p=p.then(function(){return console.log("[mediasync] Begin removeObsoleteContainerItems"),removeObsoleteContainerItems(apiClient.serverId())})).then(function(){return console.log("[mediasync] Exit afterSyncData"),Promise.resolve()})}function removeLocalItem(itemId,serverId){return console.log("[mediasync] Begin removeLocalItem"),itemRepository.getLibraryItem(serverId,itemId).then(function(item){return item?LocalAssetManager.removeLocalItem(item):Promise.resolve()},function(err2){return console.error("[mediasync] removeLocalItem: Failed: ",err2),Promise.resolve()})}function getNewMedia(apiClient,downloadCount){return console.log("[mediasync] Begin getNewMedia"),apiClient.getReadySyncItems(apiClient.deviceId()).then(function(jobItems){console.log("[mediasync] getReadySyncItems returned "+jobItems.length+" items");let p=Promise.resolve(),currentCount=downloadCount;return jobItems.forEach(function(jobItem){currentCount++<=10&&(p=p.then(function(){return getNewItem(jobItem,apiClient)}))}),p.then(function(){return console.log("[mediasync] Exit getNewMedia"),Promise.resolve()})},function(err){return console.error("[mediasync] getReadySyncItems: Failed: ",err),Promise.resolve()})}function afterMediaDownloaded(apiClient,jobItem,localItem){return console.log("[mediasync] Begin afterMediaDownloaded"),getImages(apiClient,jobItem,localItem).then(function(){return getSubtitles(apiClient,jobItem,localItem)})}function createLocalItem(libraryItem,jobItem){console.log("[mediasync] Begin createLocalItem");libraryItem={Item:libraryItem,ItemId:libraryItem.Id,ServerId:libraryItem.ServerId,Id:libraryItem.Id};return jobItem&&(libraryItem.SyncJobItemId=jobItem.SyncJobItemId),console.log("[mediasync] End createLocalItem"),libraryItem}function getNewItem(jobItem,apiClient){console.log("[mediasync] Begin getNewItem");let libraryItem=jobItem.Item;return itemRepository.getLibraryItem(libraryItem.ServerId,libraryItem.Id).then(function(existingItem){if(existingItem&&("queued"===existingItem.SyncStatus||"transferring"===existingItem.SyncStatus||"synced"===existingItem.SyncStatus)&&(console.log("[mediasync] getNewItem: getLibraryItem found existing item"),LocalAssetManager.enableBackgroundCompletion()))return Promise.resolve();libraryItem.CanDelete=!0,libraryItem.CanDownload=!1,libraryItem.SupportsSync=!1,libraryItem.People=[],clearChapterImages(libraryItem),libraryItem.Studios=[],libraryItem.SpecialFeatureCount=null,libraryItem.LocalTrailerCount=null,libraryItem.RemoteTrailers=[];let localItem=createLocalItem(libraryItem,jobItem);return localItem.SyncStatus="queued",itemRepository.updateLibraryItem(localItem.ServerId,localItem.Id,localItem).then(function(){return downloadMedia(apiClient,jobItem,localItem)})})}function downloadParentItems(apiClient,libraryItem){let p=Promise.resolve();return libraryItem.SeriesId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.SeriesId)})),libraryItem.SeasonId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.SeasonId)})),p=libraryItem.AlbumId&&(p=p.then(function(){return downloadItem(apiClient,libraryItem.AlbumId)}),libraryItem.AlbumId!==libraryItem.ParentId)?p.then(function(){return downloadItem(apiClient,libraryItem.ParentId)}):p}function downloadItem(apiClient,itemId){return apiClient.getItem(apiClient.getCurrentUserId(),itemId).then(function(downloadedItem){downloadedItem.CanDelete=!0,downloadedItem.CanDownload=!1,downloadedItem.SupportsSync=!1,downloadedItem.People=[],downloadedItem.SpecialFeatureCount=null,downloadedItem.BackdropImageTags?.length>MaxBackdrops&&(downloadedItem.BackdropImageTags.length=MaxBackdrops),downloadedItem.ParentBackdropImageTags=null,downloadedItem.ParentArtImageTag=null,downloadedItem.ParentLogoImageTag=null;let localItem=createLocalItem(downloadedItem,null);return itemRepository.updateLibraryItem(localItem.ServerId,localItem.Id,localItem).then(function(){return Promise.resolve(localItem)},function(err){return console.error("[mediasync] downloadItem failed: "+err.toString()),Promise.resolve(null)})})}function ensureLocalPathParts(localItem,jobItem){var libraryItem,parts;localItem.LocalPathParts||((parts=LocalAssetManager.getDirectoryPath(libraryItem=localItem.Item)).push(LocalAssetManager.getLocalFileName(libraryItem,jobItem.OriginalFileName)),localItem.LocalPathParts=parts)}function clearChapterImages(obj){if(obj.Chapters)for(let i=0,length=obj.Chapters.length;i<length;i++)obj.Chapters[i].ImageTag=null}function downloadMedia(apiClient,jobItem,localItem){console.log("[mediasync] downloadMedia: start.");var url=apiClient.getUrl("Sync/JobItems/"+jobItem.SyncJobItemId+"/File",{api_key:apiClient.accessToken()});return ensureLocalPathParts(localItem,jobItem),LocalAssetManager.downloadFile(url,localItem).then(function(result){console.log("[mediasync] downloadMedia-downloadFile returned path: "+result.path);var localPath=result.path,libraryItem=localItem.Item;if(localPath&&libraryItem.MediaSources)for(let i=0;i<libraryItem.MediaSources.length;i++){var mediaSource=libraryItem.MediaSources[i];mediaSource.Path=localPath,mediaSource.Protocol="File",clearChapterImages(mediaSource),mediaSource.MediaStreams.forEach(function(stream){"Subtitle"!==stream.Type||stream.IsExternal||(stream.DeliveryMethod="Embed")})}return localItem.LocalPath=localPath,localItem.SyncStatus="transferring",itemRepository.updateLibraryItem(localItem.ServerId,localItem.Id,localItem).then(function(){return afterMediaDownloaded(apiClient,jobItem,localItem).then(function(){return result.isComplete?(localItem.SyncStatus="synced",reportTransfer(apiClient,localItem)):Promise.resolve()},function(err){return console.log("[mediasync] downloadMedia: afterMediaDownloaded failed: "+err),Promise.reject(err)})},function(err){return console.log("[mediasync] downloadMedia: updateLibraryItem failed: "+err),Promise.reject(err)})},function(err){return console.log("[mediasync] downloadMedia: LocalAssetManager.downloadFile failed: "+err),Promise.reject(err)})}function getImages(apiClient,jobItem,localItem){console.log("[mediasync] Begin getImages");let p=Promise.resolve(),libraryItem=localItem.Item,serverId=libraryItem.ServerId,mainImageTag=(libraryItem.ImageTags||{}).Primary||libraryItem.PrimaryImageTag,primaryImageItemId=libraryItem.PrimaryImageItemId||libraryItem.Id,logoImageTag=(primaryImageItemId&&mainImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,primaryImageItemId,libraryItem.Id,mainImageTag,"Primary").then(function(result){return localItem.PrimaryImageItemId=null,Promise.resolve(result)})})),(libraryItem.ImageTags||{}).Logo),artImageTag=(libraryItem.Id&&logoImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.Id,libraryItem.Id,logoImageTag,"Logo")})),(libraryItem.ImageTags||{}).Art),bannerImageTag=(libraryItem.Id&&artImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.Id,libraryItem.Id,artImageTag,"Art")})),(libraryItem.ImageTags||{}).Banner),thumbImageTag=(libraryItem.Id&&bannerImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.Id,libraryItem.Id,bannerImageTag,"Banner")})),(libraryItem.ImageTags||{}).Thumb);if(libraryItem.Id&&thumbImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.Id,libraryItem.Id,thumbImageTag,"Thumb")})),libraryItem.Id&&libraryItem.BackdropImageTags){var numBackdrops=Math.min(libraryItem.BackdropImageTags.length,MaxBackdrops);for(let i=0;i<numBackdrops;i++){let index=i,backdropImageTag=libraryItem.BackdropImageTags[i];p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.Id,libraryItem.Id,backdropImageTag,"backdrop",index)})}}return libraryItem.SeriesId&&libraryItem.SeriesPrimaryImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.SeriesId,libraryItem.SeriesId,libraryItem.SeriesPrimaryImageTag,"Primary")})),libraryItem.SeasonId&&(p=(p=libraryItem.SeasonPrimaryImageTag?p:p.then(function(){return apiClient.getItem(apiClient.getCurrentUserId(),libraryItem.SeasonId).then(function(seasonItem){return libraryItem.SeasonPrimaryImageTag=(seasonItem.ImageTags||{}).Primary,Promise.resolve()})})).then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.SeasonId,libraryItem.SeasonId,libraryItem.SeasonPrimaryImageTag,"Primary")})),libraryItem.AlbumId&&libraryItem.AlbumPrimaryImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.AlbumId,libraryItem.AlbumId,libraryItem.AlbumPrimaryImageTag,"Primary")})),libraryItem.ParentThumbItemId&&libraryItem.ParentThumbImageTag&&(p=p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.ParentThumbItemId,libraryItem.ParentThumbItemId,libraryItem.ParentThumbImageTag,"Thumb")})),(p=libraryItem.ParentPrimaryImageItemId&&libraryItem.ParentPrimaryImageTag?p.then(function(){return downloadImage(localItem,apiClient,serverId,libraryItem.ParentPrimaryImageItemId,libraryItem.ParentPrimaryImageItemId,libraryItem.ParentPrimaryImageTag,"Primary")}):p).then(function(){return console.log("[mediasync] Finished getImages"),itemRepository.updateLibraryItem(localItem.ServerId,localItem.Id,localItem)},function(err){return console.log("[mediasync] Error getImages: "+err.toString()),Promise.resolve()})}function downloadImage(localItem,apiClient,serverId,downloadFromItemId,downloadToItemId,imageTag,imageType,index){return index=index||0,LocalAssetManager.hasImage(serverId,downloadToItemId,imageType,index).then(function(hasImage){if(hasImage)return console.log("[mediasync] downloadImage - skip existing: "+downloadToItemId+" "+imageType+"_"+index.toString()),Promise.resolve();let maxWidth=400;"backdrop"===imageType&&(maxWidth=null);hasImage=apiClient.getImageUrl(downloadFromItemId,{tag:imageTag,type:imageType,maxWidth:maxWidth,api_key:apiClient.accessToken()});return console.log("[mediasync] downloadImage "+downloadToItemId+" "+imageType+"_"+index.toString()),LocalAssetManager.downloadImage(localItem,hasImage,serverId,downloadToItemId,imageType,index).then(function(result){return Promise.resolve(result)},function(err){return console.log("[mediasync] Error downloadImage: "+err.toString()),Promise.resolve()})},function(err){return console.log("[mediasync] Error downloadImage: "+err.toString()),Promise.resolve()})}function getSubtitles(apiClient,jobItem,localItem){if(console.log("[mediasync] Begin getSubtitles"),!jobItem.Item.MediaSources.length)return console.log("[mediasync] Cannot download subtitles because video has no media source info."),Promise.resolve();var files=jobItem.AdditionalFiles.filter(function(f){return"Subtitles"===f.Type});let mediaSource=jobItem.Item.MediaSources[0],p=Promise.resolve();return files.forEach(function(file){p=p.then(function(){return getItemSubtitle(file,apiClient,jobItem,localItem,mediaSource)})}),p.then(function(){return console.log("[mediasync] Exit getSubtitles"),Promise.resolve()})}function getItemSubtitle(file,apiClient,jobItem,localItem,mediaSource){console.log("[mediasync] Begin getItemSubtitle");let subtitleStream=mediaSource.MediaStreams.filter(function(m){return"Subtitle"===m.Type&&m.Index===file.Index})[0];if(!subtitleStream)return console.log("[mediasync] Cannot download subtitles because matching stream info was not found."),Promise.resolve();let fileName=LocalAssetManager.getSubtitleSaveFileName(localItem,jobItem.OriginalFileName,subtitleStream.Language,subtitleStream.IsForced,subtitleStream.IsHearingImpaired,subtitleStream.Codec);return LocalAssetManager.getItemFileSize(fileName).then(function(size){return 0<size?Promise.resolve():(size=apiClient.getUrl("Sync/JobItems/"+jobItem.SyncJobItemId+"/AdditionalFiles",{Name:file.Name,api_key:apiClient.accessToken()}),LocalAssetManager.downloadSubtitles(size,fileName).then(function(subtitleResult){return localItem.AdditionalFiles&&localItem.AdditionalFiles.forEach(function(item){item.Name===file.Name&&(item.Path=subtitleResult.path)}),subtitleStream.Path=subtitleResult.path,subtitleStream.DeliveryMethod="External",itemRepository.updateLibraryItem(localItem.ServerId,localItem.Id,localItem)}))})}function checkLocalFileExistence(apiClient,options){return options.checkFileExistence?(console.log("[mediasync] Begin checkLocalFileExistence"),options=["synced","error"],itemRepository.getLibraryItemsBySyncStatus(apiClient.serverId(),options).then(function(items){let p=Promise.resolve();return items.forEach(function(completedItem){p=p.then(function(){return LocalAssetManager.fileExists(completedItem.LocalPath).then(function(exists){return exists?Promise.resolve():LocalAssetManager.removeLocalItem(completedItem).then(function(){return Promise.resolve()},function(){return Promise.resolve()})})})}),p})):Promise.resolve()}function MediaSync(){this.sync=function(apiClient,options){return console.log("[mediasync]************************************* Start sync (uwp/androidownloadmanager)"),console.log("[mediasync] options.syncCheckProgressOnly = "+(options.syncCheckProgressOnly||"false")),checkLocalFileExistence(apiClient,options).then(function(){return processDownloadStatus(apiClient,options).then(function(){return LocalAssetManager.getDownloadItemCount().then(function(downloadCount){return!0===options.syncCheckProgressOnly&&2<downloadCount?(console.log("[mediasync] exit due to syncCheckProgressOnly with downloadcount = "+downloadCount),console.log("[mediasync]************************************* Exit sync"),Promise.resolve()):reportOfflineActions(apiClient).then(function(){return getNewMedia(apiClient,downloadCount).then(function(){return syncData(apiClient).then(function(){return console.log("[mediasync]************************************* Exit sync"),Promise.resolve()})})})})})},function(err){console.error(err.toString())})}}export default MediaSync; |