mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-06 14:39:41 -05:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f61e7cb1ed | ||
|
|
3de0c0e4ac | ||
|
|
63796d3feb | ||
|
|
6b07529300 | ||
|
|
e10676710c | ||
|
|
77f67c6666 | ||
|
|
bdbcdd61e1 | ||
|
|
4ab7ec754d | ||
|
|
20f98f48bc | ||
|
|
84e0502e50 | ||
|
|
2aa1b00dbb | ||
|
|
972078a514 | ||
|
|
be8382d25b | ||
|
|
8d46e88cd8 | ||
|
|
6b6b1b79ad | ||
|
|
e1fd40b34d | ||
|
|
bc1f8f97a8 | ||
|
|
b51705f458 | ||
|
|
aaed5f4797 | ||
|
|
a8eedef1d2 | ||
|
|
9407e21e1e | ||
|
|
ba6dcfd467 | ||
|
|
e2c1de5008 | ||
|
|
10b7403748 | ||
|
|
1ba924cc12 | ||
|
|
11eb034bd3 | ||
|
|
c3250e15cb | ||
|
|
8ff8a59b4c | ||
|
|
0c646d88b2 | ||
|
|
05670ea599 | ||
|
|
e25eb32885 | ||
|
|
250f75f084 | ||
|
|
cdd39e6777 |
@@ -1,5 +1,5 @@
|
||||
*******************************************
|
||||
*** This is SABnzbd 0.7.4 ***
|
||||
*** This is SABnzbd 0.7.5 ***
|
||||
*******************************************
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
It simplifies the process of downloading from Usenet dramatically,
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
-------------------------------------------------------------------------------
|
||||
0.7.5Final by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Add missing %dn formula to Generic Sort
|
||||
- Improve RSS logging
|
||||
-------------------------------------------------------------------------------
|
||||
0.7.5RC1 by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Prevent stuck jobs at end of pre-check.
|
||||
- Fix issues with accented and special characters in names of downloaded files.
|
||||
- Adjust nzbmatrix category table.
|
||||
- Add 'prio_sort_list' special
|
||||
- Add special option 'empty_postproc'.
|
||||
- Prevent CherryPy crash when reading a cookie from another app which has a non-standard name.
|
||||
- Prevent crash when trying to open non-existing "complete" folder from Windows System-tray icon.
|
||||
- Fix problem with "Read" button when RSS feed name contains "&".
|
||||
- Prevent unusual SFV files from crashing post-processing.
|
||||
- OSX: Retina compatible menu-bar icons.
|
||||
- Don't show speed and ETA when download is paused during post-processing
|
||||
- Prevent soft-crash when api-function "addfile" is called without parameters.
|
||||
- Add news channel frame
|
||||
-------------------------------------------------------------------------------
|
||||
0.7.4Final by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
- Pre-queue script no longer got the show/season/episode information.
|
||||
- Prevent crash on startup when a fully downloaded job is still in download queue.
|
||||
- New RSS feed should no longer be considered new after first, but empty readout.
|
||||
- Make "auth" call backward-compatible with 0.6.x releases.
|
||||
- Config->Notifications: email and growl server addresses should not be marked as "url" type.
|
||||
- OSX: fix top menu queue info so that it shows total queue size
|
||||
-------------------------------------------------------------------------------
|
||||
0.7.4RC2 by The SABnzbd-Team
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SABnzbd 0.7.4
|
||||
SABnzbd 0.7.5
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0) LICENSE
|
||||
|
||||
4
PKG-INFO
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 0.7.4RC2
|
||||
Summary: SABnzbd-0.7.4RC2
|
||||
Version: 0.7.5
|
||||
Summary: SABnzbd-0.7.5
|
||||
Home-page: http://sabnzbd.org
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
36
README.mkd
36
README.mkd
@@ -1,29 +1,17 @@
|
||||
Release Notes - SABnzbd 0.7.4RC2
|
||||
==================================
|
||||
Release Notes - SABnzbd 0.7.5
|
||||
===============================
|
||||
|
||||
## Fixes in 0.7.4RC2
|
||||
- Pre-check failed to consider extra par2 files
|
||||
- Fixed unjustified warning that can occur with OSX Growl 2.0
|
||||
- Show memory usage on Linux systems
|
||||
- Fix incorrect end-of-month quota reset
|
||||
- Fix UI refresh issue when using Safari on iOS6
|
||||
## 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
|
||||
|
||||
## Fixes in 0.7.4RC1
|
||||
|
||||
- OSX Mountain Lion: Notification Center support
|
||||
- OSX Mountain Lion: improved "keep awake" support
|
||||
- Restore SABnzbd icon for Growl
|
||||
- Scheduler: action can now run on multiple weekdays
|
||||
- Scheduler: add "remove failed jobs" action
|
||||
- After successful pre-check, preserve a job's position in the queue
|
||||
- Make Windows version less eager to use par2-classic
|
||||
- Support for HTTPS chain files (needed when you buy your own certificate)
|
||||
- Prevent jobs from showing up in queue and history simultaneously
|
||||
- Fix failure to fetch more par2-files for posts with badly formatted subject lines
|
||||
- Special option: rss_odd_titles (see Wiki)
|
||||
- Special option: 'overwrite_files' (See Wiki)
|
||||
- A number of small issues (see changelog)
|
||||
- Fix for third-party tools requesting too much history
|
||||
## 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
|
||||
|
||||
## What's new in 0.7.0
|
||||
|
||||
|
||||
@@ -658,7 +658,10 @@ class Request(object):
|
||||
# Handle cookies differently because on Konqueror, multiple
|
||||
# cookies come on different lines with the same key
|
||||
if name == 'Cookie':
|
||||
self.cookie.load(value)
|
||||
try:
|
||||
self.cookie.load(value)
|
||||
except:
|
||||
pass
|
||||
|
||||
if not dict.__contains__(headers, 'Host'):
|
||||
# All Internet-based HTTP/1.1 servers MUST respond with a 400
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
<h5 class="copyright">Copyright © 2008-2012 The SABnzbd Team <<span style="color: #0000ff;">team@sabnzbd.org</span>></h5>
|
||||
<p class="copyright"><small>$T('yourRights')</small></p>
|
||||
</div>
|
||||
<!--#if $news_items#-->
|
||||
<div class="padding">
|
||||
<iframe frameborder=0 width=100% src="http://sabnzbdplus.sourceforge.net/version/news.html"></iframe>
|
||||
</div>
|
||||
<!--#end if#-->
|
||||
</div>
|
||||
|
||||
<!--#include $webdir + "/_inc_footer_uc.tmpl"#-->
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<fieldset>
|
||||
<div class="field-pair alt">
|
||||
<label class="config" for="email_server">$T('opt-email_server')</label>
|
||||
<input type="url" name="email_server" id="email_server" value="$email_server" size="40" />
|
||||
<input type="text" name="email_server" id="email_server" value="$email_server" size="40" />
|
||||
<span class="desc">$T('explain-email_server')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
@@ -111,7 +111,7 @@
|
||||
</div>
|
||||
<div class="field-pair alt">
|
||||
<label class="config" for="growl_server">$T('opt-growl_server')</label>
|
||||
<input type="url" name="growl_server" id="growl_server" value="$growl_server" size="40" />
|
||||
<input type="text" name="growl_server" id="growl_server" value="$growl_server" size="40" />
|
||||
<span class="desc">$T('explain-growl_server')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
|
||||
@@ -498,6 +498,10 @@
|
||||
</div><!-- /colmask -->
|
||||
|
||||
<script>
|
||||
function urlencode(str) {
|
||||
return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
|
||||
}
|
||||
|
||||
\$(document).ready(function(){
|
||||
\$('.editFeed').click(function(){
|
||||
var oldURI = \$(this).prev().val();
|
||||
@@ -537,7 +541,7 @@
|
||||
url: "test_rss_feed",
|
||||
data: {feed: whichFeed, session: "$session" }
|
||||
}).done(function( msg ) {
|
||||
location = '?feed=' + whichFeed;
|
||||
location = '?feed=' + urlencode(whichFeed);
|
||||
// location.reload();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
<div class="field-pair alt">
|
||||
<label class="config" for="password">$T('srv-password')</label>
|
||||
<input type="text" name="password" id="password" size="30" />
|
||||
<input type="password" name="password" id="password" size="30" />
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="connections">$T('srv-connections')</label>
|
||||
|
||||
@@ -265,6 +265,11 @@
|
||||
<td>$T('sort-File')</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-right"><b>$T('orgDirname'):</b></td>
|
||||
<td>%dn</td>
|
||||
<td>$T("sort-Folder")</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="align-right"><b>$T('lowercase'):</b></td>
|
||||
<td>{$T('TEXT')}</td>
|
||||
<td>$T('text')</td>
|
||||
@@ -432,7 +437,7 @@
|
||||
return function(callback, ms){
|
||||
clearTimeout (timer);
|
||||
timer = setTimeout(callback, ms);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
function tvSet(val) {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<div class="field-pair alt">
|
||||
<label class="nocheck clearfix" for="password">
|
||||
<span class="component-title">$T('srv-password')</span>
|
||||
<input type="text" size="25" name="password"/>
|
||||
<input type="password" size="25" name="password"/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
@@ -156,7 +156,7 @@
|
||||
<div class="field-pair alt">
|
||||
<label class="nocheck clearfix" for="password">
|
||||
<span class="component-title">$T('srv-password')</span>
|
||||
<input type="text" size="25" name="password" value="$servers[$server]['password']" />
|
||||
<input type="password" size="25" name="password" value="$servers[$server]['password']" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
|
||||
@@ -895,7 +895,7 @@ $("a","#multiops_inputs").click(function(e){
|
||||
headers: {"Cache-Control": "no-cache"},
|
||||
type: "POST",
|
||||
url: "tapi",
|
||||
data: {mode:'history', name:'delete', value:value, del_files:del_files, apikey: $.plush.apikey},
|
||||
data: {mode:'history', name:'delete', value:value, del_files:del_files, search: $('#historySearchBox').val(), apikey: $.plush.apikey},
|
||||
success: function(){
|
||||
$.colorbox.close();
|
||||
$.plush.modalOpen=false;
|
||||
@@ -1242,12 +1242,16 @@ $.plush.histprevslots = $.plush.histnoofslots; // for the next refresh
|
||||
SetQueueETAStats : function(speed,kbpersec,timeleft,eta) {
|
||||
|
||||
// ETA/speed stats at top of queue
|
||||
if (kbpersec < 1 && $.plush.paused)
|
||||
if (kbpersec < 1 || $.plush.paused) {
|
||||
$('#stats_eta').html('—');
|
||||
else
|
||||
$('#stats_speed').html('—');
|
||||
$('#time-left').attr('title','—'); // Tooltip on "time left"
|
||||
}
|
||||
else {
|
||||
$('#stats_eta').html(timeleft);
|
||||
$('#stats_speed').html(speed+"B/s");
|
||||
$('#time-left').attr('title',eta); // Tooltip on "time left"
|
||||
$('#stats_speed').html(speed+"B/s");
|
||||
$('#time-left').attr('title',eta); // Tooltip on "time left"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 388 B |
BIN
osx/resources/sab_clicked.tiff
Normal file
BIN
osx/resources/sab_clicked.tiff
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 902 B |
BIN
osx/resources/sab_idle.tiff
Normal file
BIN
osx/resources/sab_idle.tiff
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
osx/resources/sab_pause.tiff
Normal file
BIN
osx/resources/sab_pause.tiff
Normal file
Binary file not shown.
@@ -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-08-03 02:19+0000\n"
|
||||
"PO-Revision-Date: 2012-09-29 03:57+0000\n"
|
||||
"Last-Translator: lrrosa <Unknown>\n"
|
||||
"Language-Team: Brazilian Portuguese <pt_BR@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-11 05:13+0000\n"
|
||||
"X-Generator: Launchpad (build 15924)\n"
|
||||
"X-Launchpad-Export-Date: 2012-09-30 05:05+0000\n"
|
||||
"X-Generator: Launchpad (build 16049)\n"
|
||||
|
||||
#: SABnzbd.py:302 [Error message]
|
||||
msgid "Failed to start web-interface"
|
||||
@@ -56,7 +56,7 @@ msgstr "HTTPS desabilitado pela falta de arquivos CERT e KEY"
|
||||
|
||||
#: SABnzbd.py:1525
|
||||
msgid "SABnzbd %s started"
|
||||
msgstr ""
|
||||
msgstr "SABnzbd %s iniciado"
|
||||
|
||||
#: SABnzbd.py:1667 # sabnzbd/osxmenu.py:775
|
||||
msgid "SABnzbd shutdown finished"
|
||||
@@ -1518,7 +1518,7 @@ msgstr "Ler feeds RSS"
|
||||
|
||||
#: sabnzbd/skintext.py:65 [Config->Scheduler]
|
||||
msgid "Remove failed jobs"
|
||||
msgstr ""
|
||||
msgstr "Remover tarefas com falha"
|
||||
|
||||
#: sabnzbd/skintext.py:70 [Speed indicator kilobytes/sec]
|
||||
msgid "KB/s"
|
||||
@@ -2254,11 +2254,11 @@ msgstr "Nome do arquivo ou caminho para a chave HTTPS."
|
||||
|
||||
#: sabnzbd/skintext.py:302
|
||||
msgid "HTTPS Chain Certifcates"
|
||||
msgstr ""
|
||||
msgstr "Cadeia de Certificados HTTPS"
|
||||
|
||||
#: sabnzbd/skintext.py:303
|
||||
msgid "File name or path to HTTPS Chain."
|
||||
msgstr ""
|
||||
msgstr "Nome de arquivo ou caminho da Cadeia HTTPS."
|
||||
|
||||
#: sabnzbd/skintext.py:304
|
||||
msgid "Tuning"
|
||||
@@ -2769,7 +2769,7 @@ msgstr "Checar semanalmente por nova versão do SABnzbd."
|
||||
|
||||
#: sabnzbd/skintext.py:421 [Pick list for weekly test for new releases]
|
||||
msgid "Also test releases"
|
||||
msgstr ""
|
||||
msgstr "Também versões de testes"
|
||||
|
||||
#: sabnzbd/skintext.py:422
|
||||
msgid "Replace Spaces in Foldername"
|
||||
@@ -3208,19 +3208,20 @@ msgstr "Enviar as notificações a NotifyOSD."
|
||||
|
||||
#: sabnzbd/skintext.py:557
|
||||
msgid "Notification Center"
|
||||
msgstr ""
|
||||
msgstr "Centro de Notificações"
|
||||
|
||||
#: sabnzbd/skintext.py:558
|
||||
msgid "Send notifications to Notification Center"
|
||||
msgstr ""
|
||||
msgstr "Envia notificações para o Centro de Notificações"
|
||||
|
||||
#: sabnzbd/skintext.py:559
|
||||
msgid "Notification classes"
|
||||
msgstr ""
|
||||
msgstr "Classes de notificação"
|
||||
|
||||
#: sabnzbd/skintext.py:560
|
||||
msgid "Enable classes of messages to be reported (none, one or multiple)"
|
||||
msgstr ""
|
||||
"Habilita classes de mensagens a serem relatadas (nenhuma, uma, ou múltiplas)"
|
||||
|
||||
#: sabnzbd/skintext.py:564
|
||||
msgid ""
|
||||
|
||||
@@ -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-08-02 15:29+0000\n"
|
||||
"PO-Revision-Date: 2012-10-13 17:23+0000\n"
|
||||
"Last-Translator: nicusor <Unknown>\n"
|
||||
"Language-Team: Romanian <ro@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-11 05:13+0000\n"
|
||||
"X-Generator: Launchpad (build 15924)\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-14 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
|
||||
#: SABnzbd.py:302 [Error message]
|
||||
msgid "Failed to start web-interface"
|
||||
@@ -55,7 +55,7 @@ msgstr "Dezactivează HTTPS din cauza lipsei fişierelor CERT şi KEY"
|
||||
|
||||
#: SABnzbd.py:1525
|
||||
msgid "SABnzbd %s started"
|
||||
msgstr ""
|
||||
msgstr "SABnzbd %s pornit"
|
||||
|
||||
#: SABnzbd.py:1667 # sabnzbd/osxmenu.py:775
|
||||
msgid "SABnzbd shutdown finished"
|
||||
@@ -1517,7 +1517,7 @@ msgstr "Citeşte fluxuri RSS"
|
||||
|
||||
#: sabnzbd/skintext.py:65 [Config->Scheduler]
|
||||
msgid "Remove failed jobs"
|
||||
msgstr ""
|
||||
msgstr "Elimină sarcini nereuşite"
|
||||
|
||||
#: sabnzbd/skintext.py:70 [Speed indicator kilobytes/sec]
|
||||
msgid "KB/s"
|
||||
@@ -2253,11 +2253,11 @@ msgstr "Nume fişier sau cale Cheie HTTPS."
|
||||
|
||||
#: sabnzbd/skintext.py:302
|
||||
msgid "HTTPS Chain Certifcates"
|
||||
msgstr ""
|
||||
msgstr "Certificate Cheie HTTPS"
|
||||
|
||||
#: sabnzbd/skintext.py:303
|
||||
msgid "File name or path to HTTPS Chain."
|
||||
msgstr ""
|
||||
msgstr "Nume fişier sau cale cheie HTTPS."
|
||||
|
||||
#: sabnzbd/skintext.py:304
|
||||
msgid "Tuning"
|
||||
@@ -2764,7 +2764,7 @@ msgstr "Verificare săptămânală versiuni noi SABnzbd."
|
||||
|
||||
#: sabnzbd/skintext.py:421 [Pick list for weekly test for new releases]
|
||||
msgid "Also test releases"
|
||||
msgstr ""
|
||||
msgstr "Testeaza şi versiuni de încercare"
|
||||
|
||||
#: sabnzbd/skintext.py:422
|
||||
msgid "Replace Spaces in Foldername"
|
||||
@@ -3204,19 +3204,20 @@ msgstr "Trimite notificări către NotifyOSD"
|
||||
|
||||
#: sabnzbd/skintext.py:557
|
||||
msgid "Notification Center"
|
||||
msgstr ""
|
||||
msgstr "Centru Notificări"
|
||||
|
||||
#: sabnzbd/skintext.py:558
|
||||
msgid "Send notifications to Notification Center"
|
||||
msgstr ""
|
||||
msgstr "Trimite notificări la Centru Notificări"
|
||||
|
||||
#: sabnzbd/skintext.py:559
|
||||
msgid "Notification classes"
|
||||
msgstr ""
|
||||
msgstr "Clase notificări"
|
||||
|
||||
#: sabnzbd/skintext.py:560
|
||||
msgid "Enable classes of messages to be reported (none, one or multiple)"
|
||||
msgstr ""
|
||||
"Activează clasă mesaje ce vor fi raportate (niciunul, unul sau mai multe)"
|
||||
|
||||
#: sabnzbd/skintext.py:564
|
||||
msgid ""
|
||||
|
||||
@@ -1037,6 +1037,9 @@ def check_all_tasks():
|
||||
# Check one-shot pause
|
||||
sabnzbd.scheduler.pause_check()
|
||||
|
||||
# Check (and terminate) idle jobs
|
||||
sabnzbd.nzbqueue.NzbQueue.do.stop_idle_jobs()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -293,9 +293,11 @@ def _api_addfile(name, output, kwargs):
|
||||
#Side effect of next line is that attribute .value is created
|
||||
#which is needed to make add_nzbfile() work
|
||||
size = name.length
|
||||
else:
|
||||
elif hasattr(name, 'value'):
|
||||
size = len(name.value)
|
||||
if name is not None and name.filename and size:
|
||||
else:
|
||||
size = 0
|
||||
if name is not None and size and name.filename:
|
||||
cat = kwargs.get('cat')
|
||||
xcat = kwargs.get('xcat')
|
||||
if not cat and xcat:
|
||||
@@ -432,10 +434,10 @@ def _api_history(name, output, kwargs):
|
||||
history_db = cherrypy.thread_data.history_db
|
||||
if special in ('all', 'failed'):
|
||||
if del_files:
|
||||
del_job_files(history_db.get_failed_paths())
|
||||
history_db.remove_failed()
|
||||
del_job_files(history_db.get_failed_paths(search))
|
||||
history_db.remove_failed(search)
|
||||
if special in ('all', 'completed'):
|
||||
history_db.remove_completed()
|
||||
history_db.remove_completed(search)
|
||||
return report(output)
|
||||
elif value:
|
||||
jobs = value.split(',')
|
||||
@@ -556,10 +558,13 @@ def _api_auth(name, output, kwargs):
|
||||
if not cfg.disable_key():
|
||||
auth = 'badkey'
|
||||
key = kwargs.get('key', '')
|
||||
if key == cfg.nzb_key():
|
||||
auth = 'nzbkey'
|
||||
if key == cfg.api_key():
|
||||
if not key:
|
||||
auth = 'apikey'
|
||||
else:
|
||||
if key == cfg.nzb_key():
|
||||
auth = 'nzbkey'
|
||||
if key == cfg.api_key():
|
||||
auth = 'apikey'
|
||||
elif cfg.username() and cfg.password():
|
||||
auth = 'login'
|
||||
return report(output, keyword='auth', data=auth)
|
||||
@@ -1102,7 +1107,7 @@ def build_queue(web_dir=None, root=None, verbose=False, prim=True, webdir='', ve
|
||||
slot['mbdone_fmt'] = locale.format('%d', int(mb-mbleft), True)
|
||||
slot['size'] = format_bytes(bytes)
|
||||
slot['sizeleft'] = format_bytes(bytesleft)
|
||||
if not Downloader.do.paused and status != 'Paused' and status != 'Fetching' and not found_active:
|
||||
if not Downloader.do.paused and status not in (Status.PAUSED, Status.FETCHING) and not found_active:
|
||||
if status == Status.CHECKING:
|
||||
slot['status'] = Status.CHECKING
|
||||
else:
|
||||
@@ -1126,7 +1131,7 @@ def build_queue(web_dir=None, root=None, verbose=False, prim=True, webdir='', ve
|
||||
slot['percentage'] = "%s" % (int(((mb-mbleft) / mb) * 100))
|
||||
slot['missing'] = missing
|
||||
|
||||
if status in (Status.PAUSED, Status.CHECKING):
|
||||
if Downloader.do.paused or Downloader.do.postproc or status not in (Status.DOWNLOADING, Status.QUEUED):
|
||||
slot['timeleft'] = '0:00:00'
|
||||
slot['eta'] = 'unknown'
|
||||
else:
|
||||
@@ -1539,7 +1544,8 @@ def build_header(prim, webdir=''):
|
||||
if not color:
|
||||
color = ''
|
||||
|
||||
header = { 'T': Ttemplate, 'Tspec': Tspec, 'Tx' : Ttemplate, 'version':sabnzbd.__version__, 'paused': Downloader.do.paused,
|
||||
header = { 'T': Ttemplate, 'Tspec': Tspec, 'Tx' : Ttemplate, 'version':sabnzbd.__version__,
|
||||
'paused': Downloader.do.paused or Downloader.do.postproc,
|
||||
'pause_int': scheduler.pause_int(), 'paused_all': sabnzbd.PAUSED_ALL,
|
||||
'uptime':uptime, 'color_scheme':color }
|
||||
speed_limit = Downloader.do.get_limit()
|
||||
@@ -1590,13 +1596,13 @@ def build_header(prim, webdir=''):
|
||||
header['left_quota'] = to_units(BPSMeter.do.left)
|
||||
|
||||
status = ''
|
||||
if Downloader.do.paused:
|
||||
if Downloader.do.paused or Downloader.do.postproc:
|
||||
status = Status.PAUSED
|
||||
elif bytespersec > 0:
|
||||
status = Status.DOWNLOADING
|
||||
else:
|
||||
status = 'Idle'
|
||||
header['status'] = "%s" % status
|
||||
header['status'] = status
|
||||
|
||||
anfo = ArticleCache.do.cache_info()
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ email_dir = OptionDir('misc', 'email_dir', create=True)
|
||||
email_rss = OptionBool('misc', 'email_rss', False)
|
||||
|
||||
version_check = OptionNumber('misc', 'check_new_rel', 1)
|
||||
news_items = OptionBool('misc', 'news_items', True)
|
||||
autobrowser = OptionBool('misc', 'auto_browser', True)
|
||||
replace_illegal = OptionBool('misc', 'replace_illegal', True)
|
||||
pre_script = OptionStr('misc', 'pre_script', 'None')
|
||||
@@ -125,8 +126,10 @@ auto_sort = OptionBool('misc', 'auto_sort', False)
|
||||
folder_rename = OptionBool('misc', 'folder_rename', True)
|
||||
folder_max_length = OptionNumber('misc', 'folder_max_length', DEF_FOLDER_MAX, 20, 65000)
|
||||
pause_on_pwrar = OptionBool('misc', 'pause_on_pwrar', True)
|
||||
prio_sort_list = OptionList('misc', 'prio_sort_list')
|
||||
|
||||
safe_postproc = OptionBool('misc', 'safe_postproc', True)
|
||||
empty_postproc = OptionBool('misc', 'empty_postproc', False)
|
||||
pause_on_post_processing = OptionBool('misc', 'pause_on_post_processing', False)
|
||||
ampm = OptionBool('misc', 'ampm', False)
|
||||
rss_filenames = OptionBool('misc', 'rss_filenames', False)
|
||||
|
||||
@@ -224,7 +224,10 @@ class OptionList(Option):
|
||||
error = None
|
||||
if value is not None:
|
||||
if not isinstance(value, list):
|
||||
value = listquote.simplelist(value)
|
||||
if '"' not in value and ',' not in value:
|
||||
value = value.split()
|
||||
else:
|
||||
value = listquote.simplelist(value)
|
||||
if self.__validation:
|
||||
error, value = self.__validation(value)
|
||||
if not error:
|
||||
|
||||
@@ -43,6 +43,7 @@ PNFO_MISSING_FIELD = 18
|
||||
QNFO_BYTES_FIELD = 0
|
||||
QNFO_BYTES_LEFT_FIELD = 1
|
||||
QNFO_PNFO_LIST_FIELD = 2
|
||||
QNFO_Q_SIZE_LIST_FIELD = 3
|
||||
|
||||
ANFO_ARTICLE_SUM_FIELD = 0
|
||||
ANFO_CACHE_SIZE_FIELD = 1
|
||||
|
||||
@@ -51,6 +51,27 @@ def get_history_handle():
|
||||
return HistoryDB(_HISTORY_DB)
|
||||
|
||||
|
||||
def convert_search(search):
|
||||
""" Convert classic wildcard to SQL wildcard """
|
||||
if not search:
|
||||
# Default value
|
||||
search = ''
|
||||
else:
|
||||
# Allow * for wildcard matching and space
|
||||
search = search.replace('*','%').replace(' ', '%')
|
||||
|
||||
# Allow ^ for start of string and $ for end of string
|
||||
if search and search.startswith('^'):
|
||||
search = search.replace('^','')
|
||||
search += '%'
|
||||
elif search and search.endswith('$'):
|
||||
search = search.replace('$','')
|
||||
search = '%' + search
|
||||
else:
|
||||
search = '%' + search + '%'
|
||||
return search
|
||||
|
||||
|
||||
# Note: Add support for execute return values
|
||||
|
||||
class HistoryDB(object):
|
||||
@@ -141,19 +162,22 @@ class HistoryDB(object):
|
||||
logging.error(Ta('Failed to close database, see log'))
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
def remove_completed(self):
|
||||
return self.execute("""DELETE FROM history WHERE status = 'Completed'""", save=True)
|
||||
def remove_completed(self, search=None):
|
||||
search = convert_search(search)
|
||||
return self.execute("""DELETE FROM history WHERE name LIKE ? AND status = 'Completed'""", (search,), save=True)
|
||||
|
||||
def get_failed_paths(self):
|
||||
def get_failed_paths(self, search=None):
|
||||
""" Return list of all storage paths of failed jobs (may contain non-existing or empty paths) """
|
||||
fetch_ok = self.execute("""SELECT path FROM history WHERE status = 'Failed'""")
|
||||
search = convert_search(search)
|
||||
fetch_ok = self.execute("""SELECT path FROM history WHERE name LIKE ? AND status = 'Failed'""", (search,))
|
||||
if fetch_ok:
|
||||
return [item.get('path') for item in self.c.fetchall()]
|
||||
else:
|
||||
return []
|
||||
|
||||
def remove_failed(self):
|
||||
return self.execute("""DELETE FROM history WHERE status = 'Failed'""", save=True)
|
||||
def remove_failed(self, search=None):
|
||||
search = convert_search(search)
|
||||
return self.execute("""DELETE FROM history WHERE name LIKE ? AND status = 'Failed'""", (search,), save=True)
|
||||
|
||||
def remove_history(self, jobs=None):
|
||||
if jobs is None:
|
||||
@@ -180,22 +204,7 @@ class HistoryDB(object):
|
||||
|
||||
def fetch_history(self, start=None, limit=None, search=None, failed_only=0):
|
||||
|
||||
if not search:
|
||||
# Default value
|
||||
search = ''
|
||||
else:
|
||||
# Allow * for wildcard matching and space
|
||||
search = search.replace('*','%').replace(' ', '%')
|
||||
|
||||
# Allow ^ for start of string and $ for end of string
|
||||
if search and search.startswith('^'):
|
||||
search = search.replace('^','')
|
||||
search += '%'
|
||||
elif search and search.endswith('$'):
|
||||
search = search.replace('$','')
|
||||
search = '%' + search
|
||||
else:
|
||||
search = '%' + search + '%'
|
||||
search = convert_search(search)
|
||||
|
||||
# Get the number of results
|
||||
if failed_only:
|
||||
|
||||
@@ -1018,6 +1018,7 @@ class ConfigPage(object):
|
||||
for svr in config.get_servers():
|
||||
new[svr] = {}
|
||||
conf['servers'] = new
|
||||
conf['news_items'] = cfg.news_items()
|
||||
|
||||
conf['folders'] = sabnzbd.nzbqueue.scan_jobs(all=False, action=False)
|
||||
|
||||
@@ -1186,16 +1187,16 @@ class ConfigSwitches(object):
|
||||
SPECIAL_BOOL_LIST = \
|
||||
( 'start_paused', 'no_penalties', 'ignore_wrong_unrar', 'create_group_folders',
|
||||
'queue_complete_pers', 'api_warnings', 'allow_64bit_tools', 'par2_multicore',
|
||||
'never_repair', 'allow_streaming', 'ignore_unrar_dates', 'rss_filenames',
|
||||
'never_repair', 'allow_streaming', 'ignore_unrar_dates', 'rss_filenames', 'news_items',
|
||||
'osx_menu', 'osx_speed', 'win_menu', 'uniconfig', 'use_pickle', 'allow_incomplete_nzb',
|
||||
'randomize_server_ip', 'no_ipv6', 'keep_awake', 'overwrite_files'
|
||||
'randomize_server_ip', 'no_ipv6', 'keep_awake', 'overwrite_files', 'empty_postproc'
|
||||
)
|
||||
SPECIAL_VALUE_LIST = \
|
||||
( 'size_limit', 'folder_max_length', 'fsys_type', 'movie_rename_limit', 'nomedia_marker',
|
||||
'req_completion_rate', 'wait_ext_drive', 'history_limit', 'show_sysload'
|
||||
)
|
||||
SPECIAL_LIST_LIST = \
|
||||
( 'rss_odd_titles',
|
||||
( 'rss_odd_titles', 'prio_sort_list'
|
||||
)
|
||||
|
||||
class ConfigSpecial(object):
|
||||
|
||||
@@ -1306,13 +1306,12 @@ def QuickCheck(set, nzo):
|
||||
nzf_list = nzo.finished_files
|
||||
|
||||
for file in md5pack:
|
||||
file = name_fixer(file)
|
||||
if sabnzbd.misc.on_cleanup_list(file, False):
|
||||
result = True
|
||||
continue
|
||||
found = False
|
||||
for nzf in nzf_list:
|
||||
if file == name_fixer(nzf.filename):
|
||||
if file == nzf.filename:
|
||||
found = True
|
||||
if (nzf.md5sum is not None) and nzf.md5sum == md5pack[file]:
|
||||
logging.debug('Quick-check of file %s OK', file)
|
||||
@@ -1375,20 +1374,21 @@ def sfv_check(sfv_path):
|
||||
root = os.path.split(sfv_path)[0]
|
||||
for line in fp:
|
||||
line = line.strip('\n\r ')
|
||||
if line[0] != ';':
|
||||
if line and line[0] != ';':
|
||||
x = line.rfind(' ')
|
||||
filename = platform_encode(line[:x].strip())
|
||||
checksum = line[x:].strip()
|
||||
path = os.path.join(root, filename)
|
||||
if os.path.exists(path):
|
||||
if crc_check(path, checksum):
|
||||
logging.debug('File %s passed SFV check', path)
|
||||
if x > 0:
|
||||
filename = platform_encode(line[:x].strip())
|
||||
checksum = line[x:].strip()
|
||||
path = os.path.join(root, filename)
|
||||
if os.path.exists(path):
|
||||
if crc_check(path, checksum):
|
||||
logging.debug('File %s passed SFV check', path)
|
||||
else:
|
||||
logging.info('File %s did not pass SFV check', latin1(path))
|
||||
failed.append(unicoder(filename))
|
||||
else:
|
||||
logging.info('File %s did not pass SFV check', latin1(path))
|
||||
logging.info('File %s missing in SFV check', latin1(path))
|
||||
failed.append(unicoder(filename))
|
||||
else:
|
||||
logging.info('File %s missing in SFV check', latin1(path))
|
||||
failed.append(unicoder(filename))
|
||||
fp.close()
|
||||
return failed
|
||||
|
||||
@@ -1415,6 +1415,7 @@ def crc_check(path, target_crc):
|
||||
def analyse_show(name):
|
||||
""" Do a quick SeasonSort check and return basic facts """
|
||||
job = SeriesSorter(name, None, None)
|
||||
job.match(force=True)
|
||||
if job.is_match():
|
||||
job.get_values()
|
||||
info = job.show_info
|
||||
|
||||
@@ -178,8 +178,9 @@ class NzbQueue(TryList):
|
||||
logging.debug('Failed to find NZB file after pre-check (%s)', nzo.nzo_id)
|
||||
return
|
||||
from sabnzbd.dirscanner import ProcessSingleFile
|
||||
nzo_id = ProcessSingleFile(os.path.split(nzb_path)[1], nzb_path, reuse=True)[1][0]
|
||||
self.replace_in_q(nzo, nzo_id)
|
||||
res, nzo_ids = ProcessSingleFile(nzo.work_name + '.nzb', nzb_path, reuse=True)
|
||||
if res == 0 and nzo_ids:
|
||||
self.replace_in_q(nzo, nzo_ids[0])
|
||||
|
||||
|
||||
@synchronized(NZBQUEUE_LOCK)
|
||||
@@ -189,8 +190,8 @@ class NzbQueue(TryList):
|
||||
new_nzo = self.get_nzo(nzo_id)
|
||||
pos = self.__nzo_list.index(new_nzo)
|
||||
targetpos = self.__nzo_list.index(nzo)
|
||||
self.__nzo_list.pop(pos)
|
||||
self.__nzo_list[targetpos] = new_nzo
|
||||
self.__nzo_list.pop(pos)
|
||||
del self.__nzo_table[nzo.nzo_id]
|
||||
del nzo
|
||||
except:
|
||||
@@ -741,7 +742,8 @@ class NzbQueue(TryList):
|
||||
"""
|
||||
if self.actives(grabs=False) < 2 and cfg.autodisconnect():
|
||||
# This was the last job, close server connections
|
||||
sabnzbd.downloader.Downloader.do.disconnect()
|
||||
if sabnzbd.downloader.Downloader.do:
|
||||
sabnzbd.downloader.Downloader.do.disconnect()
|
||||
|
||||
# Notify assembler to call postprocessor
|
||||
if not nzo.deleted:
|
||||
@@ -779,18 +781,24 @@ class NzbQueue(TryList):
|
||||
def queue_info(self, for_cli=False, max_jobs=0):
|
||||
bytes_left = 0
|
||||
bytes = 0
|
||||
q_size = 0
|
||||
pnfo_list = []
|
||||
n = 0
|
||||
for nzo in self.__nzo_list:
|
||||
pnfo = nzo.gather_info(for_cli = for_cli)
|
||||
if nzo.status != 'Paused':
|
||||
bytes += pnfo[PNFO_BYTES_FIELD]
|
||||
bytes_left += pnfo[PNFO_BYTES_LEFT_FIELD]
|
||||
pnfo_list.append(pnfo)
|
||||
if not max_jobs or n < max_jobs:
|
||||
pnfo = nzo.gather_info(for_cli = for_cli)
|
||||
pnfo_list.append(pnfo)
|
||||
if nzo.status != 'Paused':
|
||||
bytes += pnfo[PNFO_BYTES_FIELD]
|
||||
bytes_left += pnfo[PNFO_BYTES_LEFT_FIELD]
|
||||
q_size += 1
|
||||
elif nzo.status != 'Paused':
|
||||
b, b_left = nzo.total_and_remaining()
|
||||
bytes += b
|
||||
bytes_left += b_left
|
||||
q_size += 1
|
||||
n += 1
|
||||
if max_jobs and n >= max_jobs:
|
||||
break
|
||||
return (bytes, bytes_left, pnfo_list)
|
||||
return (bytes, bytes_left, pnfo_list, q_size)
|
||||
|
||||
|
||||
@synchronized(NZBQUEUE_LOCK)
|
||||
@@ -819,6 +827,17 @@ class NzbQueue(TryList):
|
||||
|
||||
ArticleCache.do.purge_articles(nzo.saved_articles)
|
||||
|
||||
@synchronized(NZBQUEUE_LOCK)
|
||||
def stop_idle_jobs(self):
|
||||
""" Detect jobs that have zero files left and send them to post processing
|
||||
"""
|
||||
empty = []
|
||||
for nzo in self.__nzo_list:
|
||||
if not nzo.futuretype and not nzo.files and nzo.status not in (Status.PAUSED, Status.GRABBING):
|
||||
empty.append(nzo)
|
||||
for nzo in empty:
|
||||
self.end_job(nzo)
|
||||
|
||||
def get_urls(self):
|
||||
""" Return list of future-types needing URL """
|
||||
lst = []
|
||||
|
||||
@@ -1241,6 +1241,15 @@ class NzbObject(TryList):
|
||||
bytes_left += nzf.bytes_left
|
||||
return bytes_left
|
||||
|
||||
def total_and_remaining(self):
|
||||
""" Return total and remaining bytes """
|
||||
bytes = 0
|
||||
bytes_left = 0
|
||||
for nzf in self.files:
|
||||
bytes += nzf.bytes
|
||||
bytes_left += nzf.bytes_left
|
||||
return bytes, bytes_left
|
||||
|
||||
def gather_info(self, for_cli = False):
|
||||
bytes_left_all = 0
|
||||
|
||||
@@ -1383,8 +1392,9 @@ class NzbObject(TryList):
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def nzf_get_filename(nzf):
|
||||
# Return filename, if the filename not set, try the
|
||||
# the full subject line instead. Can produce non-ideal results
|
||||
""" Return filename, if the filename not set, try the
|
||||
the full subject line instead. Can produce non-ideal results
|
||||
"""
|
||||
name = nzf.filename
|
||||
if not name:
|
||||
name = nzf.subject
|
||||
@@ -1393,8 +1403,31 @@ def nzf_get_filename(nzf):
|
||||
return name.lower()
|
||||
|
||||
|
||||
def get_ext_list():
|
||||
""" Return priority extenstion list, with extensions starting with a period
|
||||
"""
|
||||
exts = []
|
||||
for ext in cfg.prio_sort_list():
|
||||
ext = ext.strip()
|
||||
if not ext.startswith('.'):
|
||||
ext = '.' + ext
|
||||
exts.append(ext)
|
||||
return exts
|
||||
|
||||
|
||||
def ext_on_list(name, lst):
|
||||
""" Return True if `name` contains any extension in `lst`
|
||||
"""
|
||||
for ext in lst:
|
||||
if name.rfind(ext) >= 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def nzf_cmp_date(nzf1, nzf2):
|
||||
# Compare files based on date, but give vol-par files preference
|
||||
""" Compare files based on date, but give vol-par files preference.
|
||||
Wrapper needed, because `cmp` function doesn't handle extra parms.
|
||||
"""
|
||||
return nzf_cmp_name(nzf1, nzf2, name=False)
|
||||
|
||||
|
||||
@@ -1422,6 +1455,16 @@ def nzf_cmp_name(nzf1, nzf2, name=True):
|
||||
if is_par2 and not is_par1:
|
||||
return -1
|
||||
|
||||
# Anything with a priority extention goes first
|
||||
ext_list = get_ext_list()
|
||||
if ext_list:
|
||||
onlist1 = ext_on_list(name1, ext_list)
|
||||
onlist2 = ext_on_list(name2, ext_list)
|
||||
if onlist1 and not onlist2:
|
||||
return -1
|
||||
if onlist2 and not onlist1:
|
||||
return 1
|
||||
|
||||
if name:
|
||||
# Prioritise .rar files above any other type of file (other than vol-par)
|
||||
# Useful for nzb streaming
|
||||
@@ -1574,4 +1617,4 @@ def name_extractor(subject):
|
||||
name = name.strip(' "')
|
||||
if name and RE_NORMAL_NAME.search(name):
|
||||
result = name
|
||||
return result
|
||||
return platform_encode(result)
|
||||
|
||||
@@ -54,7 +54,7 @@ from sabnzbd.newzbin import Bookmarks
|
||||
from sabnzbd.database import get_history_handle
|
||||
from sabnzbd.encoding import unicoder
|
||||
|
||||
status_icons = {'idle':'../Resources/sab_idle.png','pause':'../Resources/sab_pause.png','clicked':'../Resources/sab_clicked.png'}
|
||||
status_icons = {'idle':'../Resources/sab_idle.tiff','pause':'../Resources/sab_pause.tiff','clicked':'../Resources/sab_clicked.tiff'}
|
||||
start_time = NSDate.date()
|
||||
debug = 0
|
||||
|
||||
@@ -347,10 +347,7 @@ class SABnzbdDelegate(NSObject):
|
||||
self.menu_queue.addItem_(menu_queue_item)
|
||||
self.menu_queue.addItem_(NSMenuItem.separatorItem())
|
||||
|
||||
job_nb = 1
|
||||
for pnfo in pnfo_list:
|
||||
if job_nb > 10:
|
||||
break
|
||||
filename = unicoder(pnfo[PNFO_FILENAME_FIELD])
|
||||
msgid = pnfo[PNFO_MSGID_FIELD]
|
||||
bytesleft = pnfo[PNFO_BYTES_LEFT_FIELD] / MEBI
|
||||
@@ -360,11 +357,10 @@ class SABnzbdDelegate(NSObject):
|
||||
timeleft = self.calc_timeleft(bytesleftprogess, bpsnow)
|
||||
|
||||
job = "%s\t(%d/%d MB) %s" % (filename, bytesleft, bytes, timeleft)
|
||||
job_nb += 1
|
||||
menu_queue_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(job, '', '')
|
||||
self.menu_queue.addItem_(menu_queue_item)
|
||||
|
||||
self.info = "%d nzb(s)\t( %d / %d MB )" % (len(pnfo_list),(qnfo[QNFO_BYTES_LEFT_FIELD] / MEBI), (qnfo[QNFO_BYTES_FIELD] / MEBI))
|
||||
self.info = "%d nzb(s)\t( %d / %d MB )" % (qnfo[QNFO_Q_SIZE_LIST_FIELD],(qnfo[QNFO_BYTES_LEFT_FIELD] / MEBI), (qnfo[QNFO_BYTES_FIELD] / MEBI))
|
||||
|
||||
else:
|
||||
menu_queue_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(T('Empty'), '', '')
|
||||
|
||||
@@ -206,6 +206,8 @@ def process_job(nzo):
|
||||
par_error = False
|
||||
# keep track of any unpacking errors
|
||||
unpack_error = False
|
||||
# Signal empty download, for when 'empty_postproc' is enabled
|
||||
empty = False
|
||||
nzb_list = []
|
||||
# These need to be initialised incase of a crash
|
||||
workdir_complete = ''
|
||||
@@ -252,13 +254,15 @@ def process_job(nzo):
|
||||
emsg = T('Download might fail, only %s of required %s available') % (emsg, emsg2)
|
||||
else:
|
||||
emsg = T('Download failed - Out of your server\'s retention?')
|
||||
empty = True
|
||||
nzo.fail_msg = emsg
|
||||
nzo.set_unpack_info('Fail', emsg)
|
||||
nzo.status = Status.FAILED
|
||||
# do not run unpacking or parity verification
|
||||
flag_repair = flag_unpack = False
|
||||
par_error = unpack_error = True
|
||||
all_ok = False
|
||||
all_ok = cfg.empty_postproc() and empty
|
||||
if not all_ok:
|
||||
par_error = unpack_error = True
|
||||
|
||||
script = nzo.script
|
||||
cat = nzo.cat
|
||||
@@ -392,7 +396,10 @@ def process_job(nzo):
|
||||
logging.error(Ta('Error renaming "%s" to "%s"'), tmp_workdir_complete, workdir_complete)
|
||||
logging.info("Traceback: ", exc_info = True)
|
||||
|
||||
job_result = int(par_error) + int(unpack_error)*2
|
||||
if empty:
|
||||
job_result = -1
|
||||
else:
|
||||
job_result = int(par_error) + int(unpack_error)*2
|
||||
|
||||
if cfg.ignore_samples() > 0:
|
||||
remove_samples(workdir_complete)
|
||||
|
||||
@@ -303,13 +303,7 @@ class RSSQueue(object):
|
||||
regcount = len(regexes)
|
||||
|
||||
# Set first if this is the very first scan of this URI
|
||||
if feed not in self.jobs:
|
||||
self.jobs[feed] = {}
|
||||
first = not bool(self.jobs[feed])
|
||||
|
||||
jobs = self.jobs[feed]
|
||||
|
||||
first = first and ignoreFirst
|
||||
first = (feed not in self.jobs) and ignoreFirst
|
||||
|
||||
# Add sabnzbd's custom User Agent
|
||||
feedparser.USER_AGENT = 'SABnzbd+/%s' % sabnzbd.version.__version__
|
||||
@@ -319,6 +313,8 @@ class RSSQueue(object):
|
||||
uri += '&dl=1'
|
||||
|
||||
# Read the RSS feed
|
||||
msg = None
|
||||
entries = None
|
||||
if readout:
|
||||
uri = uri.replace(' ', '%20')
|
||||
logging.debug("Running feedparser on %s", uri)
|
||||
@@ -343,6 +339,12 @@ class RSSQueue(object):
|
||||
if not entries:
|
||||
msg = Ta('RSS Feed %s was empty') % uri
|
||||
logging.info(msg)
|
||||
|
||||
if feed not in self.jobs:
|
||||
self.jobs[feed] = {}
|
||||
jobs = self.jobs[feed]
|
||||
if readout:
|
||||
if not entries:
|
||||
return unicoder(msg)
|
||||
else:
|
||||
entries = jobs.keys()
|
||||
@@ -487,8 +489,7 @@ class RSSQueue(object):
|
||||
for feed in feeds.keys():
|
||||
try:
|
||||
if feeds[feed].enable.get():
|
||||
if not active:
|
||||
logging.info('Starting scheduled RSS read-out')
|
||||
logging.info('Starting scheduled RSS read-out for "%s"', feed)
|
||||
active = True
|
||||
self.run_feed(feed, download=True, ignoreFirst=True)
|
||||
# Wait 15 seconds, else sites may get irritated
|
||||
@@ -502,7 +503,7 @@ class RSSQueue(object):
|
||||
pass
|
||||
if active:
|
||||
self.save()
|
||||
logging.info('Finished scheduled RSS read-out')
|
||||
logging.info('Finished scheduled RSS read-outs')
|
||||
|
||||
|
||||
@synchronized(LOCK)
|
||||
@@ -556,7 +557,7 @@ class RSSQueue(object):
|
||||
self.jobs[feed][item]['status'] = 'D-'
|
||||
|
||||
|
||||
RE_NEWZBIN = re.compile(r'(newz)(bin|xxx|bin2)\.[\w]+/browse/post/(\d+)', re.I)
|
||||
RE_NEWZBIN = re.compile(r'(newz)(bin|xxx|bin2|xxx2)\.[\w]+/browse/post/(\d+)', re.I)
|
||||
|
||||
def _HandleLink(jobs, link, title, flag, orgcat, cat, pp, script, download, star, order,
|
||||
priority=NORMAL_PRIORITY, rule=0):
|
||||
@@ -617,7 +618,7 @@ def _get_link(uri, entry):
|
||||
link = None
|
||||
category = ''
|
||||
uri = uri.lower()
|
||||
if 'newzbin.' in uri or 'newzxxx.'in uri or 'newzbin2.' in uri:
|
||||
if 'newzbin.' in uri or 'newzxxx.' in uri or 'newzbin2.' in uri or 'newzxxx2.' in uri:
|
||||
link = entry.link
|
||||
if not (link and '/post/' in link.lower()):
|
||||
# Use alternative link
|
||||
|
||||
@@ -94,7 +94,10 @@ class SABTrayThread(SysTrayIconThread):
|
||||
|
||||
# menu handler
|
||||
def opencomplete(self, icon):
|
||||
os.startfile(cfg.complete_dir.get_path())
|
||||
try:
|
||||
os.startfile(cfg.complete_dir.get_path())
|
||||
except WindowsError:
|
||||
pass
|
||||
|
||||
# menu handler
|
||||
def browse(self, icon):
|
||||
|
||||
@@ -625,6 +625,9 @@ class GenericSorter(object):
|
||||
mapping.append(('%decade', self.movie_info['decade']))
|
||||
mapping.append(('%0decade', self.movie_info['decade_two']))
|
||||
|
||||
# Original dir name
|
||||
mapping.append(('%dn', self.original_dirname))
|
||||
|
||||
path = path_subst(sorter, mapping)
|
||||
|
||||
for key, name in REPLACE_AFTER.iteritems():
|
||||
|
||||
@@ -166,7 +166,7 @@ class URLGrabber(Thread):
|
||||
logging.error(msg)
|
||||
misc.bad_fetch(future_nzo, clean_matrix_url(url), msg, retry=True)
|
||||
continue
|
||||
category = _MATRIX_MAP.get(category, category)
|
||||
category = get_matrix_category(url, category)
|
||||
|
||||
if del_bookmark:
|
||||
# No retries of nzbmatrix bookmark removals
|
||||
@@ -398,13 +398,13 @@ _MATRIX_MAP = {
|
||||
'13' : 'games.xbox',
|
||||
'14' : 'games.xbox360',
|
||||
'56' : 'games.xbox360 (other)',
|
||||
'54' : 'movies.brrip',
|
||||
'2' : 'movies.divx/xvid',
|
||||
'1' : 'movies.dvd',
|
||||
'50' : 'movies.hd (image)',
|
||||
'1' : 'movies.sd (image)',
|
||||
'2' : 'movies.sd',
|
||||
'54' : 'movies.hd (remux)',
|
||||
'42' : 'movies.hd (x264)',
|
||||
'50' : 'movies.hd (image)',
|
||||
'4' : 'movies.other',
|
||||
'24' : 'music.dvd',
|
||||
'24' : 'music.sd (image)',
|
||||
'23' : 'music.lossless',
|
||||
'22' : 'music.mp3, albums',
|
||||
'47' : 'music.mp3, singles',
|
||||
@@ -418,7 +418,7 @@ _MATRIX_MAP = {
|
||||
'38' : 'other.iOS/iPhone',
|
||||
'40' : 'other.other',
|
||||
'26' : 'other.radio',
|
||||
'5' : 'tv.dvd (image)',
|
||||
'5' : 'tv.sd (image)',
|
||||
'57' : 'tv.hd (image)',
|
||||
'41' : 'tv.hd (x264)',
|
||||
'8' : 'tv.other',
|
||||
@@ -426,3 +426,9 @@ _MATRIX_MAP = {
|
||||
'7' : 'tv.sport/ent'
|
||||
}
|
||||
|
||||
def get_matrix_category(url, category):
|
||||
category = _MATRIX_MAP.get(category, category)
|
||||
if 'nzbxxx.com' in url:
|
||||
return 'XXX: ' + category
|
||||
else:
|
||||
return category
|
||||
|
||||
Reference in New Issue
Block a user