Commit 313d7fdb authored by echel0n's avatar echel0n
Browse files

Fixed issues with unrar and windows platforms

Fixed issues with unrar and *nix platforms
Added option to set unpack location
parent 7682ad1c
# Changelog
- * b0b60fb - 2017-12-17: Fixed issue #153 - Checking delete files when removing a show didn't actually delete the files Added code to remove queue item to be ignored when listing shows
- * feb4197 - 2017-12-17: Fixed issues with unrar and windows platforms Fixed issues with unrar and *nix platforms Added option to set unpack location
- * 7682ad1 - 2017-12-17: Fixed issue #153 - Checking delete files when removing a show didn't actually delete the files Added code to remove queue item to be ignored when listing shows
- * 3c60c67 - 2017-12-16: Release v9.2.65
- * d53ccb0 - 2017-12-16: Fixed url issue
- * 1c5d901 - 2017-12-16: refactored torrent cache api calls
......
......@@ -3472,6 +3472,7 @@ jQuery(document).ready(function ($) {
});
$('#tv_download_dir').fileBrowser({title: gt('Select TV Download Directory')});
$('#unpack_dir').fileBrowser({title: gt('Select UNPACK Directory')});
},
typewatch: function () {
......
......@@ -168,6 +168,7 @@ class Config(object):
self.nfo_rename = True
self.tv_download_dir = ""
self.unpack = False
self.unpack_dir = ""
self.skip_removed_files = False
self.allowed_extensions = ""
self.nzbs = False
......@@ -758,6 +759,7 @@ class Config(object):
'web_port': 8081,
'launch_browser': False,
'unpack': False,
'unpack_dir': "",
'delete_non_associated_files': True,
'move_associated_files': False,
'naming_multi_ep': 1,
......@@ -977,12 +979,11 @@ class Config(object):
# Download
if not found:
sickrage.app.log.info('Trying to download unrar.exe and set the path')
unrar_dir = os.path.join(sickrage.PROG_DIR, 'unrar')
unrar_zip = os.path.join(unrar_dir, 'unrar_win.zip')
unrar_zip = os.path.join(sickrage.app.data_dir, 'unrar_win.zip')
if (WebSession().download("https://sickrage.ca/downloads/unrar_win.zip",
filename=unrar_zip) and extract_zipfile(archive=unrar_zip,
targetDir=unrar_dir)):
if WebSession().download("https://sickrage.ca/downloads/unrar_win.zip",
filename=unrar_zip) and extract_zipfile(archive=unrar_zip,
targetDir=sickrage.app.data_dir):
try:
os.remove(unrar_zip)
except OSError as e:
......@@ -990,14 +991,14 @@ class Config(object):
"Unable to delete downloaded file {}: {}. You may delete it manually".format(unrar_zip,
e.strerror))
check = os.path.join(unrar_dir, "unrar.exe")
check = os.path.join(sickrage.app.data_dir, "unrar.exe")
try:
rarfile.custom_check(check)
unrar_tool = check
sickrage.app.log.info('Successfully downloaded unrar.exe and set as unrar tool')
except (rarfile.RarCannotExec, rarfile.RarExecError, OSError, IOError):
sickrage.app.log.info(
'Sorry, unrar was not set up correctly. Try installing WinRAR and make sure it is on the system PATH')
sickrage.app.log.info('Sorry, unrar was not set up correctly. Try installing WinRAR and '
'make sure it is on the system PATH')
else:
sickrage.app.log.info('Unable to download unrar.exe')
......@@ -1494,6 +1495,7 @@ class Config(object):
self.process_automatically = self.check_setting_bool('General', 'process_automatically')
self.no_delete = self.check_setting_bool('General', 'no_delete')
self.unpack = self.check_setting_bool('General', 'unpack')
self.unpack_dir = self.check_setting_str('General', 'unpack_dir')
self.rename_episodes = self.check_setting_bool('General', 'rename_episodes')
self.airdate_episodes = self.check_setting_bool('General', 'airdate_episodes')
self.file_timestamp_timezone = self.check_setting_str('General', 'file_timestamp_timezone')
......@@ -1988,6 +1990,7 @@ class Config(object):
'process_automatically': int(self.process_automatically),
'no_delete': int(self.no_delete),
'unpack': int(self.unpack),
'unpack_dir': self.unpack_dir,
'rename_episodes': int(self.rename_episodes),
'airdate_episodes': int(self.airdate_episodes),
'file_timestamp_timezone': self.file_timestamp_timezone,
......
......@@ -317,11 +317,7 @@ def is_media_file(filename):
if re.search('extras?$', sepFile[0], re.I):
return False
if sepFile[2].lower() in mediaExtensions:
return True
else:
return False
return sepFile[-1].lower() in mediaExtensions
def is_rar_file(filename):
"""
......
......@@ -22,9 +22,7 @@ import os
import shutil
import stat
import UnRAR2
from UnRAR2.rar_exceptions import ArchiveHeaderBroken, FileOpenError, \
IncorrectRARPassword, InvalidRARArchive, InvalidRARArchiveUsage
import rarfile
import sickrage
from sickrage.core.common import Quality
......@@ -47,6 +45,7 @@ class ProcessResult(object):
def __unicode__(self):
return self.output
def delete_folder(folder, check_empty=True):
"""
Removes a folder from the filesystem
......@@ -342,92 +341,110 @@ def validateDir(process_path, release_name, failed, result):
return False
def unrar(path, rarFiles, force, result):
def unrar(path, rar_files, force, result):
"""
Extracts RAR files
:param path: Path to look for files in
:param rarFiles: Names of RAR files
:param rar_files: Names of RAR files
:param force: process currently processing items
:param result: Previous results
:return: List of unpacked file names
"""
unpacked_files = []
unpacked_dirs = []
if sickrage.app.config.unpack and rarFiles:
if sickrage.app.config.unpack == 1 and rar_files:
result.output += logHelper("Packed Releases detected: {0}".format(rar_files), sickrage.app.log.DEBUG)
for archive in rar_files:
failure = None
rar_handle = None
try:
archive_path = os.path.join(path, archive)
if already_postprocessed(path, archive, force, result):
result.output += logHelper("Archive file already post-processed, extraction skipped: {}".format
(archive_path), sickrage.app.log.DEBUG)
continue
result.output += logHelper("Packed Releases detected: " + str(rarFiles), sickrage.app.log.DEBUG)
if not is_rar_file(archive_path):
continue
for archive in rarFiles:
result.output += logHelper("Checking if archive is valid and contains a video: {}".format(archive_path),
sickrage.app.log.DEBUG)
rar_handle = rarfile.RarFile(archive_path)
if rar_handle.needs_password():
# TODO: Add support in settings for a list of passwords to try here with rar_handle.set_password(x)
result.output += logHelper('Archive needs a password, skipping: {0}'.format(archive_path))
continue
result.output += logHelper("Unpacking archive: " + archive, sickrage.app.log.DEBUG)
# If there are no video files in the rar, don't extract it
rar_media_files = filter(is_media_file, rar_handle.namelist())
if not rar_media_files:
continue
try:
rar_handle = UnRAR2.RarFile(os.path.join(path, archive))
rar_release_name = archive.rpartition('.')[0]
# Skip extraction if any file in archive has previously been extracted
skip_file = False
for file_in_archive in [os.path.basename(x.filename) for x in rar_handle.infolist() if not x.isdir]:
if already_postprocessed(path, file_in_archive, force, result):
# Choose the directory we'll unpack to:
if sickrage.app.config.unpack_dir and os.path.isdir(sickrage.app.config.unpack_dir):
unpack_base_dir = sickrage.app.config.unpack_dir
else:
unpack_base_dir = path
if sickrage.app.config.unpack_dir: # Let user know if we can't unpack there
result.output += logHelper('Unpack directory cannot be verified. Using {}'.format(path),
sickrage.app.log.DEBUG)
# Fix up the list for checking if already processed
rar_media_files = [os.path.join(unpack_base_dir, rar_release_name, rar_media_file) for rar_media_file in
rar_media_files]
skip_rar = False
for rar_media_file in rar_media_files:
check_path, check_file = os.path.split(rar_media_file)
if already_postprocessed(check_path, check_file, force, result):
result.output += logHelper(
"Archive file already post-processed, extraction skipped: " + file_in_archive,
sickrage.app.log.DEBUG)
skip_file = True
"Archive file already post-processed, extraction skipped: {0}".format
(rar_media_file), sickrage.app.log.DEBUG)
skip_rar = True
break
if skip_file:
if skip_rar:
continue
rar_handle.extract(path=path, withSubpath=False, overwrite=False)
for x in rar_handle.infolist():
if not x.isdir:
basename = os.path.basename(x.filename)
if basename not in unpacked_files:
unpacked_files.append(basename)
del rar_handle
except ArchiveHeaderBroken as e:
result.output += logHelper("Failed Unrar archive {0}: Unrar: Archive Header Broken".format(archive),
sickrage.app.log.ERROR)
result.result = False
result.missedfiles.append(archive + " : Unpacking failed because the Archive Header is Broken")
rar_extract_path = os.path.join(unpack_base_dir, rar_release_name)
result.output += logHelper("Unpacking archive: {0}".format(archive), sickrage.app.log.DEBUG)
rar_handle.extractall(path=rar_extract_path)
unpacked_dirs.append(rar_extract_path)
except rarfile.RarCRCError:
failure = ('Archive Broken', 'Unpacking failed because of a CRC error')
except rarfile.RarWrongPassword:
failure = ('Incorrect RAR Password', 'Unpacking failed because of an Incorrect Rar Password')
except rarfile.PasswordRequired:
failure = ('Rar is password protected', 'Unpacking failed because it needs a password')
except rarfile.RarOpenError:
failure = ('Rar Open Error, check the parent folder and destination file permissions.',
'Unpacking failed with a File Open Error (file permissions?)')
except rarfile.RarExecError:
failure = ('Invalid Rar Archive Usage',
'Unpacking Failed with Invalid Rar Archive Usage. Is unrar installed and on the system PATH?')
except rarfile.BadRarFile:
failure = ('Invalid Rar Archive', 'Unpacking Failed with an Invalid Rar Archive Error')
except rarfile.NeedFirstVolume:
continue
except IncorrectRARPassword:
result.output += logHelper("Failed Unrar archive {0}: Unrar: Incorrect Rar Password".format(archive),
sickrage.app.log.ERROR)
except (Exception, rarfile.Error) as e:
failure = (e, 'Unpacking failed')
finally:
if rar_handle:
del rar_handle
if failure:
result.output += logHelper('Failed to extract the archive {}: {}'.format(archive, failure[0]),
sickrage.app.log.WARNING)
result.missed_files.append('{} : Unpacking failed: {}'.format(archive, failure[1]))
result.result = False
result.missedfiles.append(archive + " : Unpacking failed because of an Incorrect Rar Password")
continue
except FileOpenError:
result.output += logHelper(
"Failed Unrar archive {0}: Unrar: File Open Error, check the parent folder and destination file permissions.".format(
archive), sickrage.app.log.ERROR)
result.result = False
result.missedfiles.append(archive + " : Unpacking failed with a File Open Error (file permissions?)")
continue
except InvalidRARArchiveUsage:
result.output += logHelper("Failed Unrar archive {0}: Unrar: Invalid Rar Archive Usage".format(archive),
sickrage.app.log.ERROR)
result.result = False
result.missedfiles.append(archive + " : Unpacking Failed with Invalid Rar Archive Usage")
continue
except InvalidRARArchive:
result.output += logHelper("Failed Unrar archive {0}: Unrar: Invalid Rar Archive".format(archive),
sickrage.app.log.ERROR)
result.result = False
result.missedfiles.append(archive + " : Unpacking Failed with an Invalid Rar Archive Error")
continue
except Exception as e:
result.output += logHelper("Failed Unrar archive {}: {}".format(archive, e),
sickrage.app.log.ERROR)
result.result = False
result.missedfiles.append(archive + " : Unpacking failed for an unknown reason")
continue
result.output += logHelper("UnRar content: " + str(unpacked_files), sickrage.app.log.DEBUG)
return unpacked_files
return unpacked_dirs
def already_postprocessed(dirName, videofile, force, result):
......
<%inherit file="../layouts/config.mako"/>
<%def name='formaction()'><% return 'savePostProcessing' %></%def>
<%!
import sys
import os.path
import sickrage
......@@ -284,24 +285,44 @@
<label class="component-title">${_('Unpack')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<input id="unpack" type="checkbox"
<input id="unpack" class="enabler" type="checkbox"
name="unpack" ${('', 'checked')[bool(sickrage.app.config.unpack)]} />
<label for="unpack">
${_('Unpack any TV releases in your')} <i>${_('TV Download Dir')}</i>?<br/>
<b>${_('NOTE:')}</b> ${_('Only working with RAR archive')}
<b>${_('NOTE:')}</b> ${_('Only works with RAR archives')}
</label>
</div>
</div>
<div class="row field-pair">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('Delete RAR contents')}</label>
<div id="content_unpack">
<div class="row field-pair">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('Unpack Directory')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<div class="input-group input350">
<div class="input-group-addon">
<span class="glyphicon glyphicon-folder-open"></span>
</div>
<input name="unpack_dir" id="unpack_dir"
value="${'|'.join(sickrage.app.config.unpack_dir)}"
class="form-control" autocapitalize="off"/>
</div>
<label for="unpack_dir">
${_('Choose a path to unpack files, leave blank to unpack in download dir')}
</label>
</div>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<input type="checkbox" name="del_rar_contents"
id="del_rar_contents" ${('', 'checked')[bool(sickrage.app.config.delrarcontents)]}/>
<label for="del_rar_contents">
${_('Delete content of RAR files, even if Process Method not set to move?')}
</label>
<div class="row field-pair">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">${_('Delete RAR contents')}</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<input type="checkbox" name="del_rar_contents"
id="del_rar_contents" ${('', 'checked')[bool(sickrage.app.config.delrarcontents)]}/>
<label for="del_rar_contents">
${_('Delete content of RAR files, even if Process Method not set to move?')}
</label>
</div>
</div>
</div>
<div class="row field-pair">
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment