|
|
|
from couchpotato import get_session
|
|
|
|
from couchpotato.core.event import addEvent, fireEvent
|
|
|
|
from couchpotato.core.helpers.encoding import toUnicode
|
|
|
|
from couchpotato.core.helpers.variable import getExt
|
|
|
|
from couchpotato.core.logger import CPLog
|
|
|
|
from couchpotato.core.plugins.base import Plugin
|
|
|
|
from couchpotato.core.settings.model import Library
|
|
|
|
import os.path
|
|
|
|
import re
|
|
|
|
import shutil
|
|
|
|
import traceback
|
|
|
|
|
|
|
|
log = CPLog(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class Renamer(Plugin):
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
|
|
addEvent('renamer.scan', self.scan)
|
|
|
|
#addEvent('app.load', self.scan)
|
|
|
|
|
|
|
|
#fireEvent('schedule.interval', 'renamer.scan', self.scan, minutes = self.conf('run_every'))
|
|
|
|
|
|
|
|
def scan(self):
|
|
|
|
|
|
|
|
groups = fireEvent('scanner.scan', folder = self.conf('from'), single = True)
|
|
|
|
|
|
|
|
destination = self.conf('to')
|
|
|
|
folder_name = self.conf('folder_name')
|
|
|
|
file_name = self.conf('file_name')
|
|
|
|
trailer_name = self.conf('trailer_name')
|
|
|
|
backdrop_name = self.conf('fanart_name')
|
|
|
|
nfo_name = self.conf('nfo_name')
|
|
|
|
separator = self.conf('separator')
|
|
|
|
|
|
|
|
for group_identifier in groups:
|
|
|
|
|
|
|
|
group = groups[group_identifier]
|
|
|
|
rename_files = {}
|
|
|
|
|
|
|
|
# Add _UNKNOWN_ if no library is connected
|
|
|
|
if not group['library']:
|
|
|
|
if group['dirname']:
|
|
|
|
rename_files[group['parentdir']] = group['parentdir'].replace(group['dirname'], '_UNKNOWN_%s' % group['dirname'])
|
|
|
|
else: # Add it to filename
|
|
|
|
for file_type in group['files']:
|
|
|
|
for rename_me in group['files'][file_type]:
|
|
|
|
filename = os.path.basename(rename_me)
|
|
|
|
rename_files[rename_me] = rename_me.replace(filename, '_UNKNOWN_%s' % filename)
|
|
|
|
|
|
|
|
# Rename the files using the library data
|
|
|
|
else:
|
|
|
|
group['library'] = fireEvent('library.update', identifier = group['library']['identifier'], single = True)
|
|
|
|
library = group['library']
|
|
|
|
|
|
|
|
# Find subtitle for renaming
|
|
|
|
fireEvent('renamer.before', group)
|
|
|
|
|
|
|
|
# Remove weird chars from moviename
|
|
|
|
movie_name = re.sub(r"[\x00\/\\:\*\?\"<>\|]", '', group['library']['titles'][0]['title'])
|
|
|
|
|
|
|
|
# Put 'The' at the end
|
|
|
|
name_the = movie_name
|
|
|
|
if movie_name[:4].lower() == 'the ':
|
|
|
|
name_the = movie_name[4:] + ', The'
|
|
|
|
|
|
|
|
replacements = {
|
|
|
|
'ext': 'mkv',
|
|
|
|
'namethe': name_the.strip(),
|
|
|
|
'thename': movie_name.strip(),
|
|
|
|
'year': library['year'],
|
|
|
|
'first': name_the[0].upper(),
|
|
|
|
'dirname': group['dirname'],
|
|
|
|
'quality': group['meta_data']['quality']['label'],
|
|
|
|
'quality_type': group['meta_data']['quality_type'],
|
|
|
|
'video': group['meta_data'].get('video'),
|
|
|
|
'audio': group['meta_data'].get('audio'),
|
|
|
|
'group': group['meta_data']['group'],
|
|
|
|
'source': group['meta_data']['source'],
|
|
|
|
'resolution_width': group['meta_data'].get('resolution_width'),
|
|
|
|
'resolution_height': group['meta_data'].get('resolution_height'),
|
|
|
|
}
|
|
|
|
|
|
|
|
for file_type in group['files']:
|
|
|
|
|
|
|
|
# Move DVD files (no renaming)
|
|
|
|
if group['is_dvd'] and file_type is 'movie':
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Move nfo depending on settings
|
|
|
|
if file_type is 'nfo' and not self.conf('rename_nfo'):
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Subtitle extra
|
|
|
|
if file_type is 'subtitle_extra':
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Move other files
|
|
|
|
multiple = len(group['files']['movie']) > 1
|
|
|
|
cd = 1 if multiple else 0
|
|
|
|
|
|
|
|
for file in sorted(list(group['files'][file_type])):
|
|
|
|
|
|
|
|
# Original filename
|
|
|
|
replacements['original'] = os.path.basename(file)
|
|
|
|
|
|
|
|
# Extension
|
|
|
|
replacements['ext'] = getExt(file)
|
|
|
|
|
|
|
|
# cd #
|
|
|
|
replacements['cd'] = ' cd%d' % cd if cd else ''
|
|
|
|
replacements['cd_nr'] = cd
|
|
|
|
|
|
|
|
# Naming
|
|
|
|
final_folder_name = self.doReplace(folder_name, replacements)
|
|
|
|
final_file_name = self.doReplace(file_name, replacements)
|
|
|
|
replacements['filename'] = final_file_name[:-(len(getExt(final_file_name)) + 1)]
|
|
|
|
|
|
|
|
# Meta naming
|
|
|
|
if file_type is 'trailer':
|
|
|
|
final_file_name = self.doReplace(trailer_name, replacements)
|
|
|
|
elif file_type is 'nfo':
|
|
|
|
final_file_name = self.doReplace(nfo_name, replacements)
|
|
|
|
elif file_type is 'backdrop':
|
|
|
|
final_file_name = self.doReplace(backdrop_name, replacements)
|
|
|
|
|
|
|
|
# Seperator replace
|
|
|
|
if separator:
|
|
|
|
final_file_name = final_file_name.replace(' ', separator)
|
|
|
|
|
|
|
|
# Main file
|
|
|
|
rename_files[file] = os.path.join(destination, final_folder_name, final_file_name)
|
|
|
|
|
|
|
|
# Check for extra subtitle files
|
|
|
|
if file_type is 'subtitle':
|
|
|
|
|
|
|
|
def test(s):
|
|
|
|
return file[:-len(replacements['ext'])] in s
|
|
|
|
|
|
|
|
for subtitle_extra in set(filter(test, group['files']['subtitle_extra'])):
|
|
|
|
replacements['ext'] = getExt(subtitle_extra)
|
|
|
|
|
|
|
|
final_folder_name = self.doReplace(folder_name, replacements)
|
|
|
|
final_file_name = self.doReplace(file_name, replacements)
|
|
|
|
rename_files[subtitle_extra] = os.path.join(destination, final_folder_name, final_file_name)
|
|
|
|
|
|
|
|
if multiple:
|
|
|
|
cd += 1
|
|
|
|
|
|
|
|
# Before renaming, remove the lower quality files
|
|
|
|
db = get_session()
|
|
|
|
library = db.query(Library).filter_by(identifier = group['library']['identifier']).first()
|
|
|
|
for movie in library.movies:
|
|
|
|
for release in movie.releases:
|
|
|
|
if release.quality.order < group['meta_data']['quality']['order']:
|
|
|
|
log.info('Removing older release for %s, with quality %s' % (movie.library.titles[0].title, release.quality.label))
|
|
|
|
elif release.quality.order is group['meta_data']['quality']['order']:
|
|
|
|
log.info('Same quality release already exists for %s, with quality %s. Assuming repack.' % (movie.library.titles[0].title, release.quality.label))
|
|
|
|
else:
|
|
|
|
log.info('Better quality release already exists for %s, with quality %s' % (movie.library.titles[0].title, release.quality.label))
|
|
|
|
|
|
|
|
# Add _EXISTS_ to the parent dir
|
|
|
|
if group['dirname']:
|
|
|
|
for rename_me in rename_files: # Don't rename anything in this group
|
|
|
|
rename_files[rename_me] = None
|
|
|
|
rename_files[group['parentdir']] = group['parentdir'].replace(group['dirname'], '_EXISTS_%s' % group['dirname'])
|
|
|
|
else: # Add it to filename
|
|
|
|
for rename_me in rename_files:
|
|
|
|
filename = os.path.basename(rename_me)
|
|
|
|
rename_files[rename_me] = rename_me.replace(filename, '_EXISTS_%s' % filename)
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
for file in release.files:
|
|
|
|
log.info('Removing "%s"' % file.path)
|
|
|
|
|
|
|
|
# Rename
|
|
|
|
for rename_me in rename_files:
|
|
|
|
if rename_files[rename_me]:
|
|
|
|
log.info('Renaming "%s" to "%s"' % (rename_me, rename_files[rename_me]))
|
|
|
|
|
|
|
|
path = os.path.dirname(rename_files[rename_me])
|
|
|
|
try:
|
|
|
|
if not os.path.isdir(path): os.makedirs(path)
|
|
|
|
except:
|
|
|
|
log.error('Failed creating dir %s: %s' % (path, traceback.format_exc()))
|
|
|
|
continue
|
|
|
|
|
|
|
|
#print rename_me, rename_files[rename_me]
|
|
|
|
|
|
|
|
# Search for trailers
|
|
|
|
fireEvent('renamer.after', group)
|
|
|
|
|
|
|
|
def moveFile(self, old, dest, suppress = True):
|
|
|
|
try:
|
|
|
|
shutil.move(old, dest)
|
|
|
|
except:
|
|
|
|
log.error("Couldn't move file '%s' to '%s': %s" % (old, dest, traceback.format_exc()))
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def doReplace(self, string, replacements):
|
|
|
|
'''
|
|
|
|
replace confignames with the real thing
|
|
|
|
'''
|
|
|
|
|
|
|
|
replaced = toUnicode(string)
|
|
|
|
for x, r in replacements.iteritems():
|
|
|
|
if r is not None:
|
|
|
|
replaced = replaced.replace('<%s>' % toUnicode(x), toUnicode(r))
|
|
|
|
else:
|
|
|
|
#If information is not available, we don't want the tag in the filename
|
|
|
|
replaced = replaced.replace('<' + x + '>', '')
|
|
|
|
|
|
|
|
replaced = re.sub(r"[\x00:\*\?\"<>\|]", '', replaced)
|
|
|
|
|
|
|
|
sep = self.conf('separator')
|
|
|
|
return self.replaceDoubles(replaced).replace(' ', ' ' if not sep else sep)
|
|
|
|
|
|
|
|
def replaceDoubles(self, string):
|
|
|
|
return string.replace(' ', ' ').replace(' .', '.')
|