@ -3,7 +3,7 @@ from couchpotato.api import addApiView
from couchpotato . core . event import addEvent , fireEvent , fireEventAsync
from couchpotato . core . helpers . encoding import toUnicode , ss , sp
from couchpotato . core . helpers . variable import getExt , mergeDicts , getTitle , \
getImdb , link , symlink , tryInt , splitString
getImdb , link , symlink , tryInt , splitString , fnEscape , isSubFolder
from couchpotato . core . logger import CPLog
from couchpotato . core . plugins . base import Plugin
from couchpotato . core . settings . model import Library , File , Profile , Release , \
@ -30,10 +30,11 @@ class Renamer(Plugin):
' desc ' : ' For the renamer to check for new files to rename in a folder ' ,
' params ' : {
' async ' : { ' desc ' : ' Optional: Set to 1 if you dont want to fire the renamer.scan asynchronous. ' } ,
' movie_folder ' : { ' desc ' : ' Optional: The folder of the movie to scan. Keep empty for default renamer folder. ' } ,
' files ' : { ' desc ' : ' Optional: Provide the release files if more releases are in the same movie_folder, delimited with a \' | \' . Note that no dedicated release folder is expected for releases with one file. ' } ,
' media_folder ' : { ' desc ' : ' Optional: The folder of the media to scan. Keep empty for default renamer folder. ' } ,
' files ' : { ' desc ' : ' Optional: Provide the release files if more releases are in the same media_folder, delimited with a \' | \' . Note that no dedicated release folder is expected for releases with one file. ' } ,
' base_folder ' : { ' desc ' : ' Optional: The folder to find releases in. Leave empty for default folder. ' } ,
' downloader ' : { ' desc ' : ' Optional: The downloader the release has been downloaded with. \' download_id \' is required with this option. ' } ,
' download_id ' : { ' desc ' : ' Optional: The nzb/torrent ID of the release in movi e_folder. \' downloader \' is required with this option. ' } ,
' download_id ' : { ' desc ' : ' Optional: The nzb/torrent ID of the release in media _folder. \' downloader \' is required with this option. ' } ,
' status ' : { ' desc ' : ' Optional: The status of the release: \' completed \' (default) or \' seeding \' ' } ,
} ,
} )
@ -64,25 +65,32 @@ class Renamer(Plugin):
def scanView ( self , * * kwargs ) :
async = tryInt ( kwargs . get ( ' async ' , 0 ) )
movie_folder = sp ( kwargs . get ( ' movie_folder ' ) )
base_folder = kwargs . get ( ' base_folder ' )
media_folder = sp ( kwargs . get ( ' media_folder ' ) )
# Backwards compatibility, to be removed after a few versions :)
if not media_folder :
media_folder = sp ( kwargs . get ( ' movie_folder ' ) )
downloader = kwargs . get ( ' downloader ' )
download_id = kwargs . get ( ' download_id ' )
files = ' | ' . join ( [ sp ( filename ) for filename in splitString ( kwargs . get ( ' files ' ) , ' | ' ) ] )
status = kwargs . get ( ' status ' , ' completed ' )
release_download = { ' folder ' : movie_folder } if movie_folder else None
if release_download :
release_download = None
if not base_folder and media_folder :
release_download = { ' folder ' : media_folder }
release_download . update ( { ' id ' : download_id , ' downloader ' : downloader , ' status ' : status , ' files ' : files } if download_id else { } )
fire_handle = fireEvent if not async else fireEventAsync
fire_handle ( ' renamer.scan ' , release_download )
fire_handle ( ' renamer.scan ' , base_folder = base_folder , release_download = release_download )
return {
' success ' : True
}
def scan ( self , release_download = None ) :
def scan ( self , base_folder = None , release_download = None ) :
if not release_download : release_download = { }
if self . isDisabled ( ) :
@ -92,11 +100,14 @@ class Renamer(Plugin):
log . info ( ' Renamer is already running, if you see this often, check the logs above for errors. ' )
return
if not base_folder :
base_folder = self . conf ( ' from ' )
from_folder = sp ( self . conf ( ' from ' ) )
to_folder = sp ( self . conf ( ' to ' ) )
# Get movi e folder to process
movi e_folder = release_download . get ( ' folder ' )
# Get media folder to process
media _folder = release_download . get ( ' folder ' )
# Get all folders that should not be processed
no_process = [ to_folder ]
@ -109,73 +120,73 @@ class Renamer(Plugin):
pass
# Check to see if the no_process folders are inside the "from" folder.
if not os . path . isdir ( from _folder) or not os . path . isdir ( to_folder ) :
log . error ( ' Both the " To " and " From " have to exist. ' )
if not os . path . isdir ( base _folder) or not os . path . isdir ( to_folder ) :
log . error ( ' Both the " To " and " From " folder have to exist. ' )
return
else :
for item in no_process :
if from_folder in item :
log . error ( ' To protect your data, the movi e libraries can \' t be inside of or the same as the " from " folder. ' )
if isSubFolder ( item , base_folder ) :
log . error ( ' To protect your data, the media libraries can \' t be inside of or the same as the " from " folder. ' )
return
# Check to see if the no_process folders are inside the provided movi e_folder
if movi e_folder and not os . path . isdir ( movi e_folder ) :
log . debug ( ' The provided movi e folder %s does not exist. Trying to find it in the \' from \' folder. ' , movi e_folder )
# Check to see if the no_process folders are inside the provided media _folder
if media _folder and not os . path . isdir ( media _folder ) :
log . debug ( ' The provided media folder %s does not exist. Trying to find it in the \' from \' folder. ' , media _folder )
# Update to the from folder
if len ( splitString ( release_download . get ( ' files ' ) , ' | ' ) ) == 1 :
new_movi e_folder = from_folder
new_media _folder = from_folder
else :
new_movi e_folder = os . path . join ( from_folder , os . path . basename ( movi e_folder ) )
new_media _folder = os . path . join ( from_folder , os . path . basename ( media _folder ) )
if not os . path . isdir ( new_movi e_folder ) :
log . error ( ' The provided movi e folder %s does not exist and could also not be found in the \' from \' folder. ' , movi e_folder )
if not os . path . isdir ( new_media _folder ) :
log . error ( ' The provided media folder %s does not exist and could also not be found in the \' from \' folder. ' , media _folder )
return
# Update the files
new_files = [ os . path . join ( new_movi e_folder , os . path . relpath ( filename , movi e_folder ) ) for filename in splitString ( release_download . get ( ' files ' ) , ' | ' ) ]
new_files = [ os . path . join ( new_media _folder , os . path . relpath ( filename , media _folder ) ) for filename in splitString ( release_download . get ( ' files ' ) , ' | ' ) ]
if new_files and not os . path . isfile ( new_files [ 0 ] ) :
log . error ( ' The provided movi e folder %s does not exist and its files could also not be found in the \' from \' folder. ' , movi e_folder )
log . error ( ' The provided media folder %s does not exist and its files could also not be found in the \' from \' folder. ' , media _folder )
return
# Update release_download info to the from folder
log . debug ( ' Release %s found in the \' from \' folder. ' , movi e_folder )
release_download [ ' folder ' ] = new_movi e_folder
log . debug ( ' Release %s found in the \' from \' folder. ' , media _folder )
release_download [ ' folder ' ] = new_media _folder
release_download [ ' files ' ] = ' | ' . join ( new_files )
movi e_folder = new_movi e_folder
media _folder = new_media _folder
if movi e_folder :
if media _folder :
for item in no_process :
if movie_folder in item :
log . error ( ' To protect your data, the movi e libraries can \' t be inside of or the same as the provided movi e folder. ' )
if isSubFolder ( item , media_folder ) :
log . error ( ' To protect your data, the media libraries can \' t be inside of or the same as the provided media folder. ' )
return
# Make sure a checkSnatched marked all downloads/seeds as such
if not release_download and self . conf ( ' run_every ' ) > 0 :
fireEvent ( ' renamer.check_snatched ' )
self . checkSnatched ( fire_scan = False )
self . renaming_started = True
# make sure the movi e folder name is included in the search
# make sure the media folder name is included in the search
folder = None
files = [ ]
if movi e_folder :
log . info ( ' Scanning movi e folder %s ... ' , movi e_folder )
folder = os . path . dirname ( movi e_folder )
if media _folder :
log . info ( ' Scanning media folder %s ... ' , media _folder )
folder = os . path . dirname ( media _folder )
if release_download . get ( ' files ' , ' ' ) :
files = splitString ( release_download [ ' files ' ] , ' | ' )
# If there is only one file in the torrent, the downloader did not create a subfolder
if len ( files ) == 1 :
folder = movi e_folder
folder = media _folder
else :
# Get all files from the specified folder
try :
for root , folders , names in os . walk ( movi e_folder ) :
for root , folders , names in os . walk ( media _folder ) :
files . extend ( [ sp ( os . path . join ( root , name ) ) for name in names ] )
except :
log . error ( ' Failed getting files from %s : %s ' , ( movi e_folder , traceback . format_exc ( ) ) )
log . error ( ' Failed getting files from %s : %s ' , ( media _folder , traceback . format_exc ( ) ) )
db = get_session ( )
@ -185,10 +196,10 @@ class Renamer(Plugin):
# Unpack any archives
extr_files = None
if self . conf ( ' unrar ' ) :
folder , movi e_folder , files , extr_files = self . extractFiles ( folder = folder , movi e_folder = movi e_folder , files = files ,
folder , media _folder , files , extr_files = self . extractFiles ( folder = folder , media _folder = media _folder , files = files ,
cleanup = self . conf ( ' cleanup ' ) and not self . downloadIsTorrent ( release_download ) )
groups = fireEvent ( ' scanner.scan ' , folder = folder if folder else from _folder,
groups = fireEvent ( ' scanner.scan ' , folder = folder if folder else base _folder,
files = files , release_download = release_download , return_ignored = False , single = True ) or [ ]
folder_name = self . conf ( ' folder_name ' )
@ -201,6 +212,10 @@ class Renamer(Plugin):
done_status , active_status , downloaded_status , snatched_status , seeding_status = \
fireEvent ( ' status.get ' , [ ' done ' , ' active ' , ' downloaded ' , ' snatched ' , ' seeding ' ] , single = True )
# Tag release folder as failed_rename in case no groups were found. This prevents check_snatched from removing the release from the downloader.
if not groups and self . statusInfoComplete ( release_download ) :
self . tagRelease ( release_download = release_download , tag = ' failed_rename ' )
for group_identifier in groups :
group = groups [ group_identifier ]
@ -497,7 +512,10 @@ class Renamer(Plugin):
os . remove ( src )
parent_dir = os . path . dirname ( src )
if delete_folders . count ( parent_dir ) == 0 and os . path . isdir ( parent_dir ) and not parent_dir in [ destination , movie_folder ] and not from_folder in parent_dir :
if delete_folders . count ( parent_dir ) == 0 and os . path . isdir ( parent_dir ) and \
not isSubFolder ( destination , parent_dir ) and not isSubFolder ( media_folder , parent_dir ) and \
not isSubFolder ( parent_dir , base_folder ) :
delete_folders . append ( parent_dir )
except :
@ -513,6 +531,7 @@ class Renamer(Plugin):
# Rename all files marked
group [ ' renamed_files ' ] = [ ]
failed_rename = False
for src in rename_files :
if rename_files [ src ] :
dst = rename_files [ src ]
@ -525,11 +544,20 @@ class Renamer(Plugin):
self . moveFile ( src , dst , forcemove = not self . downloadIsTorrent ( release_download ) or self . fileIsAdded ( src , group ) )
group [ ' renamed_files ' ] . append ( dst )
except :
log . error ( ' Failed moving the file " %s " : %s ' , ( os . path . basename ( src ) , traceback . format_exc ( ) ) )
self . tagRelease ( group = group , tag = ' failed_rename ' )
log . error ( ' Failed ranaming the file " %s " : %s ' , ( os . path . basename ( src ) , traceback . format_exc ( ) ) )
failed_rename = True
break
# If renaming failed tag the release folder as failed and continue with next group. Note that all old files have already been deleted.
if failed_rename :
self . tagRelease ( group = group , tag = ' failed_rename ' )
continue
# If renaming succeeded, make sure it is not tagged as failed (scanner didn't return a group, but a download_ID was provided in an earlier attempt)
else :
self . untagRelease ( group = group , tag = ' failed_rename ' )
# Tag folder if it is in the 'from' folder and it will not be removed because it is a torrent
if self . movieInFromFolder ( movie_folder ) and self . downloadIsTorrent ( release_download ) :
if self . movieInFromFolder ( media _folder ) and self . downloadIsTorrent ( release_download ) :
self . tagRelease ( group = group , tag = ' renamed_already ' )
# Remove matching releases
@ -541,12 +569,12 @@ class Renamer(Plugin):
log . error ( ' Failed removing %s : %s ' , ( release . identifier , traceback . format_exc ( ) ) )
if group [ ' dirname ' ] and group [ ' parentdir ' ] and not self . downloadIsTorrent ( release_download ) :
if movi e_folder :
if media _folder :
# Delete the movie folder
group_folder = movi e_folder
group_folder = media _folder
else :
# Delete the first empty subfolder in the tree relative to the 'from' folder
group_folder = sp ( os . path . join ( from _folder, os . path . relpath ( group [ ' parentdir ' ] , from _folder) . split ( os . path . sep ) [ 0 ] ) )
group_folder = sp ( os . path . join ( base _folder, os . path . relpath ( group [ ' parentdir ' ] , base _folder) . split ( os . path . sep ) [ 0 ] ) )
try :
log . info ( ' Deleting folder: %s ' , group_folder )
@ -564,7 +592,7 @@ class Renamer(Plugin):
# Break if CP wants to shut down
if self . shuttingDown ( ) :
break
self . renaming_started = False
def getRenameExtras ( self , extra_type = ' ' , replacements = None , folder_name = ' ' , file_name = ' ' , destination = ' ' , group = None , current_file = ' ' , remove_multiple = False ) :
@ -614,28 +642,46 @@ Remove it if you want it to be renamed (again, or at least let it try again)
tag_files . extend ( [ os . path . join ( root , name ) for name in names ] )
for filename in tag_files :
# Dont tag .ignore files
if os . path . splitext ( filename ) [ 1 ] == ' .ignore ' :
continue
tag_filename = ' %s . %s .ignore ' % ( os . path . splitext ( filename ) [ 0 ] , tag )
if not os . path . isfile ( tag_filename ) :
self . createFile ( tag_filename , text )
def untagRelease ( self , release_download , tag = ' ' ) :
def untagRelease ( self , group = None , release_download = None , tag = ' ' ) :
if not release_download :
return
tag_files = [ ]
folder = None
folder = release_download [ ' folder ' ]
if not os . path . isdir ( folder ) :
return False
# Tag movie files if they are known
if isinstance ( group , dict ) :
tag_files = [ sorted ( list ( group [ ' files ' ] [ ' movie ' ] ) ) [ 0 ] ]
# Untag download_files if they are known
if release_download [ ' files ' ] :
tag_files = splitString ( release_download [ ' files ' ] , ' | ' )
folder = group [ ' parentdir ' ]
if not group . get ( ' dirname ' ) or not os . path . isdir ( folder ) :
return False
# Untag all files in release folder
else :
for root , folders , names in os . walk ( release_download [ ' folder ' ] ) :
tag_files . extend ( [ sp ( os . path . join ( root , name ) ) for name in names if not os . path . splitext ( name ) [ 1 ] == ' .ignore ' ] )
elif isinstance ( release_download , dict ) :
# Untag download_files if they are known
if release_download [ ' files ' ] :
tag_files = splitString ( release_download [ ' files ' ] , ' | ' )
# Untag all files in release folder
else :
for root , folders , names in os . walk ( release_download [ ' folder ' ] ) :
tag_files . extend ( [ sp ( os . path . join ( root , name ) ) for name in names if not os . path . splitext ( name ) [ 1 ] == ' .ignore ' ] )
folder = release_download [ ' folder ' ]
if not os . path . isdir ( folder ) :
return False
if not folder :
return False
# Find all .ignore files in folder
ignore_files = [ ]
@ -644,7 +690,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
# Match all found ignore files with the tag_files and delete if found
for tag_file in tag_files :
ignore_file = fnmatch . filter ( ignore_files , ' %s . %s .ignore ' % ( re . escape ( os . path . splitext ( tag_file ) [ 0 ] ) , tag if tag else ' * ' ) )
ignore_file = fnmatch . filter ( ignore_files , fnEscape ( ' %s . %s .ignore ' % ( os . path . splitext ( tag_file ) [ 0 ] , tag if tag else ' * ' ) ) )
for filename in ignore_file :
try :
os . remove ( filename )
@ -677,7 +723,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
# Match all found ignore files with the tag_files and return True found
for tag_file in tag_files :
ignore_file = fnmatch . filter ( ignore_files , ' %s . %s .ignore ' % ( os . path . splitext ( tag_file ) [ 0 ] , tag if tag else ' * ' ) )
ignore_file = fnmatch . filter ( ignore_files , fnEscape ( ' %s . %s .ignore ' % ( os . path . splitext ( tag_file ) [ 0 ] , tag if tag else ' * ' ) ) )
if ignore_file :
return True
@ -790,7 +836,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
except :
loge ( ' Couldn \' t remove empty directory %s : %s ' , ( folder , traceback . format_exc ( ) ) )
def checkSnatched ( self ) :
def checkSnatched ( self , fire_scan = True ) :
if self . checking_snatched :
log . debug ( ' Already checking snatched ' )
@ -806,126 +852,169 @@ Remove it if you want it to be renamed (again, or at least let it try again)
Release . status_id . in_ ( [ snatched_status . get ( ' id ' ) , seeding_status . get ( ' id ' ) , missing_status . get ( ' id ' ) ] )
) . all ( )
if not rels :
#No releases found that need status checking
self . checking_snatched = False
return True
# Collect all download information with the download IDs from the releases
download_ids = [ ]
no_status_support = [ ]
try :
for rel in rels :
rel_dict = rel . to_dict ( { ' info ' : { } } )
if rel_dict [ ' info ' ] . get ( ' download_id ' ) and rel_dict [ ' info ' ] . get ( ' download_downloader ' ) :
download_ids . append ( { ' id ' : rel_dict [ ' info ' ] [ ' download_id ' ] , ' downloader ' : rel_dict [ ' info ' ] [ ' download_downloader ' ] } )
ds = rel_dict [ ' info ' ] . get ( ' download_status_support ' )
if ds == False or ds == ' False ' :
no_status_support . append ( ss ( rel_dict [ ' info ' ] . get ( ' download_downloader ' ) ) )
except :
log . error ( ' Error getting download IDs from database ' )
self . checking_snatched = False
return False
release_downloads = fireEvent ( ' download.status ' , download_ids , merge = True ) if download_ids else [ ]
if len ( no_status_support ) > 0 :
log . debug ( ' Download status functionality is not implemented for one of the active downloaders: %s ' , no_status_support )
if not release_downloads :
if fire_scan :
self . scan ( )
self . checking_snatched = False
return True
scan_releases = [ ]
scan_required = False
if rels :
log . debug ( ' Checking status snatched releases... ' )
log . debug ( ' Checking status snatched releases... ' )
release_downloads = fireEvent ( ' download.status ' , merge = True )
if not release_downloads :
log . debug ( ' Download status functionality is not implemented for active downloaders. ' )
scan_required = True
else :
try :
for rel in rels :
rel_dict = rel . to_dict ( { ' info ' : { } } )
movie_dict = fireEvent ( ' movie.get ' , rel . movie_id , single = True )
try :
for rel i n rels :
rel_dict = rel . to_dict ( { ' info ' : { } } )
movie_dict = fireEvent ( ' media.get ' , media_id = rel . movie_id , single = True )
if not isinstance ( rel_dict [ ' info ' ] , dict ) :
log . error ( ' Faulty release found without any info, ignoring. ' )
fireEvent ( ' release.update_status ' , rel . id , status = ignored_status , single = True )
continue
if not isinstance ( rel_dict [ ' info ' ] , ( dict ) ) :
log . error ( ' Faulty release found without any info, ignoring. ' )
# Check if download ID is available
if not rel_dict [ ' info ' ] . get ( ' download_id ' ) or not rel_dict [ ' info ' ] . get ( ' download_downloader ' ) :
log . debug ( ' Download status functionality is not implemented for downloader ( %s ) of release %s . ' , ( rel_dict [ ' info ' ] . get ( ' download_downloader ' , ' unknown ' ) , rel_dict [ ' info ' ] [ ' name ' ] ) )
scan_required = True
# Continue with next release
continue
# Find release in downloaders
nzbname = self . createNzbName ( rel_dict [ ' info ' ] , movie_dict )
found_release = False
for release_download in release_downloads :
found_release = False
if rel_dict [ ' info ' ] . get ( ' download_id ' ) :
if release_download [ ' id ' ] == rel_dict [ ' info ' ] [ ' download_id ' ] and release_download [ ' downloader ' ] == rel_dict [ ' info ' ] [ ' download_downloader ' ] :
log . debug ( ' Found release by id: %s ' , release_download [ ' id ' ] )
found_release = True
break
else :
if release_download [ ' name ' ] == nzbname or rel_dict [ ' info ' ] [ ' name ' ] in release_download [ ' name ' ] or getImdb ( release_download [ ' name ' ] ) == movie_dict [ ' library ' ] [ ' identifier ' ] :
log . debug ( ' Found release by release name or imdb ID: %s ' , release_download [ ' name ' ] )
found_release = True
break
if not found_release :
log . info ( ' %s not found in downloaders ' , nzbname )
#Check status if already missing and for how long, if > 1 week, set to ignored else to missing
if rel . status_id == missing_status . get ( ' id ' ) :
if rel . last_edit < int ( time . time ( ) ) - 7 * 24 * 60 * 60 :
fireEvent ( ' release.update_status ' , rel . id , status = ignored_status , single = True )
continue
# check status
nzbname = self . createNzbName ( rel_dict [ ' info ' ] , movie_dict )
found = False
for release_download in release_downloads :
found_release = False
if rel_dict [ ' info ' ] . get ( ' download_id ' ) :
if release_download [ ' id ' ] == rel_dict [ ' info ' ] [ ' download_id ' ] and release_download [ ' downloader ' ] == rel_dict [ ' info ' ] [ ' download_downloader ' ] :
log . debug ( ' Found release by id: %s ' , release_download [ ' id ' ] )
found_release = True
else :
if release_download [ ' name ' ] == nzbname or rel_dict [ ' info ' ] [ ' name ' ] in release_download [ ' name ' ] or getImdb ( release_download [ ' name ' ] ) == movie_dict [ ' library ' ] [ ' identifier ' ] :
found_release = True
else :
# Set the release to missing
fireEvent ( ' release.update_status ' , rel . id , status = missing_status , single = True )
if found_release :
timeleft = ' N/A ' if release_download [ ' timeleft ' ] == - 1 else release_download [ ' timeleft ' ]
log . debug ( ' Found %s : %s , time to go: %s ' , ( release_download [ ' name ' ] , release_download [ ' status ' ] . upper ( ) , timeleft ) )
# Continue with next release
continue
if release_download [ ' status ' ] == ' busy ' :
# Set the release to snatched if it was missing before
fireEvent ( ' release.update_status ' , rel . id , status = snatched_status , single = True )
# Log that we found the release
timeleft = ' N/A ' if release_download [ ' timeleft ' ] == - 1 else release_download [ ' timeleft ' ]
log . debug ( ' Found %s : %s , time to go: %s ' , ( release_download [ ' name ' ] , release_download [ ' status ' ] . upper ( ) , timeleft ) )
# Tag folder if it is in the 'from' folder and it will not be processed because it is still downloading
if self . movieInFromFolder ( release_download [ ' folder ' ] ) :
self . tagRelease ( release_download = release_download , tag = ' downloading ' )
# Check status of release
if release_download [ ' status ' ] == ' busy ' :
# Set the release to snatched if it was missing before
fireEvent ( ' release.update_status ' , rel . id , status = snatched_status , single = True )
elif release_download [ ' status ' ] == ' seeding ' :
#If linking setting is enabled, process release
if self . conf ( ' file_action ' ) != ' move ' and not rel . status_id == seeding_status . get ( ' id ' ) and self . statusInfoComplete ( release_download ) :
log . info ( ' Download of %s completed! It is now being processed while leaving the original files alone for seeding. Current ratio: %s . ' , ( release_download [ ' name ' ] , release_download [ ' seed_ratio ' ] ) )
# Tag folder if it is in the 'from' folder and it will not be processed because it is still downloading
if self . movieInFromFolder ( release_download [ ' folder ' ] ) :
self . tagRelease ( release_download = release_download , tag = ' downloading ' )
# Remove the downloading tag
self . untagRelease ( release_download = release_download , tag = ' downloading ' )
elif release_download [ ' status ' ] == ' seeding ' :
#If linking setting is enabled, process release
if self . conf ( ' file_action ' ) != ' move ' and not rel . status_id == seeding_status . get ( ' id ' ) and self . statusInfoComplete ( release_download ) :
log . info ( ' Download of %s completed! It is now being processed while leaving the original files alone for seeding. Current ratio: %s . ' , ( release_download [ ' name ' ] , release_download [ ' seed_ratio ' ] ) )
# Scan and set the torrent to paused if required
release_download . update ( { ' pause ' : True , ' scan ' : True , ' process_complete ' : False } )
scan_releases . append ( release_download )
else :
#let it seed
log . debug ( ' %s is seeding with ratio: %s ' , ( release_download [ ' name ' ] , release_download [ ' seed_ratio ' ] ) )
# Remove the downloading tag
self . untagRelease ( release_download = release_download , tag = ' downloading ' )
# Set the release to seeding
fireEvent ( ' release.update_status ' , rel . id , status = seeding_status , single = True )
elif release_download [ ' status ' ] == ' failed ' :
# Set the release to failed
fireEvent ( ' release.update_status ' , rel . id , status = failed_status , single = True )
fireEvent ( ' download.remove_failed ' , release_download , single = True )
if self . conf ( ' next_on_failed ' ) :
fireEvent ( ' movie.searcher.try_next_release ' , movie_id = rel . movie_id )
elif release_download [ ' status ' ] == ' completed ' :
log . info ( ' Download of %s completed! ' , release_download [ ' name ' ] )
if self . statusInfoComplete ( release_download ) :
# If the release has been seeding, process now the seeding is done
if rel . status_id == seeding_status . get ( ' id ' ) :
if self . conf ( ' file_action ' ) != ' move ' :
# Set the release to done as the movie has already been renamed
fireEvent ( ' release.update_status ' , rel . id , status = downloaded_status , single = True )
# Allow the downloader to clean-up
release_download . update ( { ' pause ' : False , ' scan ' : False , ' process_complete ' : True } )
scan_releases . append ( release_download )
else :
# Scan and Allow the downloader to clean-up
release_download . update ( { ' pause ' : False , ' scan ' : True , ' process_complete ' : True } )
scan_releases . append ( release_download )
else :
# Set the release to snatched if it was missing before
fireEvent ( ' release.update_status ' , rel . id , status = snatched_status , single = True )
# Remove the downloading tag
self . untagRelease ( release_download = release_download , tag = ' downloading ' )
# Scan and Allow the downloader to clean-up
release_download . update ( { ' pause ' : False , ' scan ' : True , ' process_complete ' : True } )
scan_releases . append ( release_download )
else :
scan_required = True
found = True
break
# Scan and set the torrent to paused if required
release_download . update ( { ' pause ' : True , ' scan ' : True , ' process_complete ' : False } )
scan_releases . append ( release_download )
else :
#let it seed
log . debug ( ' %s is seeding with ratio: %s ' , ( release_download [ ' name ' ] , release_download [ ' seed_ratio ' ] ) )
# Set the release to seeding
fireEvent ( ' release.update_status ' , rel . id , status = seeding_status , single = True )
elif release_download [ ' status ' ] == ' failed ' :
# Set the release to failed
fireEvent ( ' release.update_status ' , rel . id , status = failed_status , single = True )
fireEvent ( ' download.remove_failed ' , release_download , single = True )
if self . conf ( ' next_on_failed ' ) :
fireEvent ( ' movie.searcher.try_next_release ' , media_id = rel . movie_id )
elif release_download [ ' status ' ] == ' completed ' :
log . info ( ' Download of %s completed! ' , release_download [ ' name ' ] )
if not found :
log . info ( ' %s not found in downloaders ' , nzbname )
#Make sure the downloader sent over a path to look in
if self . statusInfoComplete ( release_download ) :
#Check status if already missing and for how long, if > 1 week, set to ignored else to missing
if rel . status_id == missing_status . get ( ' id ' ) :
if rel . last_edit < int ( time . time ( ) ) - 7 * 24 * 60 * 60 :
fireEvent ( ' release.update_status ' , rel . id , status = ignored_status , single = True )
# If the release has been seeding, process now the seeding is done
if rel . status_id == seeding_status . get ( ' id ' ) :
if self . conf ( ' file_action ' ) != ' move ' :
# Set the release to done as the movie has already been renamed
fireEvent ( ' release.update_status ' , rel . id , status = downloaded_status , single = True )
# Allow the downloader to clean-up
release_download . update ( { ' pause ' : False , ' scan ' : False , ' process_complete ' : True } )
scan_releases . append ( release_download )
else :
# Set the release to missing
fireEvent ( ' release.update_status ' , rel . id , status = missing_status , single = True )
# Scan and Allow the downloader to clean-up
release_download . update ( { ' pause ' : False , ' scan ' : True , ' process_complete ' : True } )
scan_releases . append ( release_download )
except :
log . error ( ' Failed checking for release in downloader: %s ' , traceback . format_exc ( ) )
else :
# Set the release to snatched if it was missing before
fireEvent ( ' release.update_status ' , rel . id , status = snatched_status , single = True )
# Remove the downloading tag
self . untagRelease ( release_download = release_download , tag = ' downloading ' )
# Scan and Allow the downloader to clean-up
release_download . update ( { ' pause ' : False , ' scan ' : True , ' process_complete ' : True } )
scan_releases . append ( release_download )
else :
scan_required = True
except :
log . error ( ' Failed checking for release in downloader: %s ' , traceback . format_exc ( ) )
# The following can either be done here, or inside the scanner if we pass it scan_items in one go
for release_download in scan_releases :
@ -933,7 +1022,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
if release_download [ ' scan ' ] :
if release_download [ ' pause ' ] and self . conf ( ' file_action ' ) == ' link ' :
fireEvent ( ' download.pause ' , release_download = release_download , pause = True , single = True )
fireEvent ( ' renamer.scan ' , release_download = release_download )
self . scan ( release_download = release_download )
if release_download [ ' pause ' ] and self . conf ( ' file_action ' ) == ' link ' :
fireEvent ( ' download.pause ' , release_download = release_download , pause = False , single = True )
if release_download [ ' process_complete ' ] :
@ -944,11 +1033,10 @@ Remove it if you want it to be renamed (again, or at least let it try again)
# Ask the downloader to process the item
fireEvent ( ' download.process_complete ' , release_download = release_download , single = True )
if scan_required :
fireEvent ( ' renamer.scan ' )
if fire_scan and ( scan_required or len ( no_status_support ) > 0 ) :
self . scan ( )
self . checking_snatched = False
return True
def extendReleaseDownload ( self , release_download ) :
@ -993,12 +1081,12 @@ Remove it if you want it to be renamed (again, or at least let it try again)
return src in group [ ' before_rename ' ]
def statusInfoComplete ( self , release_download ) :
return release_download [ ' id ' ] and release_download [ ' downloader ' ] and release_download [ ' folder ' ]
return release_download . get ( ' id ' ) and release_download . get ( ' downloader ' ) and release_download . get ( ' folder ' )
def movieInFromFolder ( self , movi e_folder ) :
return movi e_folder and sp ( self . conf ( ' from ' ) ) in sp ( movie_folder ) or not movi e_folder
def movieInFromFolder ( self , media _folder ) :
return media _folder and isSubFolder ( media_folder , sp ( self . conf ( ' from ' ) ) ) or not media _folder
def extractFiles ( self , folder = None , movi e_folder = None , files = None , cleanup = False ) :
def extractFiles ( self , folder = None , media _folder = None , files = None , cleanup = False ) :
if not files : files = [ ]
# RegEx for finding rar files
@ -1013,7 +1101,7 @@ Remove it if you want it to be renamed (again, or at least let it try again)
folder = from_folder
check_file_date = True
if movi e_folder :
if media _folder :
check_file_date = False
if not files :
@ -1109,18 +1197,18 @@ Remove it if you want it to be renamed (again, or at least let it try again)
if cleanup :
# Remove all left over folders
log . debug ( ' Removing old movie folder %s ... ' , movi e_folder )
self . deleteEmptyFolder ( movi e_folder )
log . debug ( ' Removing old movie folder %s ... ' , media _folder )
self . deleteEmptyFolder ( media _folder )
movi e_folder = os . path . join ( from_folder , os . path . relpath ( movi e_folder , folder ) )
media _folder = os . path . join ( from_folder , os . path . relpath ( media _folder , folder ) )
folder = from_folder
if extr_files :
files . extend ( extr_files )
# Cleanup files and folder if movi e_folder was not provided
if not movi e_folder :
# Cleanup files and folder if media _folder was not provided
if not media _folder :
files = [ ]
folder = None
return folder , movi e_folder , files , extr_files
return folder , media _folder , files , extr_files