Commit 6f42bec8 authored by SVN-Git Migration's avatar SVN-Git Migration

Imported Upstream version 0.7.6

parent b98792ac
*******************************************
*** This is SABnzbd 0.7.5 ***
*** This is SABnzbd 0.7.6 ***
*******************************************
SABnzbd is an open-source cross-platform binary newsreader.
It simplifies the process of downloading from Usenet dramatically,
......
-------------------------------------------------------------------------------
0.7.6Final by The SABnzbd-Team
-------------------------------------------------------------------------------
- Recursive scanning when re-queuing downloaded NZB files
- Log "User-Agent" header of API calls
-------------------------------------------------------------------------------
0.7.6Beta2 by The SABnzbd-Team
-------------------------------------------------------------------------------
- A damaged smallest par2 can block fetching of more par2 files
- Fix evaluation of schedules at startup
- Make check for running SABnzbd instance more robust
-------------------------------------------------------------------------------
0.7.6Beta1 by The SABnzbd-Team
-------------------------------------------------------------------------------
- Handle par2 sets that were renamed after creation
- Prevent blocking assembly of completed files, ( this resulted in
excessive CPU and memory usage)
- Fix speed issues with some Usenet servers due to unreachable IPv6 addresses
- Fix issues with SFV-base checks
- Prevent crash on Unix-Pythons that don't have the os.getloadavg() function
- Successfully pre-checked job lost its attributes when those were changed during check
- Remove version check when looking for a running instance of SABnzbd
-------------------------------------------------------------------------------
0.7.5Final by The SABnzbd-Team
-------------------------------------------------------------------------------
......
SABnzbd 0.7.5
SABnzbd 0.7.6
-------------------------------------------------------------------------------
0) LICENSE
......@@ -60,7 +60,8 @@ Unix/Linux/OSX
OSX Leopard/SnowLeopard
Python 2.6 http://www.activestate.com
OSX Lion Apple Python 2.7 (included in OSX)
OSX Lion/MountainLion
Apple Python 2.7 Included in OSX (default)
Windows
Python-2.7.latest http://www.activestate.com
......
Metadata-Version: 1.0
Name: SABnzbd
Version: 0.7.5
Summary: SABnzbd-0.7.5
Version: 0.7.6
Summary: SABnzbd-0.7.6
Home-page: http://sabnzbd.org
Author: The SABnzbd Team
Author-email: team@sabnzbd.org
......
Release Notes - SABnzbd 0.7.5
Release Notes - SABnzbd 0.7.6
===============================
## Features
- Update nzbmatrix category table (check your categories!)
- Add special options 'empty_postproc' and 'prio_sort_list' (See Wiki)
- OSX: Retina compatible menu-bar icons
- Properly handle par2-sets that were renamed after creation by the poster
- Recursive scanning when re-queuing downloaded NZB files
## Bug fixes
- Prevent stuck jobs at end of pre-check
- Fix issues with accented and special characters in names of downloaded files
- Fix problem with "Read" button when RSS feed name contains "&"
- Prevent unusual SFV files from crashing post-processing
- Added missing %dn formula to Generic Sort
- Prevent blocking assembly of completed files, (this resulted in excessive CPU and memory usage)
- Fix speed issues with some Usenet servers due to unreachable IPv6 addresses
- Fix issues with SFV-base checks
- Successfully pre-checked job lost its attributes when those were changed during check
- No longer check version when looking for a running instance of SABnzbd (this prevents unintended multiple instances).
- A damaged base par2 file could block download of more par2 files
- Fix evaluation of schedules at startup
- Fix possible failing startup when running as a Windows Service
## What's new in 0.7.0
......
......@@ -28,6 +28,7 @@ import signal
import socket
import platform
import time
import re
try:
import Cheetah
......@@ -691,10 +692,7 @@ def is_sabnzbd_running(url):
try:
url = '%s&mode=version' % (url)
ver = sabnzbd.newsunpack.get_from_url(url)
if ver and ver.strip(' \n\r\t') == sabnzbd.__version__:
return True
else:
return False
return bool(ver and re.search(r'\d+\.\d+\.', ver))
except:
return False
......@@ -714,7 +712,7 @@ def find_free_port(host, currentport):
def check_for_sabnzbd(url, upload_nzbs, allow_browser=True):
""" Check for a running instance of sabnzbd(same version) on this port
""" Check for a running instance of sabnzbd on this port
allow_browser==True|None will launch the browser, False will not.
"""
if allow_browser is None:
......
......@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-09-10 17:12+0000\n"
"PO-Revision-Date: 2012-09-25 03:49+0000\n"
"Last-Translator: Joel Pedraza <Unknown>\n"
"PO-Revision-Date: 2012-10-21 17:25+0000\n"
"Last-Translator: Juanma <Unknown>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-09-26 05:07+0000\n"
"X-Generator: Launchpad (build 16022)\n"
"X-Launchpad-Export-Date: 2012-10-22 04:51+0000\n"
"X-Generator: Launchpad (build 16165)\n"
#: SABnzbd.py:302 [Error message]
msgid "Failed to start web-interface"
......@@ -3867,7 +3867,7 @@ msgstr "Purgar"
#: sabnzbd/skintext.py:755
msgid "left"
msgstr "Izquierda"
msgstr "Restante"
#: sabnzbd/skintext.py:756 [Used in speed menu. Split in two lines if too long.]
msgid "Max Speed"
......
......@@ -302,10 +302,11 @@ def initialize(pause_downloader = False, clean_up = False, evalSched=False, repa
PostProcessor()
NzbQueue()
NzbQueue.do.read_queue(repair)
Assembler()
NzbQueue.do.read_queue(repair)
Downloader(pause_downloader or paused)
DirScanner()
......
......@@ -139,7 +139,7 @@ def _assemble(nzf, path, dupe):
decodetable = nzf.decodetable
for articlenum in decodetable:
sleep(0.01)
sleep(0.001)
article = decodetable[articlenum]
data = ArticleCache.do.load_article(article)
......
......@@ -218,6 +218,7 @@ ssl_type = OptionStr('misc', 'ssl_type', 'v23')
unpack_check = OptionBool('misc', 'unpack_check', True)
no_penalties = OptionBool('misc', 'no_penalties', False)
randomize_server_ip = OptionBool('misc', 'randomize_server_ip', False)
ipv6_servers = OptionNumber('misc', 'ipv6_servers', 1, 0, 2)
# Internal options, not saved in INI file
debug_delay = OptionNumber('misc', 'debug_delay', 0, add=False)
......@@ -226,6 +227,7 @@ api_key = OptionStr('misc', 'api_key', create_api_key())
nzb_key = OptionStr('misc', 'nzb_key', create_api_key())
disable_key = OptionBool('misc', 'disable_api_key', False)
api_warnings = OptionBool('misc', 'api_warnings', True)
local_range = OptionStr('misc', 'local_range')
max_art_tries = OptionNumber('misc', 'max_art_tries', 3, 2)
max_art_opt = OptionBool('misc', 'max_art_opt', False)
use_pickle = OptionBool('misc', 'use_pickle', False)
......
......@@ -65,6 +65,7 @@ FUTURE_Q_FOLDER = 'future'
JOB_ADMIN = '__ADMIN__'
VERIFIED_FILE = '__verified__'
QCHECK_FILE = '__skip_qcheck__'
RENAMES_FILE = '__renames__'
ATTRIB_FILE = 'SABnzbd_attrib'
REPAIR_REQUEST = 'repair-all.sab'
......
......@@ -23,6 +23,7 @@ import Queue
import binascii
import logging
import re
from time import sleep
from threading import Thread
try:
import _yenc
......@@ -72,6 +73,7 @@ class Decoder(Thread):
def run(self):
from sabnzbd.nzbqueue import NzbQueue
while 1:
sleep(0.001)
art_tup = self.queue.get()
if not art_tup:
break
......
This diff is collapsed.
......@@ -39,7 +39,7 @@ except:
import sabnzbd
from sabnzbd.decorators import synchronized
from sabnzbd.constants import DEFAULT_PRIORITY, FUTURE_Q_FOLDER, JOB_ADMIN, GIGI, VERIFIED_FILE, Status, MEBI
from sabnzbd.constants import DEFAULT_PRIORITY, FUTURE_Q_FOLDER, JOB_ADMIN, GIGI, Status, MEBI
import sabnzbd.config as config
import sabnzbd.cfg as cfg
from sabnzbd.encoding import unicoder, latin1
......@@ -1010,7 +1010,7 @@ def memory_usage():
res = int(_PAGE_SIZE * int(v[1]) / MEBI)
return "V=%sM R=%sM" % (virt, res)
except:
return None
return ''
try:
_PAGE_SIZE = os.sysconf("SC_PAGE_SIZE")
......@@ -1026,7 +1026,10 @@ def loadavg():
if not sabnzbd.WIN32 and not sabnzbd.DARWIN:
opt = cfg.show_sysload()
if opt:
p = '%.2f | %.2f | %.2f' % os.getloadavg()
try:
p = '%.2f | %.2f | %.2f' % os.getloadavg()
except:
pass
if opt > 1 and _HAVE_STATM:
p = '%s | %s' % (p, memory_usage())
return p
......@@ -1078,7 +1081,11 @@ def int_conv(value):
# Diskfree
if sabnzbd.WIN32:
# windows diskfree
import win32api
try:
# Careful here, because win32api test hasn't been done yet!
import win32api
except:
pass
def diskfree(_dir):
""" Return amount of free diskspace in GBytes
"""
......
......@@ -35,7 +35,8 @@ from sabnzbd.misc import format_time_string, find_on_path, make_script_path, int
flag_file
from sabnzbd.tvsort import SeriesSorter
import sabnzbd.cfg as cfg
from constants import Status, QCHECK_FILE
from sabnzbd.constants import Status, QCHECK_FILE, RENAMES_FILE
load_data = save_data = None
if sabnzbd.WIN32:
try:
......@@ -78,6 +79,7 @@ CURL_COMMAND = None
def find_programs(curdir):
"""Find external programs
"""
global load_data, save_data
def check(path, program):
p = os.path.abspath(os.path.join(path, program))
if os.access(p, os.X_OK):
......@@ -85,6 +87,10 @@ def find_programs(curdir):
else:
return None
# Another crazy Python import bug work-around
load_data = sabnzbd.load_data
save_data = sabnzbd.save_data
if sabnzbd.DARWIN:
try:
os_version = subprocess.Popen("sw_vers -productVersion", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stdout.read()
......@@ -888,6 +894,8 @@ def par2_repair(parfile_nzf, nzo, workdir, setname):
_RE_BLOCK_FOUND = re.compile('File: "([^"]+)" - found \d+ of \d+ data blocks from "([^"]+)"')
_RE_IS_MATCH_FOR = re.compile('File: "([^"]+)" - is a match for "([^"]+)"')
def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
""" Run par2 on par-set """
if cfg.never_repair():
......@@ -918,6 +926,9 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
if setname in joinable:
command.append(joinable)
# Append the wildcard for this set
command.append('%s*' % os.path.join(os.path.split(parfile)[0], setname))
stup, need_shell, command, creationflags = build_command(command)
logging.debug('Starting par2: %s', command)
......@@ -935,6 +946,7 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
# Set up our variables
pars = []
datafiles = []
renames = {}
linebuf = ''
finished = 0
......@@ -965,12 +977,7 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
if 'Repairing:' not in line:
lines.append(line)
if 'The recovery file does not exist' in line:
logging.info('%s', line)
nzo.set_unpack_info('Repair', unicoder(line), set=setname)
nzo.status = Status.FAILED
elif line.startswith('Invalid option specified'):
if line.startswith('Invalid option specified'):
msg = T('[%s] PAR2 received incorrect options, check your Config->Switches settings') % unicoder(setname)
nzo.set_unpack_info('Repair', msg, set=setname)
nzo.status = Status.FAILED
......@@ -990,7 +997,7 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
start = time()
verified = 1
elif line.startswith('Main packet not found'):
elif line.startswith('Main packet not found') or 'The recovery file does not exist' in line:
## Initialparfile probably didn't decode properly,
logging.info(Ta('Main packet not found...'))
......@@ -1009,8 +1016,13 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
logging.info("Found new par2file %s", nzf.filename)
## Move from extrapar list to files to be downloaded
nzo.add_parfile(nzf)
extrapars.remove(nzf)
## Now set new par2 file as primary par2
nzo.partable[setname] = nzf
nzf.extrapars= extrapars
parfile_nzf = []
## mark for readd
readd = True
else:
......@@ -1129,6 +1141,15 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
# Hit a bug in par2-tbb, retry with par2-classic
retry_classic = True
# File: "oldname.rar" - is a match for "newname.rar".
elif 'is a match for' in line:
m = _RE_IS_MATCH_FOR.search(line)
if m:
old_name = m.group(1)
new_name = m.group(2)
logging.debug('PAR2 will rename "%s" to "%s"', old_name, new_name)
renames[new_name] = old_name
elif not verified:
if line.startswith('Verifying source files'):
nzo.set_action_line(T('Verifying'), '01/%02d' % verifytotal)
......@@ -1169,6 +1190,13 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=False):
logging.debug('PAR2 output was\n%s', '\n'.join(lines))
# If successful, add renamed files to the collection
if finished and renames:
previous = load_data(RENAMES_FILE, nzo.workpath, remove=False)
for name in previous or {}:
renames[name] = previous[name]
save_data(renames, RENAMES_FILE, nzo.workpath)
if retry_classic:
logging.debug('Retry PAR2-joining with par2-classic')
return PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, classic=True)
......
......@@ -28,6 +28,7 @@ import logging
import sabnzbd
from sabnzbd.constants import *
import sabnzbd.cfg
try:
from OpenSSL import SSL
......@@ -84,23 +85,32 @@ def request_server_info(server):
def GetServerParms(host, port):
# Make sure port is numeric (unicode input not supported)
""" Return processed getaddrinfo() for server
"""
try:
int(port)
except:
# Could do with a warning here
port = 119
opt = sabnzbd.cfg.ipv6_servers()
try:
# Standard IPV4
return socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
# Standard IPV4 or IPV6
ips = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
if opt == 2 or (_EXTERNAL_IPV6 and opt == 1):
# IPv6 reachable and allowed, or forced by user
return ips
else:
# IPv6 unreachable or not allowed by user
return [ip for ip in ips if ':' not in ip[4][0]]
except:
try:
# Try IPV6 explicitly
return socket.getaddrinfo(host, port, socket.AF_INET6,
socket.SOCK_STREAM, socket.IPPROTO_IP, socket.AI_CANONNAME)
except:
# Nothing found!
return None
if opt == 2 or (_EXTERNAL_IPV6 and opt == 1):
try:
# Try IPV6 explicitly
return socket.getaddrinfo(host, port, socket.AF_INET6,
socket.SOCK_STREAM, socket.IPPROTO_IP, socket.AI_CANONNAME)
except:
# Nothing found!
pass
return None
def con(sock, host, port, sslenabled, write_fds, nntp):
......@@ -415,3 +425,25 @@ class SSLConnection(object):
return apply(self._ssl_conn.%s, args)
finally:
self._lock.release()\n""" % (f, f)
def test_ipv6():
""" Check if external IPv6 addresses are reachable """
# Use google.com to test IPv6 access
try:
info = socket.getaddrinfo('www.google.com', 80, socket.AF_INET6, socket.SOCK_STREAM,
socket.IPPROTO_IP, socket.AI_CANONNAME)
except socket.gaierror:
return False
try:
af, socktype, proto, canonname, sa = info[0]
sock = socket.socket(af, socktype, proto)
sock.settimeout(4)
sock.connect(sa[0:2])
sock.close()
return True
except socket.error:
return False
_EXTERNAL_IPV6 = test_ipv6()
......@@ -27,7 +27,7 @@ import datetime
import sabnzbd
from sabnzbd.trylist import TryList
from sabnzbd.nzbstuff import NzbObject
from sabnzbd.misc import exit_sab, cat_to_opts, flag_file, \
from sabnzbd.misc import exit_sab, cat_to_opts, \
get_admin_path, remove_all, globber
from sabnzbd.panic import panic_queue
import sabnzbd.database as database
......@@ -147,7 +147,13 @@ class NzbQueue(TryList):
def repair_job(self, folder, new_nzb=None):
""" Reconstruct admin for a single job folder, optionally with new NZB """
""" Reconstruct admin for a single job folder, optionally with new NZB
"""
def all_verified(path):
""" Return True when all sets have been successfully verified """
verified = sabnzbd.load_data(VERIFIED_FILE, path, remove=False) or {'x':False}
return not bool([True for x in verified if not verified[x]])
name = os.path.basename(folder)
path = os.path.join(folder, JOB_ADMIN)
if hasattr(new_nzb, 'filename'):
......@@ -155,7 +161,7 @@ class NzbQueue(TryList):
else:
filename = ''
if not filename:
if not flag_file(folder, VERIFIED_FILE):
if not all_verified(path):
filename = globber(path, '*.gz')
if len(filename) > 0:
logging.debug('Repair job %s by reparsing stored NZB', latin1(name))
......@@ -749,6 +755,7 @@ class NzbQueue(TryList):
if not nzo.deleted:
nzo.deleted = True
if nzo.precheck:
nzo.save_attribs()
# Check result
enough, ratio = nzo.check_quality()
if enough:
......@@ -759,7 +766,7 @@ class NzbQueue(TryList):
return
else:
# Not enough data, let postprocessor show it as failed
nzo.save_attribs()
pass
Assembler.do.process((nzo, None))
......
......@@ -37,7 +37,7 @@ import sabnzbd
from sabnzbd.constants import sample_match, GIGI, ATTRIB_FILE, JOB_ADMIN, \
DEFAULT_PRIORITY, LOW_PRIORITY, NORMAL_PRIORITY, \
HIGH_PRIORITY, PAUSED_PRIORITY, TOP_PRIORITY, DUP_PRIORITY, \
Status
RENAMES_FILE, Status
from sabnzbd.misc import to_units, cat_to_opts, cat_convert, sanitize_foldername, \
get_unique_path, get_admin_path, remove_all, format_source_url, \
sanitize_filename, globber, sanitize_foldername, int_conv, \
......@@ -827,8 +827,7 @@ class NzbObject(TryList):
# Move only when not current NZF and filename was extractable from subject
if name and nzf is not xnzf:
head, vol, block = analyse_par2(name)
# When only subject is known, it's enough that that 'parset' is in subject
if head and lparset in head.lower():
if head and matcher(lparset, head.lower()):
xnzf.set_par2(parset, vol, block)
self.extrapars[parset].append(xnzf)
if not self.precheck:
......@@ -846,6 +845,9 @@ class NzbObject(TryList):
head, vol, block = analyse_par2(fn)
## Is a par2file and repair mode activated
if head and (self.repair or cfg.allow_streaming()):
## Skip if mini-par2 is not complete
if not block and nzf.bytes_left:
return
nzf.set_par2(head, vol, block)
## Already got a parfile for this set?
if head in self.partable:
......@@ -910,6 +912,15 @@ class NzbObject(TryList):
"""
# Get a list of already present files
files = [os.path.basename(f) for f in globber(wdir) if os.path.isfile(f)]
# Substitute renamed files
renames = sabnzbd.load_data(RENAMES_FILE, self.workpath, remove=True)
if renames:
for name in renames:
if name in files:
files.remove(name)
files.append(renames[name])
# Looking for the longest name first, minimizes the chance on a mismatch
files.sort(lambda x, y: len(y) - len(x))
......@@ -1603,7 +1614,7 @@ def analyse_par2(name):
vol = m.group(2)
block = m.group(3)
elif name.lower().find('.par2') > 0:
head = os.path.splitext(name)[0]
head = os.path.splitext(name)[0].strip()
else:
head = None
return head, vol, block
......@@ -1618,3 +1629,13 @@ def name_extractor(subject):
if name and RE_NORMAL_NAME.search(name):
result = name
return platform_encode(result)
def matcher(pattern, txt):
""" Return True if `pattern` is sufficiently equal to `txt`
"""
if txt.endswith(pattern):
txt = txt[:txt.rfind(pattern)].strip()
return (not txt) or txt.endswith('"')
else:
return False
......@@ -31,9 +31,9 @@ import re
from sabnzbd.newsunpack import unpack_magic, par2_repair, external_processing, sfv_check
from threading import Thread
from sabnzbd.misc import real_path, get_unique_path, create_dirs, move_to_path, \
get_unique_filename, make_script_path, flag_file, \
make_script_path, \
on_cleanup_list, renamer, remove_dir, remove_all, globber, \
set_permissions
set_permissions, cleanup_empty_directories
from sabnzbd.tvsort import Sorter
from sabnzbd.constants import REPAIR_PRIORITY, TOP_PRIORITY, POSTPROC_QUEUE_FILE_NAME, \
POSTPROC_QUEUE_VERSION, sample_match, JOB_ADMIN, Status, VERIFIED_FILE
......@@ -375,10 +375,7 @@ def process_job(nzo):
nzb_list = None
if nzb_list:
nzo.set_unpack_info('Download', T('Sent %s to queue') % unicoder(nzb_list))
try:
remove_dir(tmp_workdir_complete)
except:
pass
cleanup_empty_directories(tmp_workdir_complete)
else:
cleanup_list(tmp_workdir_complete, False)
......@@ -540,6 +537,9 @@ def parring(nzo, workdir):
growler.send_notification(T('Post-processing'), nzo.final_name, 'pp')
logging.info('Par2 check starting on %s', filename)
## Get verification status of sets
verified = sabnzbd.load_data(VERIFIED_FILE, nzo.workpath, remove=False) or {}
## Collect the par files
if nzo.partable:
par_table = nzo.partable.copy()
......@@ -551,51 +551,65 @@ def parring(nzo, workdir):
par_error = False
if repair_sets:
for setname in repair_sets:
if cfg.ignore_samples() > 0 and 'sample' in setname.lower():
continue
if not verified.get(setname, False):
logging.info("Running repair on set %s", setname)
parfile_nzf = par_table[setname]
need_re_add, res = par2_repair(parfile_nzf, nzo, workdir, setname)
re_add = re_add or need_re_add
if not res and cfg.sfv_check():
res = try_sfv_check(nzo, workdir, setname)
verified[setname] = res
par_error = par_error or not res
else:
logging.info("No par2 sets for %s", filename)
nzo.set_unpack_info('Repair', T('[%s] No par2 sets') % unicoder(filename))
if cfg.sfv_check():
par_error = not try_sfv_check(nzo, workdir, '')
verified[''] = not par_error
if re_add:
logging.info('Readded %s to queue', filename)
if nzo.priority != TOP_PRIORITY:
nzo.priority = REPAIR_PRIORITY
sabnzbd.nzbqueue.add_nzo(nzo)
sabnzbd.downloader.Downloader.do.resume_from_postproc()
sabnzbd.save_data(verified, VERIFIED_FILE, nzo.workpath)
logging.info('Par2 check finished on %s', filename)
return par_error, re_add
for set_ in repair_sets:
logging.info("Running repair on set %s", set_)
parfile_nzf = par_table[set_]
need_re_add, res = par2_repair(parfile_nzf, nzo, workdir, set_)
if need_re_add:
re_add = True
par_error = par_error or not res
if re_add:
logging.info('Readded %s to queue', filename)
if nzo.priority != TOP_PRIORITY:
nzo.priority = REPAIR_PRIORITY
sabnzbd.nzbqueue.add_nzo(nzo)
sabnzbd.downloader.Downloader.do.resume_from_postproc()
logging.info('Par2 check finished on %s', filename)
if (par_error and not re_add) or not repair_sets:
# See if alternative SFV check is possible
if cfg.sfv_check() and not (flag_file(workdir, VERIFIED_FILE) and not repair_sets):
sfvs = globber(workdir, '*.sfv')
else:
sfvs = None
if sfvs:
par_error = False
def try_sfv_check(nzo, workdir, setname):
""" Attempt to verify set using SFV file
Return True if verified, False when failed
When setname is '', all SFV files will be used, otherwise only the matching one
When setname is '' and no SFV files are found, True is returned
"""
# Get list of SFV names; shortest name first, minimizes the chance on a mismatch
sfvs = globber(workdir, '*.sfv')
sfvs.sort(lambda x, y: len(x) - len(y))
par_error = False
found = False
for sfv in sfvs:
if setname in os.path.basename(sfv):
found = True
nzo.set_unpack_info('Repair', T('Trying SFV verification'))
for sfv in sfvs:
failed = sfv_check(sfv)
if failed:
msg = T('Some files failed to verify against "%s"') % unicoder(os.path.basename(sfv))
msg += '; '
msg += '; '.join(failed)
nzo.set_unpack_info('Repair', msg)
par_error = True
if not par_error:
failed = sfv_check(sfv)
if failed:
msg = T('Some files failed to verify against "%s"') % unicoder(os.path.basename(sfv))
msg += '; '
msg += '; '.join(failed)
nzo.set_unpack_info('Repair', msg)
par_error = True
else:
nzo.set_unpack_info('Repair', T('Verified successfully using SFV files'))
elif not repair_sets:
logging.info("No par2 sets for %s", filename)
nzo.set_unpack_info('Repair', T('[%s] No par2 sets') % unicoder(filename))
if not par_error:
flag_file(workdir, VERIFIED_FILE, create=True)
return par_error, re_add
if setname:
break
return (found or not setname) and not par_error
#------------------------------------------------------------------------------
......@@ -649,6 +663,11 @@ def cleanup_list(wdir, skip_nzb):
except:
logging.error(Ta('Removing %s failed'), path)
logging.info("Traceback: ", exc_info = True)
if files:
try:
remove_dir(wdir)
except:
pass
def prefix(path, pre):
......@@ -664,29 +683,24 @@ def nzb_redirect(wdir, nzbname, pp, script, cat, priority):
if so send to queue and remove if on CleanList
Returns list of processed NZB's
"""
lst = []
try:
files = os.listdir(wdir)
except:
files = []
files = []
for root, dirs, names in os.walk(wdir):
for name in names:
files.append(os.path.join(root, name))
for file_ in files:
if os.path.splitext(file_)[1].lower() != '.nzb':
return lst
return None
# For a single NZB, use the current job name