2022-10-07 11:03:06 -05:00
import os
import re
2022-10-06 06:02:31 -05:00
import time
2022-10-07 11:03:06 -05:00
import subprocess
2022-10-11 09:57:49 -05:00
from Video import default
2022-10-09 09:13:15 -05:00
from Universal import tools
2022-10-06 06:02:31 -05:00
from Universal import ioservice
from Universal import loggingservice
2022-10-07 11:03:06 -05:00
from Video . Services import tmdbservice
2022-10-11 09:57:49 -05:00
from Universal . network import sftpservice
2022-10-06 06:02:31 -05:00
class VideoService :
def __init__ ( self ) :
self . logger = loggingservice . Output ( True , False )
self . video_settings = default . VideoSettings ( )
2022-10-11 09:57:49 -05:00
# Movie/TV Show Database
self . tmdbservice = tmdbservice . TMDBService ( self . logger )
# Network Service
self . sftpservice = sftpservice . SFTPService ( self . logger )
self . failedFiles = [ ]
2022-10-06 06:02:31 -05:00
self . video_settings . updateSettings ( )
def startNewProcess ( self , num = 1 ) :
self . logger . debugReport ( " [Video] startNewProcess " )
self . current_library = num
self . total_processed = 0
self . is_processing = True
self . video_settings . updateLibrary ( self . current_library )
if self . video_settings . library [ " Server " ] . lower ( ) . find ( " none " ) == - 1 :
self . video_settings . updateServer ( self . video_settings . library [ " Server " ] )
while self . is_processing :
self . processLibraries ( )
2022-10-11 09:57:49 -05:00
self . startNewProcess ( self . current_library )
2022-10-06 06:02:31 -05:00
2022-10-11 09:57:49 -05:00
def processLibraries ( self , refreshLib = True ) :
2022-10-06 06:02:31 -05:00
self . logger . debugReport ( " [Video] processLibraries " )
tmp_library_time = time . time ( )
if self . video_settings . library is not None :
if self . video_settings . library [ " Input " ] is not None :
if refreshLib :
self . total_processed = 0
2022-10-11 09:57:49 -05:00
time . sleep ( 2 )
2022-10-06 06:02:31 -05:00
self . logger . infoReport ( " [Video] Current Library: " + self . video_settings . library [ " Name " ] )
self . current_library_list = ioservice . listAllFiles ( self . video_settings . library [ " Input " ] )
if self . current_library_list is not None :
self . current_library_list = sorted ( self . current_library_list )
if self . current_library_list is not None :
if refreshLib :
self . srt_list = [ ]
for item_search in self . current_library_list :
if item_search . lower ( ) . find ( " .srt " ) != - 1 :
self . srt_list . append ( item_search )
if self . srt_list is not None :
for item_search in self . srt_list :
self . current_library_list . remove ( item_search )
2022-10-11 09:57:49 -05:00
if len ( self . current_library_list ) == 0 :
self . is_processing = False
else :
self . logger . infoReport ( " [Video] Found a total of " + str ( len ( self . current_library_list ) ) + " files " )
2022-10-06 06:02:31 -05:00
for self . current_file in self . current_library_list :
if self . total_processed != 0 :
self . logger . infoReport ( " [Video] Total file remaining: " + str ( len ( self . current_library_list ) - self . total_processed ) )
self . processVideo ( )
else :
self . logger . infoReport ( " [Video] Folder is empty " )
ioservice . deleteEmptyFolders ( self . video_settings . library [ " Input " ] )
else :
self . is_processing = False
else :
self . is_processing = False
self . logger . infoReport ( " [Video] Current Library: " + self . video_settings . library [ " Name " ] + " Time Elapsed: " + time . strftime ( " % H: % M: % S " , time . gmtime ( time . time ( ) - tmp_library_time ) ) )
self . current_library + = 1
def processVideo ( self ) :
self . logger . debugReport ( " [Video] processVideo " )
self . logger . infoReport ( " [Video] Current File: " + self . current_file )
2022-10-07 11:03:06 -05:00
tmp_isDeleted = False
2022-10-11 09:57:49 -05:00
tmp_isSuccess = True
tmp_serverPath = None
2022-10-07 11:03:06 -05:00
if not ioservice . checkSizeChange ( self . current_file ) :
if ioservice . getFileSize ( self . current_file ) == 0 :
self . logger . infoReport ( " [Video] Assuming file has been deleted or moved... Skipping... " )
tmp_isDeleted = True
else :
self . logger . infoReport ( " [Video] File size has changed " )
self . processVideo ( )
else :
if not tmp_isDeleted :
2022-10-11 09:57:49 -05:00
tmp_currentFileDetails = self . extractVideoInformation ( self . current_file )
self . constructOutputPath ( tmp_currentFileDetails )
if tmp_currentFileDetails [ " Episode " ] is None and tmp_currentFileDetails [ " Season " ] is None :
self . logger . infoReport ( " [Video] " + tmp_currentFileDetails [ " Name " ] + " " + str ( tmp_currentFileDetails [ " Year " ] ) )
2022-10-09 09:13:15 -05:00
else :
2022-10-11 09:57:49 -05:00
self . logger . infoReport ( " [Video] " + tmp_currentFileDetails [ " Name " ] + " Season: " + str ( tmp_currentFileDetails [ " Season " ] ) + " Episode: " + str ( tmp_currentFileDetails [ " Episode " ] ) )
self . findSRTs ( )
tmp_compress = False
if not self . video_settings . library [ " Server " ] . lower ( ) . find ( " none " ) != - 1 :
self . video_settings . updateServer ( self . video_settings . library [ " Server " ] )
tmp_serverPath = self . constructServerPath ( )
if self . video_settings . server [ " Type " ] . lower ( ) . find ( " sftp " ) != - 1 :
if self . sftpservice . isEnabled ( ) :
if not self . sftpservice . isConnected ( ) :
self . sftpservice . connectSFTPServer ( self . video_settings . server [ " Host " ] , self . video_settings . server [ " Port " ] , self . video_settings . server [ " Username " ] ,
self . video_settings . server [ " Password " ] , self . video_settings . server [ " Key File " ] , self . video_settings . server [ " Key Type " ] )
if self . sftpservice . isConnected ( ) :
if not ioservice . doesFileExist ( self . currentFileOutputPath ) :
if self . video_settings . library [ " Server Overwrite " ] :
tmp_compress = True
else :
if not self . sftpservice . doesFileExists ( tmp_serverPath ) :
tmp_compress = True
else :
if not ioservice . doesFileExist ( self . currentFileOutputPath ) :
tmp_compress = True
if tmp_compress and not self . video_settings . library [ " Compress " ] :
if self . video_settings . library [ " Delete Input " ] :
self . logger . infoReport ( " [Video] Moving file " )
self . is_processing = True
ioservice . moveFile ( self . current_file , self . currentFileOutputPath )
i = 0
while i < len ( self . srt_to_include ) :
ioservice . moveFile ( self . srt_to_include [ i ] , self . constructOutputPath ( tmp_currentFileDetails , True , i ) )
i + = 1
self . is_processing = False
tmp_isSuccess = True
self . logger . infoReport ( " [Video] Move complete " )
else :
self . logger . infoReport ( " [Video] Copying file " )
self . is_processing = True
ioservice . moveFile ( self . current_file , self . currentFileOutputPath , True )
i = 0
while i < len ( self . srt_to_include ) :
ioservice . moveFile ( self . srt_to_include [ i ] , self . constructOutputPath ( tmp_currentFileDetails , True , i ) , True )
i + = 1
self . is_processing = False
tmp_isSuccess = True
self . logger . infoReport ( " [Video] Copying complete " )
elif tmp_compress and self . video_settings . library [ " Compress " ] :
self . logger . infoReport ( " [Video] Compressing video " )
self . startCompressing ( self . current_file , self . currentFileOutputPath , self . srt_to_include )
tmp_isSuccess = True
self . logger . infoReport ( " [Video] Compressing completed " )
if not self . video_settings . library [ " Server " ] . lower ( ) . find ( " none " ) != - 1 :
self . video_settings . updateServer ( self . video_settings . library [ " Server " ] )
if self . video_settings . server [ " Type " ] . lower ( ) . find ( " sftp " ) != - 1 :
if self . sftpservice . isEnabled ( ) :
if not self . sftpservice . isConnected ( ) :
self . sftpservice . connectSFTPServer ( self . video_settings . server [ " Host " ] , self . video_settings . server [ " Port " ] , self . video_settings . server [ " Username " ] ,
self . video_settings . server [ " Password " ] , self . video_settings . server [ " Key File " ] , self . video_settings . server [ " Key Type " ] )
if self . sftpservice . isConnected ( ) :
if self . sftpservice . doesFileExists ( tmp_serverPath ) :
if self . video_settings . library [ " Server Overwrite " ] :
if self . sftpservice . getFileSize ( tmp_serverPath ) != ioservice . getFileSize ( self . currentFileOutputPath ) :
if self . sftpservice . doesFileExist ( tmp_serverPath ) :
self . sftpservice . deleteFile ( tmp_serverPath )
if self . sftpservice . uploadFile ( self . currentFileOutputPath , tmp_serverPath ) :
tmp_isSuccess = True
self . logger . infoReport ( " [Video] Upload Complete " )
else :
tmp_isSuccess = False
else :
if self . sftpservice . uploadFile ( self . currentFileOutputPath , tmp_serverPath ) :
tmp_isSuccess = True
self . logger . infoReport ( " [Video] Upload Complete " )
else :
tmp_isSuccess = False
else :
if self . sftpservice . uploadFile ( self . currentFileOutputPath , tmp_serverPath ) :
tmp_isSuccess = True
else :
tmp_isSuccess = False
if not tmp_isSuccess :
self . failedFiles = self . failedFiles + [ self . current_file ]
else :
self . total_processed + = 1
2022-10-07 11:03:06 -05:00
def extractVideoInformation ( self , file ) :
self . logger . debugReport ( " [Video] extractVideoInformation " )
file = file . replace ( self . video_settings . library [ " Input " ] , " " ) . lstrip ( ) . replace ( " _ " , " " )
for blacklist_item in self . video_settings . settings [ " Blacklist " ] . split ( " , " ) :
file = file . replace ( blacklist_item , " " )
tmp_input_format = file . rsplit ( " . " , 1 ) [ - 1 ]
tmp_name = None
tmp_season = None
tmp_episode = None
tmp_episode_title = None
tmp_year = None
tmp_episode_year = None
tmp_length = self . getVideoLength ( )
tmp_folders , tmp_file = os . path . split ( file )
for possible_years in re . findall ( r ' \ d+ ' , file ) :
if len ( possible_years ) == 4 :
tmp_year = int ( possible_years )
match len ( tmp_folders . split ( ioservice . getPathSeperator ( ) ) ) :
case 1 :
tmp_name = tmp_folders . split ( ioservice . getPathSeperator ( ) ) [ 0 ]
if not tmp_name :
tmp_name = tmp_file . replace ( str ( tmp_year ) , " " ) . replace ( " . " + tmp_input_format , " " ) . strip ( )
case 2 :
tmp_name = tmp_folders . split ( ioservice . getPathSeperator ( ) ) [ 0 ]
case 3 :
tmp_name = tmp_folders . split ( ioservice . getPathSeperator ( ) ) [ 0 ]
case _ :
tmp_name = tmp_file . replace ( " . " + tmp_input_format , " " )
if self . video_settings . library [ " Type " ] . lower ( ) . find ( " show " ) != - 1 :
if tmp_season is None or tmp_episode is None :
match len ( tmp_folders . split ( ioservice . getPathSeperator ( ) ) ) :
case 2 :
tmp_season = re . findall ( r ' \ d+ ' , tmp_folders . replace ( tmp_name , " " ) ) [ 0 ]
tmp_episode = re . findall ( r ' ([0-9]*[0-9]) ' , tmp_file . replace ( " . " + tmp_input_format , " " ) . replace ( tmp_name , " " ) ) [ - 1 ]
if tmp_file . lower ( ) . find ( tmp_episode + " a " ) != - 1 :
tmp_episode = tmp_episode + " - Part 1 "
elif tmp_file . lower ( ) . find ( tmp_episode + " b " ) != - 1 :
tmp_episode = tmp_episode + " - Part 2 "
case 3 :
tmp_season = re . findall ( r ' \ d+ ' , tmp_folders . replace ( tmp_name , " " ) ) [ 0 ]
tmp_episode = re . findall ( r ' ([0-9]*[0-9]) ' , tmp_folders . replace ( " . " + tmp_input_format , " " ) . replace ( tmp_name , " " ) ) [ - 1 ]
if tmp_file . lower ( ) . find ( tmp_episode + " a " ) != - 1 :
tmp_episode = tmp_episode + " - Part 1 "
elif tmp_file . lower ( ) . find ( tmp_episode + " b " ) != - 1 :
tmp_episode = tmp_episode + " - Part 2 "
case _ :
tmp_episode = re . findall ( r ' \ d+ ' , tmp_file . replace ( " . " + tmp_input_format , " " ) . replace ( tmp_name , " " ) ) [ - 1 ]
try :
tmp_season = re . findall ( r ' \ d+ ' , tmp_file . replace ( " . " + tmp_input_format , " " ) . replace ( tmp_name , " " ) ) [ 0 ]
except :
tmp_episode = re . findall ( r ' \ d+ ' , tmp_file . replace ( " . " + tmp_input_format , " " ) ) [ - 1 ]
if tmp_season != " 0 " and tmp_season :
tmp_season = tmp_season . lstrip ( " 0 " )
if tmp_episode != " 0 " and tmp_episode :
tmp_episode = tmp_episode . lstrip ( " 0 " )
match self . video_settings . library [ " Database " ] . lower ( ) :
case " tmdb " :
if self . tmdbservice . isEnabled ( ) :
self . tmdbservice . connectToTMDB ( )
if self . video_settings . library [ " Type " ] . lower ( ) . find ( " movie " ) != - 1 :
tmp_name = tmp_name . replace ( str ( tmp_year ) , " " ) . replace ( " ( " , " " ) . replace ( " ) " , " " )
if tmp_length is not None or tmp_year is not None :
tmp_data = self . tmdbservice . getBestMovie ( tmp_name , tmp_length , tmp_year )
if tmp_data :
tmp_name = tmp_data [ 0 ]
tmp_year = tmp_data [ 2 ]
else :
tmp_data = self . tmdbservice . searchMovies ( tmp_name )
tmp_name = tmp_data [ 0 ] [ 0 ]
tmp_year = tmp_data [ 0 ] [ 1 ]
elif self . video_settings . library [ " Type " ] . lower ( ) . find ( " show " ) != - 1 :
tmp_data = self . tmdbservice . getShowName ( tmp_name )
tmp_name = tmp_data [ " name " ]
tmp_year = tmp_data [ " first_air_date " ] [ : 4 ]
case " tvdb " :
2022-10-11 09:57:49 -05:00
#TODO: Implement
2022-10-07 11:03:06 -05:00
pass
case _ :
2022-10-11 09:57:49 -05:00
#TODO: Implement
2022-10-07 11:03:06 -05:00
pass
tmp_name = tmp_name . replace ( " : " , " " )
if tmp_episode_title :
tmp_episode_title = tmp_episode_title . replace ( " : " , " " )
2022-10-11 09:57:49 -05:00
return { " Name " : tmp_name , " Year " : tmp_year , " Season " : tmp_season , " Episode " : tmp_episode , " Episode Title " : tmp_episode_title , " Episode Year " : tmp_episode_year , " Format " : tmp_input_format }
2022-10-07 11:03:06 -05:00
2022-10-09 09:13:15 -05:00
def constructOutputPath ( self , file_info , subtitles = False , num = 0 ) :
2022-10-07 11:03:06 -05:00
self . logger . debugReport ( " [Video] constructOutputPath " )
2022-10-11 09:57:49 -05:00
self . currentFileOutputPath = self . video_settings . library [ " Output " ] + self . video_settings . library [ " Directory " ]
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {NAME} " , file_info [ " Name " ] )
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {YEAR} " , file_info [ " Year " ] )
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {SEASON} " , file_info [ " Season " ] )
2022-10-09 09:13:15 -05:00
if isinstance ( file_info [ " Episode " ] , list ) :
tmp_episodes = None
for eps in file_info [ " Episode " ] :
if eps != file_info [ " Episode " ] [ - 1 ] :
if not tmp_episodes :
tmp_episodes = str ( eps ) + " - "
else :
tmp_episodes = tmp_episodes + str ( eps ) + " - "
else :
if not tmp_episodes :
tmp_episodes = str ( eps )
else :
tmp_episodes = tmp_episodes + str ( eps )
2022-10-11 09:57:49 -05:00
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {EPISODE} " , tmp_episodes )
2022-10-09 09:13:15 -05:00
else :
2022-10-11 09:57:49 -05:00
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {EPISODE} " , file_info [ " Episode " ] )
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {EPISODE_YEAR} " , file_info [ " Episode Year " ] )
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {EPISODE_NAME} " , file_info [ " Episode Title " ] )
2022-10-09 09:13:15 -05:00
if not subtitles :
2022-10-11 09:57:49 -05:00
if self . currentFileOutputPath [ self . currentFileOutputPath . index ( " $ {FORMAT} " ) - 1 ] != " . " :
2022-10-09 09:13:15 -05:00
if file_info [ " Format " ] . startswith ( " . " ) :
2022-10-11 09:57:49 -05:00
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {FORMAT} " , file_info [ " Format " ] )
2022-10-09 09:13:15 -05:00
else :
2022-10-11 09:57:49 -05:00
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {FORMAT} " , " . " + file_info [ " Format " ] )
2022-10-09 09:13:15 -05:00
else :
if file_info [ " Format " ] . startswith ( " . " ) :
2022-10-11 09:57:49 -05:00
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " .$ {FORMAT} " , file_info [ " Format " ] )
2022-10-09 09:13:15 -05:00
else :
2022-10-11 09:57:49 -05:00
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " .$ {FORMAT} " , " . " + file_info [ " Format " ] )
2022-10-09 09:13:15 -05:00
else :
2022-10-11 09:57:49 -05:00
if self . currentFileOutputPath [ self . currentFileOutputPath . index ( " $ {FORMAT} " ) - 1 ] != " . " :
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " $ {FORMAT} " , " - " + self . srt_language [ num ] + " .srt " )
elif self . currentFileOutputPath [ self . currentFileOutputPath . index ( " $ {FORMAT} " - 1 ) ] == " . " :
self . currentFileOutputPath = tools . replace ( self . currentFileOutputPath , " .$ {FORMAT} " , " - " + self . srt_language [ num ] + " .srt " )
self . logger . debugReport ( " [Video] Output Path: " + self . currentFileOutputPath )
return self . currentFileOutputPath
def startCompressing ( input_path , output_path , srt_list ) :
#TODO: Implement
pass
def constructServerPath ( self ) :
#TODO: Implement
pass
2022-10-09 09:13:15 -05:00
def findSRTs ( self ) :
self . logger . debugReport ( " [Video] findSRTs " )
tmp_srt_lang = [ " aar " , " abk " , " afr " , " aka " , " alb " , " amh " , " ara " , " arg " , " arm " , " asm " , " ava " , " ave " , " aym " , " aze " , " bak " , " bam " , " baq " ,
" bel " , " ben " , " bih " , " bis " , " bos " , " bre " , " bul " , " bur " , " cat " , " cha " , " che " , " chi " , " chu " , " chv " , " cor " , " cos " , " cre " ,
" cze " , " dan " , " div " , " dut " , " dzo " , " eng " , " epo " , " est " , " ewe " , " fao " , " fij " , " fin " , " fre " , " fry " , " ful " , " geo " , " ger " ,
" gla " , " gle " , " glg " , " glv " , " gre " , " grn " , " guj " , " hat " , " hau " , " heb " , " her " , " hin " , " hmo " , " hrv " , " hun " , " ibo " , " ice " ,
" ido " , " iii " , " iku " , " ile " , " ina " , " ind " , " ipk " , " ita " , " jav " , " jpn " , " kal " , " kan " , " kas " , " kau " , " kaz " , " khm " , " kik " ,
" kin " , " kir " , " kom " , " kon " , " kor " , " kua " , " kur " , " lao " , " lat " , " lav " , " lim " , " lin " , " lit " , " ltz " , " lub " , " lug " , " mac " ,
" mah " , " mal " , " mao " , " mar " , " may " , " mlg " , " mlt " , " mon " , " nau " , " nav " , " nbl " , " nde " , " ndo " , " nep " , " nno " , " nob " , " nor " ,
" nya " , " oci " , " oji " , " ori " , " orm " , " oss " , " pan " , " per " , " pli " , " pol " , " por " , " pus " , " que " , " roh " , " rum " , " run " , " rus " ,
" sag " , " san " , " sin " , " slo " , " slv " , " sme " , " smo " , " sna " , " snd " , " som " , " sot " , " spa " , " srd " , " srp " , " ssw " , " sun " , " swa " ,
" swe " , " tah " , " tam " , " tat " , " tel " , " tgk " , " tgl " , " tha " , " tib " , " tir " , " ton " , " tsn " , " tso " , " tuk " , " tur " , " twi " , " uig " ,
" ukr " , " urd " , " uzb " , " ven " , " vie " , " vol " , " wel " , " wln " , " wol " , " xho " , " yid " , " yor " , " zha " , " zul " ]
2022-10-11 09:57:49 -05:00
self . srt_to_include = [ ]
self . srt_language = [ ]
tmp_srt = self . current_file . replace ( self . current_file . rsplit ( " . " ) [ - 1 ] , " srt " ) . lower ( )
if ( ioservice . doesFileExist ( tmp_srt ) ) :
self . srt_to_include . append ( tmp_srt )
self . srt_language . append ( " eng " )
else :
for possible_srt in tmp_srt_lang :
tmp_srt = self . current_file . replace ( self . current_file . rsplit ( " . " ) [ - 1 ] , " " ) [ : - 1 ] . lower ( )
tmp_srt = tmp_srt + " - " + possible_srt + " .srt "
if ( ioservice . doesFileExist ( tmp_srt ) ) :
self . srt_to_include . append ( tmp_srt )
self . srt_language . append ( possible_srt )
2022-10-07 11:03:06 -05:00
def getVideoLength ( self ) :
self . logger . debugReport ( " [Video] getVideoLength " )
tmp_time = None
try :
tmp_time = subprocess . check_output ( [ self . video_settings . settings [ " FFProbe " ] , ' -i ' , self . current_file , ' -show_entries ' , ' format=duration ' , ' -v ' , ' quiet ' , ' -of ' , ' csv= %s ' % ( " p=0 " ) ] )
tmp_time = str ( tmp_time )
if not tmp_time . find ( " N/A " ) != - 1 :
tmp_hours = time . strftime ( " % H " , time . gmtime ( round ( float ( re . findall ( ' \ d+ ' , tmp_time ) [ 0 ] ) ) ) ) . lstrip ( " 0 " )
tmp_minutes = time . strftime ( " % M " , time . gmtime ( round ( float ( re . findall ( ' \ d+ ' , tmp_time ) [ 0 ] ) ) ) ) . lstrip ( " 0 " )
try :
tmp_hours = int ( tmp_hours ) * 60
except :
tmp_hours = 0
try :
tmp_length = tmp_hours + int ( tmp_minutes )
except :
tmp_length = tmp_hours
else :
self . logger . errorReport ( " [Video] FFProbe could not get video content length " )
tmp_length = None
return tmp_length
except :
self . logger . errorReport ( " [Video] There was a problem getting the length of video content " )
return None