FIX:(#1905) Unicode errors when logging and system language is not a subset of english, IMP: Added post-processing queue (currently just for forceProcess api, but will be used by default for all post-processing actions soon), IMP: Multiple Torznab support added, IMP: Logging values for number of files and size/file added to config, IMP: Pushover notifications can be sent to specific device now, IMP: Added nzbget, newznab, nzb.su and dognzb test options, IMP: Added graphical checkmark/x when performing various tests (providers, downloaders, notifiers) within configuration, IMP: Removed some more unnecessary logging lines from searches

This commit is contained in:
evilhero 2018-04-06 13:46:39 -04:00
parent 6f57c19290
commit a895f3f8d3
18 changed files with 1045 additions and 404 deletions

View File

@ -62,6 +62,18 @@ def main():
if not mylar.SYS_ENCODING or mylar.SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'):
mylar.SYS_ENCODING = 'UTF-8'
#setup logger for non-english
try:
language = locale.getdefaultlocale()[0][:2]
except:
language = 'en'
mylar.LOG_LANG = language
if language != 'en':
print 'language detected as non-English. Forcing specific logging module - errors WILL NOT be captured in the logs'
else:
print 'log language set to %s' % mylar.LOG_LANG
# Set up and gather command line arguments
parser = argparse.ArgumentParser(description='Automated Comic Book Downloader')
subparsers = parser.add_subparsers(title='Subcommands', dest='maintenance')
@ -98,11 +110,21 @@ def main():
if args.verbose:
mylar.VERBOSE = True
if args.quiet:
#print 'Verbose/Debugging mode enabled...'
#mylar.LOG_LEVEL = 2
elif args.quiet:
mylar.QUIET = True
#print 'Quiet mode enabled...'
#mylar.LOG_LEVEL = 0
else:
#print 'Normal logging mode enabled...'
#mylar.LOG_LEVEL = 1
mylar.VERBOSE = False
# Do an intial setup of the logger.
if mylar.LOG_LANG == 'en':
logger.initLogger(console=not mylar.QUIET, log_dir=False, init=True, verbose=mylar.VERBOSE)
#logger.mylar_log.initLogger(loglevel=mylar.LOG_LEVEL)
if args.daemon:
if sys.platform == 'win32':
@ -125,7 +147,7 @@ def main():
except IOError, e:
raise SystemExit("Unable to write PID file: %s [%d]" % (e.strerror, e.errno))
else:
logger.warn("Not running in daemon mode. PID file creation disabled.")
print("Not running in daemon mode. PID file creation disabled.")
if args.datadir:
mylar.DATA_DIR = args.datadir
@ -147,6 +169,19 @@ def main():
else:
mylar.NOWEEKLY = False
# Put the database in the DATA_DIR
mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')
# Read config and start logging
if mylar.MAINTENANCE is False:
print('Initializing startup sequence....')
#try:
mylar.initialize(mylar.CONFIG_FILE)
#except Exception as e:
# print e
# raise SystemExit('FATAL ERROR')
if mylar.MAINTENANCE is False:
filechecker.validateAndCreateDirectory(mylar.DATA_DIR, True)
@ -154,9 +189,6 @@ def main():
if not os.access(mylar.DATA_DIR, os.W_OK):
raise SystemExit('Cannot write to the data directory: ' + mylar.DATA_DIR + '. Exiting...')
# Put the database in the DATA_DIR
mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')
# backup the db and configs before they load.
if args.backup:
print '[AUTO-BACKUP] Backing up .db and config.ini files for safety.'
@ -198,17 +230,6 @@ def main():
i += 1
# Read config and start logging
if mylar.MAINTENANCE is False:
logger.info('Initializing startup sequence....')
try:
mylar.initialize(mylar.CONFIG_FILE)
except Exception as e:
print e
raise SystemExit('FATAL ERROR')
# Rename the main thread
threading.currentThread().name = "MAIN"

View File

@ -395,6 +395,7 @@
</div>
<div align="center" class="row">
<img name="sabnzbd_statusicon" id="sabnzbd_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test SABnzbd" id="test_sab" style="float:center" /></br>
<input type="text" name="sabstatus" style="text-align:center; font-size:11px;" id="sabstatus" size="50" DISABLED />
</div>
@ -403,20 +404,20 @@
<fieldset id="nzbget_options">
<div class="row">
<label>NZBGet Host:</label>
<input type="text" name="nzbget_host" value="${config['nzbget_host']}" size="30">
<input type="text" id="nzbget_host" name="nzbget_host" value="${config['nzbget_host']}" size="30">
<small>usually http://localhost</small>
</div>
<div class="row">
<label>NZBGet Port:</label>
<input type="text" name="nzbget_port" value="${config['nzbget_port']}" size="36">
<input type="text" id="nzbget_port" name="nzbget_port" value="${config['nzbget_port']}" size="36">
</div>
<div class="row">
<label>NZBGet Username:</label>
<input type="text" name="nzbget_username" value="${config['nzbget_user']}" size="20">
<input type="text" id="nzbget_username" name="nzbget_username" value="${config['nzbget_user']}" size="20">
</div>
<div class="row">
<label>NZBGet Password:</label>
<input type="password" name="nzbget_password" value="${config['nzbget_pass']| h}" size="20">
<input type="password" id="nzbget_password" name="nzbget_password" value="${config['nzbget_pass']| h}" size="20">
</div>
<div class="row">
<label>NZBGet Download Directory</label>
@ -447,6 +448,12 @@
<small>The category label above is used to when completed download handling is enabled</small>
</div>
<div align="center" class="row">
<img name="nzbget_statusicon" id="nzbget_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test NZBGet" id="test_nzbget" style="float:center" /></br>
<input type="text" name="nzbgetstatus" style="text-align:center; font-size:11px;" id="nzbgetstatus" size="50" DISABLED />
</div>
</fieldset>
<fieldset id="blackhole_options">
<div class="row">
@ -595,6 +602,7 @@
<small>Automatically start torrent on successful loading within rtorrent client</small>
</div>
<div class="row">
<img name="rtorrent_statusicon" id="rtorrent_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test Connection" id="rtorrent_test" />
</div>
</fieldset>
@ -692,7 +700,7 @@
</div>
<div class="config">
<div class="row checkbox">
<input type="checkbox" name="nzbsu_verify" value="1" ${config['nzbsu_verify']} /><label>Verify SSL</label>
<input type="checkbox" name="nzbsu_verify" id="nzbsu_verify" value="1" ${config['nzbsu_verify']} /><label>Verify SSL</label>
</div>
<div class="row">
<label>NZB.SU UID</label>
@ -701,7 +709,11 @@
</div>
<div class="row">
<label>NZB.SU API</label>
<input type="text" name="nzbsu_apikey" value="${config['nzbsu_api']}" size="36">
<input type="text" name="nzbsu_apikey" id="nzbsu_apikey" value="${config['nzbsu_api']}" size="36">
</div>
<div>
<img name="nzbsu_statusicon" id="nzbsu_statusicon" src="interfaces/default/images/success.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" class="newznabtest" value="Test Connection" id="test_nzbsu" name="test_nzbsu" style="float:right;margin-right:10px;" />
</div>
</div>
</fieldset>
@ -712,11 +724,15 @@
</div>
<div class="config">
<div class="row checkbox">
<input id="dognzb_verify" type="checkbox" name="dognzb_verify" value="1" ${config['dognzb_verify']} /><label>Verify SSL</label>
<input id="dognzb_verify" type="checkbox" name="dognzb_verify" id="dognzb_verify" value="1" ${config['dognzb_verify']} /><label>Verify SSL</label>
</div>
<div class="row">
<label>DOGNZB API</label>
<input type="text" name="dognzb_apikey" value="${config['dognzb_api']}" size="36">
<input type="text" name="dognzb_apikey" id="dognzb_apikey" value="${config['dognzb_api']}" size="36">
</div>
<div>
<img name="dognzb_statusicon" id="dognzb_statusicon" src="interfaces/default/images/success.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" class="newznabtest" value="Test Connection" id="test_dognzb" name="test_dognzb" style="float:right;margin-right:10px;" />
</div>
</div>
</fieldset>
@ -780,6 +796,7 @@
<small>( monitor the NEW releases feed & your personal notifications )</small>
</div>
<div align="center" class="row">
<img name="test32p_statusicon" id="test32p_statusicon" src="interfaces/default/images/success.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test Connection" id="test_32p" style="float:center" /></br>
<input type="text" name="status32p" style="text-align:center; font-size:11px;" id="status32p" size="50" DISABLED />
</div>
@ -797,23 +814,50 @@
<div class="row checkbox left clearfix">
<input type="checkbox" id="enable_torznab" onclick="initConfigCheckbox($(this));" name="enable_torznab" value=1 ${config['enable_torznab']} /><label>Enable Torznab</label>
</div>
<div class="config">
<div id="torznab_providers">
<%
torznab_number = 1
%>
%for torznab in config['extra_torznabs']:
<%
if torznab[4] == '1' or torznab[4] == 1:
torznab_enabled = "checked"
else:
torznab_enabled = ""
%>
<div class="config" id="torznab${torznab_number}">
<div class="row">
<label>Torznab Name</label>
<input type="text" name="torznab_name" value="${config['torznab_name']}" size="30">
<input type="text" name="torznab_name${torznab_number}" id="torznab_name${torznab_number}" value="${torznab[0]}" size="30">
</div>
<div class="row">
<label>Torznab Host</label>
<input type="text" name="torznab_host" value="${config['torznab_host']}" size="30">
<input type="text" name="torznab_host${torznab_number}" id="torznab_host${torznab_number}" value="${torznab[1]}" size="30">
</div>
<div class="row">
<label>Torznab API</label>
<input type="text" name="torznab_apikey" value="${config['torznab_apikey']}" size="36">
<input type="text" name="torznab_apikey${torznab_number}" id="torznab_apikey${torznab_number}" value="${torznab[2]}" size="36">
</div>
<div class="row">
<label>Torznab Category</label>
<input type="text" name="torznab_category" value="${config['torznab_category']}" size="12">
<input type="text" name="torznab_category${torznab_number}" id="torznab_category${torznab_number}" value="${torznab[3]}" size="12">
</div>
<div class="row checkbox">
<input id="torznab_enabled${torznab_number}" type="checkbox" name="torznab_enabled${torznab_number}" value="1" ${torznab_enabled} /><label>Enabled</label>
<img name="torznabstatus${torznab_number}" id="torznabstatus${torznab_number}" src="interfaces/default/images/success.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" class="torznabtest" value="Test ${torznab[0]}" id="torznab_test${torznab_number}" name="torznab_test${torznab_number}" style="float:right;margin-right:10px;" />
</div>
<div class="row">
<input type="button" class="remove" id="torznab${torznab_number}" value="Remove ${torznab[0]}">
</div>
</div>
<%
torznab_number += 1
%>
%endfor
<input type="button" value="Add Torznab" class="add_torznab" id="add_torznab" />
</div>
</div>
</fieldset>
@ -864,9 +908,9 @@
<small>( only needed for RSS feed )</small>
</div>
<div class="row checkbox">
<input id="newznab_enabled" type="checkbox" name="newznab_enabled${newznab_number}" value="1" ${newznab_enabled} /><label>Enabled</label>
<input type="button" value="Test ${newznab[0]}" name="${newznab_number}" id="newznabtest" style="float:center" />
<img name="newznabstatus${newznab_number}" id="newznabstatus${newznab_number}" src="interfaces/default/images/checkmark.png" style="vertical-align: middle; margin: 3px; margin-top: -1px; display: none" height="10" width="10">
<input id="newznab_enabled${newznab_number}" type="checkbox" name="newznab_enabled${newznab_number}" value="1" ${newznab_enabled} /><label>Enabled</label>
<img name="newznabstatus${newznab_number}" id="newznabstatus${newznab_number}" src="interfaces/default/images/success.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" class="newznabtest" value="Test ${newznab[0]}" id="newznab_test${newznab_number}" name="newznab_test${newznab_number}" style="float:right;margin-right:10px;" />
</div>
<div class="row">
<input type="button" class="remove" id="newznab${newznab_number}" value="Remove ${newznab[0]}">
@ -903,9 +947,9 @@
<fieldset>
<legend>Quality</legend>
<div class="row radio left clearfix">
<input type="radio" style="vertical-align: middle; margin: 3px; margin-top: -1px;" name="preferred_quality" value="1" ${config['pref_qual_1']} /><label>cbr</label>
<input type="radio" style="vertical-align: middle; margin: 3px; margin-top: -1px;" name="preferred_quality" value="2" ${config['pref_qual_2']} /><label>cbz</label>
<input type="radio" style="vertical-align: middle; margin: 3px; margin-top: -1px;" name="preferred_quality" value="0" ${config['pref_qual_0']} /><label>Whichever - just get it</label>
<input type="radio" style="vertical-align: middle; margin: 3px; margin-top: -1px;" name="preferred_quality" value="1" ${config['pref_qual_1']} /><label>cbr</label>
<input type="radio" style="vertical-align: middle; margin: 3px; margin-top: -1px;" name="preferred_quality" value="2" ${config['pref_qual_2']} /><label>cbz</label>
<input type="radio" style="vertical-align: middle; margin: 3px; margin-top: -1px;" name="preferred_quality" value="0" ${config['pref_qual_0']} /><label>Whichever - just get it</label>
</div>
</fieldset>
<fieldset>
@ -1209,7 +1253,7 @@
</div>
<div id="prowloptions">
<div class="row">
<label>API key</label><input type="text" name="prowl_keys" value="${config['prowl_keys']}" size="50">
<label>API key</label><input type="text" id="prowl_keys" name="prowl_keys" value="${config['prowl_keys']}" size="50">
</div>
<div class="row checkbox">
<input type="checkbox" name="prowl_onsnatch" value="1" ${config['prowl_onsnatch']} /><label>Notify on snatch?</label>
@ -1219,6 +1263,7 @@
<input type="text" name="prowl_priority" value="${config['prowl_priority']}" size="2">
</div>
<div class="row">
<img name="prowl_statusicon" id="prowl_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test PROWL" id="prowl_test" />
</div>
</div>
@ -1263,6 +1308,7 @@
</select>
</div>
<div align="center" class="row">
<img name="nma_statusicon" id="nma_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test NMA" id="nma_test" style="float:center" /></br>
<input type="text" name="nmastatus" style="text-align:center; font-size:11px;" id="nmastatus" size="55" DISABLED />
</div>
@ -1281,6 +1327,9 @@
<div class="row">
<label>User key</label><input type="text" name="pushover_userkey" id="pushover_userkey" value="${config['pushover_userkey']}" size="50">
</div>
<div class="row">
<label>Device</label><input type="text" title="Specific Device ID to push notifications to" name="pushover_device" id="pushover_device" value="${config['pushover_device']}" size="50">
</div>
<div class="row checkbox">
<input type="checkbox" name="pushover_onsnatch" value="1" ${config['pushover_onsnatch']} /><label>Notify on snatch?</label>
</div>
@ -1289,6 +1338,7 @@
<input type="text" name="pushover_priority" value="${config['pushover_priority']}" size="2">
</div>
<div align="center" class="row">
<img name="pushover_statusicon" id="pushover_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test Pushover" id="pushover_test" style="float:center" /></br>
<input type="text" name="pushoverstatus" style="text-align:center; font-size:11px;" id="pushoverstatus" size="55" DISABLED />
</div>
@ -1308,6 +1358,7 @@
<label>Boxcar Token</label>
<input type="text" name="boxcar_token" value="${config['boxcar_token']}" size="30">
<div class="row">
<img name="boxcar_statusicon" id="boxcar_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test Boxcar" id="boxcar_test" />
</div>
</div>
@ -1339,6 +1390,7 @@
<small>Send to all subscribers of the channel with this tag (Optional)</small>
</div>
<div align="center" class="row">
<img name="pushbullet_statusicon" id="pushbullet_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test Pushbullet" id="pushbullet_test" style="float:center" /></br>
<input type="text" name="pbstatus" style="text-align:center; font-size:11px;" id="pbstatus" size="55" DISABLED />
</div>
@ -1361,6 +1413,7 @@
<input type="checkbox" name="telegram_onsnatch" value="1" ${config['telegram_onsnatch']} /><label>Notify on snatch?</label>
</div>
<div align="center" class="row">
<img name="telegram_statusicon" id="telegram_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test Telegram" id="telegram_test" style="float:center" /></br>
<input type="text" name="telegramstatus" style="text-align:center; font-size:11px;" id="telegramstatus" size="55" DISABLED />
</div>
@ -1380,6 +1433,7 @@
<input type="checkbox" name="slack_onsnatch" value="1" ${config['slack_onsnatch']} /><label>Notify on snatch?</label>
</div>
<div align="center" class="row">
<img name="slack_statusicon" id="slack_statusicon" src="interfaces/default/images/successs.png" style="float:right;visibility:hidden;" height="20" width="20" />
<input type="button" value="Test Slack" id="slack_test" style="float:center" /></br>
<input type="text" name="slackstatus" style="text-align:center; font-size:11px;" id="slackstatus" size="55" DISABLED />
</div>
@ -1820,6 +1874,7 @@
});
var deletedNewznabs = 0;
var deletedTorznabs = 0;
$(".remove").click(function() {
$(this).parent().parent().remove();
@ -1843,6 +1898,7 @@
};
$("#test_32p").click(function(){
var imagechk = document.getElementById("test32p_statusicon");
$.get('test_32p',
function(data){
if (data.error != undefined) {
@ -1854,14 +1910,26 @@
inkd = numberWithCommas(inkd);
$('#status32p').val(obj['status']);
$('#inkdrops32p span').text('Inkdrops Available: '+inkd);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#test_sab').click(function () {
var sabhost = document.getElementById('sab_host').value;
var sabuser = document.getElementById('sab_username').value;
var sabpass = document.getElementById('sab_password').value;
var sabapi = document.getElementById('sab_apikey').value;
var imagechk = document.getElementById("sabnzbd_statusicon");
var sabhost = document.getElementById("sab_host").value;
var sabuser = document.getElementById("sab_username").value;
var sabpass = document.getElementById("sab_password").value;
var sabapi = document.getElementById("sab_apikey").value;
$.get("SABtest",
{ sabhost: sabhost, sabusername: sabuser, sabpassword: sabpass, sabapikey: sabapi },
function(data){
@ -1870,8 +1938,44 @@
return;
}
$('#sabstatus').val(data);
// $('#sab_apikey').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#test_nzbget').click(function () {
var imagechk = document.getElementById("nzbget_statusicon");
var nzbhost = document.getElementById("nzbget_host").value;
var nzbport = document.getElementById("nzbget_port").value;
var nzbuser = document.getElementById("nzbget_username").value;
var nzbpass = document.getElementById("nzbget_password").value;
$.get("NZBGet_test",
{ nzbhost: nzbhost, nzbport: nzbport, nzbusername: nzbuser, nzbpassword: nzbpass },
function(data){
if (data.error != undefined) {
alert(data.error);
return;
}
$('#nzbgetstatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
@ -1929,16 +2033,32 @@
$("#add_newznab").click(function() {
var intId = $("#newznab_providers > div").size() + deletedNewznabs + 1;
var formfields = $("<div class=\"config\" id=\"newznab" + intId + "\"><div class=\"row\"><label>Newznab Name</label><input type=\"text\" name=\"newznab_name" + intId + "\" size=\"36\"></div><div class=\"row\"><label>Newznab Host</label><input type=\"text\" name=\"newznab_host" + intId + "\" + value=\"http://\" + size=\"30\"></div><div class=\"row checkbox\"><input type=\"checkbox\" name=\"newznab_verify" + intId + "\" value=\"0\" checked /><label>Verify SSL</label></div><div class=\"row\"><label>Newznab API</label><input type=\"text\" name=\"newznab_api" + intId + "\" size=\"36\"></div><div class=\"row\"><label>Newznab UID</label><input type=\"text\" name=\"newznab_uid" + intId + "\" size=\"15\"></div><div class=\"row checkbox\"><input type=\"checkbox\" name=\"newznab_enabled" + intId + "\" value=\"1\" checked /><label>Enabled</label></div>");
var removeButton = $("<div class=\"row\"><input type=\"button\" class=\"remove\" value=\"Remove\" /></div>");
removeButton.click(function() {
var newzformfields = $("<div class=\"config\" id=\"newznab" + intId + "\"><div class=\"row\"><label>Newznab Name</label><input type=\"text\" id=\"newznab_name" + intId + "\" name=\"newznab_name" + intId + "\" size=\"36\"></div><div class=\"row\"><label>Newznab Host</label><input type=\"text\" id=\"newznab_host" + intId + "\" name=\"newznab_host" + intId + "\" + value=\"http://\" + size=\"30\"></div><div class=\"row checkbox\"><input type=\"checkbox\" id=\"newznab_verify" + intId + "\" name=\"newznab_verify" + intId + "\" value=\"0\" checked /><label>Verify SSL</label></div><div class=\"row\"><label>Newznab API</label><input type=\"text\" id=\"newznab_api" + intId + "\" name=\"newznab_api" + intId + "\" size=\"36\"></div><div class=\"row\"><label>Newznab UID</label><input type=\"text\" id=\"newznab_uid" + intId + "\" name=\"newznab_uid" + intId + "\" size=\"15\"></div><div class=\"row checkbox\"><input type=\"checkbox\" name=\"newznab_enabled" + intId + "\" value=\"1\" checked /><label>Enabled</label></div>");
var newztestButton = $("<div class=\"row\"><img name=\"newznabstatus" + intId + "\" id=\"newznabstatus" + intId + "\" src=\"interfaces/default/images/success.png\" style=\"float:right;visibility:hidden;\" height=\"20\" width=\"20\" /><input type=\"button\" class=\"newznabtest\" value=\"Test\" id=\"newznab_test" + intId + "\" name=\"newznab_test" + intId + "\" style=\"float:right;margin-right:10px;\" /></div>");
var newzremoveButton = $("<div class=\"row\"><input type=\"button\" class=\"remove\" value=\"Remove\" /></div>");
newzremoveButton.click(function() {
$(this).parent().remove();
deletedNewznabs = deletedNewznabs + 1;
});
formfields.append(removeButton);
formfields.append("</div>");
$("#add_newznab").before(formfields);
newzformfields.append(newztestButton);
newzformfields.append(newzremoveButton);
newzformfields.append("</div>");
$("#add_newznab").before(newzformfields);
});
$("#add_torznab").click(function() {
var intId = $("#torznab_providers > div").size() + deletedTorznabs + 1;
var torformfields = $("<div class=\"config\" id=\"torznab" + intId + "\"><div class=\"row\"><label>Torznab Name</label><input type=\"text\" id=\"torznab_name" + intId + "\" name=\"torznab_name" + intId + "\" size=\"36\"></div><div class=\"row\"><label>Torznab Host</label><input type=\"text\" id=\"torznab_host" + intId + "\" name=\"torznab_host" + intId + "\" + value=\"http://\" + size=\"30\"></div><div class=\"row\"><label>Torznab API</label><input type=\"text\" id=\"torznab_apikey" + intId + "\" name=\"torznab_apikey" + intId + "\" size=\"36\"></div><div class=\"row\"><label>Torznab Category</label><input type=\"text\" id=\"torznab_category" + intId + "\" name=\"torznab_category" + intId + "\" size=\"36\"></div><div class=\"row checkbox\"><input type=\"checkbox\" name=\"torznab_enabled" + intId + "\" value=\"1\" checked /><label>Enabled</label></div>");
var tortestButton = $("<div class=\"row\"><img name=\"torznabstatus" + intId + "\" id=\"torznabstatus" + intId + "\" src=\"interfaces/default/images/success.png\" style=\"float:right;visibility:hidden;\" height=\"20\" width=\"20\" /><input type=\"button\" class=\"torznabtest\" value=\"Test\" id=\"torznab_test" + intId + "\" name=\"torznab_test" + intId + "\" style=\"float:right;margin-right:10px;\" /></div>");
var torremoveButton = $("<div class=\"row\"><input type=\"button\" class=\"remove\" value=\"Remove\" /></div>");
torremoveButton.click(function() {
$(this).parent().remove();
deletedTorznabs = deletedTorznabs + 1;
});
torformfields.append(tortestButton);
torformfields.append(torremoveButton);
torformfields.append("</div>");
$("#add_torznab").before(torformfields);
});
function addAction() {
@ -1946,14 +2066,14 @@
};
$('#rtorrent_test').click(function () {
var host = document.getElementById('rtorrent_host').value;
var username = document.getElementById('rtorrent_username').value;
var password = document.getElementById('rtorrent_password').value;
var auth = document.getElementById('rtorrent_authentication').value;
var verify = document.getElementById('rtorrent_verify').value;
var ssl = document.getElementById('rtorrent_ssl').value;
var rpc_url = document.getElementById('rtorrent_rpc_url').value;
alert(host);
var imagechk = document.getElementById("rtorrent_statusicon");
var host = document.getElementById("rtorrent_host").value;
var username = document.getElementById("rtorrent_username").value;
var password = document.getElementById("rtorrent_password").value;
var auth = document.getElementById("rtorrent_authentication").value;
var verify = document.getElementById("rtorrent_verify").value;
var ssl = document.getElementById("rtorrent_ssl").value;
var rpc_url = document.getElementById("rtorrent_rpc_url").value;
$.get("testrtorrent",
{ host: host, username: username, password: password, auth: auth, verify: verify, ssl: ssl, rpc_url: rpc_url },
function(data){
@ -1963,16 +2083,40 @@
}
//$('#rtorrentstatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#newznabtest').click(function () {
var newznab = document.getElementById("newznabtest").getAttribute("name");
$(".newznabtest").click(function () {
var newznab = this.attributes["name"].value.replace('newznab_test', '');
if ( newznab.indexOf("test_dognzb") > -1) {
var imagechk = document.getElementById("dognzb_statusicon");
var name = 'DOGnzb';
var host = 'https://api.dognzb.cr';
var ssl = document.getElementById("dognzb_verify").value;
var apikey = document.getElementById("dognzb_apikey").value;
} else if ( newznab.indexOf("test_nzbsu") > -1) {
var imagechk = document.getElementById("nzbsu_statusicon");
var name = 'nzb.su';
var host = 'https://api.nzb.su';
var ssl = document.getElementById("nzbsu_verify").value;
var apikey = document.getElementById("nzbsu_apikey").value;
} else {
var imagechk = document.getElementById("newznabstatus"+newznab);
var name = document.getElementById("newznab_name"+newznab).value;
var host = document.getElementById("newznab_host"+newznab).value;;
var ssl = document.getElementById("newznab_verify"+newznab).value;
var apikey = document.getElementById("newznab_api"+newznab).value;
}
$.get("testnewznab",
{ name: name, host: host, ssl: ssl, apikey: apikey },
function(data){
@ -1980,14 +2124,50 @@
alert(data.error);
return;
}
document.getElementById("newznabstatus" + newznab).style.display = "inline";
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$(".torznabtest").click(function () {
var torznab = this.attributes["name"].value.replace('torznab_test', '');
var imagechk = document.getElementById("tornabstatus"+torznab);
var name = document.getElementById("torznab_name"+torznab).value;
var host = document.getElementById("torznab_host"+torznab).value;
var apikey = document.getElementById("torznab_api"+torznab).value;
$.get("testtorznab",
{ name: name, host: host, ssl: ssl, apikey: apikey },
function(data){
if (data.error != undefined) {
alert(data.error);
return;
}
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#nma_test').click(function () {
var apikey = document.getElementById('nma_apikey').value;
var imagechk = document.getElementById("nma_statusicon");
var apikey = document.getElementById("nma_apikey").value;
$.get("testNMA",
{ apikey: apikey },
function(data){
@ -1997,21 +2177,50 @@
}
$('#nmastatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#prowl_test').click(function () {
var imagechk = document.getElementById("prowl_statusicon");
var apikey = document.getElementById("prowl_keys");
$.get("testprowl",
function (data) { $('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>"); });
{ apikey: apikey },
function (data) {
if (data.error != undefined) {
alert(data.error);
return;
}
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#pushover_test').click(function () {
var apikey = document.getElementById('pushover_apikey').value;
var userkey = document.getElementById('pushover_userkey').value;
var imagechk = document.getElementById("pushover_statusicon");
var apikey = document.getElementById("pushover_apikey").value;
var userkey = document.getElementById("pushover_userkey").value;
var device = document.getElementById("pushover_device").value;
$.get("testpushover",
{ apikey: apikey, userkey: userkey },
{ apikey: apikey, userkey: userkey , device: device},
function(data){
if (data.error != undefined) {
alert(data.error);
@ -2019,18 +2228,47 @@
}
$('#pushoverstatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#boxcar_test').click(function () {
var imagechk = document.getElementById("boxcar_statusicon");
var token = document.getElementById("boxcar_token");
$.get("testboxcar",
function (data) { $('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>"); });
{ token: token },
function (data) {
if (data.error != undefined) {
alert(data.error);
return;
}
$('#pushoverstatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#pushbullet_test').click(function () {
var apikey = document.getElementById('pushbullet_apikey').value;
var imagechk = document.getElementById("pushbullet_statusicon");
var apikey = document.getElementById("pushbullet_apikey").value;
$.get("testpushbullet",
{ apikey: apikey },
function(data){
@ -2040,13 +2278,23 @@
}
$('#pbstatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#telegram_test').click(function () {
var userid = document.getElementById('telegram_userid').value;
var token = document.getElementById('telegram_token').value;
var imagechk = document.getElementById("telegram_statusicon");
var userid = document.getElementById("telegram_userid").value;
var token = document.getElementById("telegram_token").value;
$.get("testtelegram",
{ userid: userid, token: token },
function(data){
@ -2056,12 +2304,22 @@
}
$('#telegramstatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});
$('#slack_test').click(function () {
var webhook_url = document.getElementById('slack_webhook_url').value;
var imagechk = document.getElementById("slack_statusicon");
var webhook_url = document.getElementById("slack_webhook_url").value;
$.get("testslack",
{ webhook_url: webhook_url },
function(data){
@ -2071,6 +2329,15 @@
}
$('#slackstatus').val(data);
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>");
if ( data.indexOf("Successfully") > -1){
imagechk.src = "";
imagechk.src = "interfaces/default/images/success.png";
imagechk.style.visibility = "visible";
} else {
imagechk.src = "";
imagechk.src = "interfaces/default/images/fail.png";
imagechk.style.visibility = "visible";
}
});
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut();
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -65,7 +65,7 @@ class FailedProcessor(object):
if queue: self.queue = queue
self.valreturn = []
def _log(self, message, level=logger.message):
def _log(self, message, level=logger): #.message):
"""
A wrapper for the internal logger which also keeps track of messages and saves them to a string

View File

@ -62,8 +62,12 @@ class PostProcessor(object):
if queue:
self.queue = queue
if mylar.APILOCK is True:
return {'status': 'IN PROGRESS'}
if apicall is True:
self.apicall = True
mylar.APILOCK = True
else:
self.apicall = False
@ -86,7 +90,7 @@ class PostProcessor(object):
else:
self.comicid = None
def _log(self, message, level=logger.message): #level=logger.MESSAGE):
def _log(self, message, level=logger): #.message): #level=logger.MESSAGE):
"""
A wrapper for the internal logger which also keeps track of messages and saves them to a string for sabnzbd post-processing logging functions.
@ -641,8 +645,10 @@ class PostProcessor(object):
if datematch == 'True':
if watchmatch['sub']:
logger.fdebug('%s[SUB: %s][CLOCATION: %s]' % (module, watchmatch['sub'], watchmatch['comiclocation']))
clocation = os.path.join(watchmatch['comiclocation'], watchmatch['sub'], helpers.conversion(watchmatch['comicfilename']))
else:
logger.fdebug('%s[CLOCATION] %s' % (module, watchmatch['comiclocation']))
if self.issueid is not None and os.path.isfile(watchmatch['comiclocation']):
clocation = watchmatch['comiclocation']
else:
@ -1272,6 +1278,8 @@ class PostProcessor(object):
logger.info('%s post-processing of pack completed for %s issues [FAILED: %s]' % (module, i, self.failed_files))
else:
logger.info('%s Manual post-processing completed for %s issues [FAILED: %s]' % (module, i, self.failed_files))
if mylar.APILOCK is True:
mylar.APILOCK = False
return
else:
pass
@ -2283,7 +2291,8 @@ class PostProcessor(object):
"mode": 'stop',
"issueid": issueid,
"comicid": comicid})
if self.apicall is True:
self.sendnotify(series, issueyear, issuenumOG, annchk, module)
return self.queue.put(self.valreturn)
self.sendnotify(series, issueyear, issuenumOG, annchk, module)

View File

@ -51,6 +51,8 @@ FULL_PATH = None
MAINTENANCE = False
LOG_DIR = None
LOGTYPE = 'log'
LOG_LANG = 'en'
LOGLIST = []
ARGS = None
SIGNAL = None
SYS_ENCODING = None
@ -61,7 +63,6 @@ DAEMON = False
PIDFILE= None
CREATEPID = False
QUIET=False
LOG_LEVEL = 0
MAX_LOGSIZE = 5000000
SAFESTART = False
NOWEEKLY = False
@ -120,10 +121,10 @@ SNPOOL = None
NZBPOOL = None
SNATCHED_QUEUE = Queue.Queue()
NZB_QUEUE = Queue.Queue()
PP_QUEUE = Queue.Queue()
COMICSORT = None
PULLBYFILE = None
CFG = None
LOG_LIST = []
CURRENT_WEEKNUMBER = None
CURRENT_YEAR = None
INSTALL_TYPE = None
@ -133,6 +134,7 @@ LATEST_VERSION = None
COMMITS_BEHIND = None
LOCAL_IP = None
DOWNLOAD_APIKEY = None
APILOCK = False
CMTAGGER_PATH = None
STATIC_COMICRN_VERSION = "1.01"
STATIC_APC_VERSION = "2.01"
@ -153,11 +155,11 @@ def initialize(config_file):
with INIT_LOCK:
global CONFIG, _INITIALIZED, QUIET, CONFIG_FILE, OS_DETECT, MAINTENANCE, CURRENT_VERSION, LATEST_VERSION, COMMITS_BEHIND, INSTALL_TYPE, IMPORTLOCK, PULLBYFILE, INKDROPS_32P, \
DONATEBUTTON, CURRENT_WEEKNUMBER, CURRENT_YEAR, UMASK, USER_AGENT, SNATCHED_QUEUE, NZB_QUEUE, PULLNEW, COMICSORT, WANTED_TAB_OFF, CV_HEADERS, \
DONATEBUTTON, CURRENT_WEEKNUMBER, CURRENT_YEAR, UMASK, USER_AGENT, SNATCHED_QUEUE, NZB_QUEUE, PP_QUEUE, PULLNEW, COMICSORT, WANTED_TAB_OFF, CV_HEADERS, \
IMPORTBUTTON, IMPORT_FILES, IMPORT_TOTALFILES, IMPORT_CID_COUNT, IMPORT_PARSED_COUNT, IMPORT_FAILURE_COUNT, CHECKENABLED, CVURL, DEMURL, WWTURL, \
USE_SABNZBD, USE_NZBGET, USE_BLACKHOLE, USE_RTORRENT, USE_UTORRENT, USE_QBITTORRENT, USE_DELUGE, USE_TRANSMISSION, USE_WATCHDIR, SAB_PARAMS, \
PROG_DIR, DATA_DIR, CMTAGGER_PATH, DOWNLOAD_APIKEY, LOCAL_IP, STATIC_COMICRN_VERSION, STATIC_APC_VERSION, KEYS_32P, AUTHKEY_32P, FEED_32P, FEEDINFO_32P, \
MONITOR_STATUS, SEARCH_STATUS, RSS_STATUS, WEEKLY_STATUS, VERSION_STATUS, UPDATER_STATUS, DBUPDATE_INTERVAL, \
MONITOR_STATUS, SEARCH_STATUS, RSS_STATUS, WEEKLY_STATUS, VERSION_STATUS, UPDATER_STATUS, DBUPDATE_INTERVAL, LOG_LEVEL, LOG_LANG, APILOCK, \
SCHED_RSS_LAST, SCHED_WEEKLY_LAST, SCHED_MONITOR_LAST, SCHED_SEARCH_LAST, SCHED_VERSION_LAST, SCHED_DBUPDATE_LAST, COMICINFO
cc = mylar.config.Config(config_file)
@ -168,11 +170,11 @@ def initialize(config_file):
if _INITIALIZED:
return False
#set up the default values here if they're wrong.
#cc.configure()
# Start the logger, silence console logging if we need to
logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR, verbose=VERBOSE) #logger.mylar_log.initLogger(verbose=VERBOSE)
if mylar.LOG_LANG == 'en':
logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR, verbose=VERBOSE)
else:
logger.mylar_log.initLogger(loglevel=mylar.LOG_LEVEL)
# Also sets INSTALL_TYPE variable to 'win', 'git' or 'source'
CURRENT_VERSION, CONFIG.GIT_BRANCH = versioncheck.getVersion()
@ -407,6 +409,11 @@ def start():
elif CONFIG.NZB_DOWNLOADER == 1:
logger.info('[AUTO-COMPLETE-NZB] Succesfully started Completed post-processing handling for NZBGet - will now monitor for completed nzbs within nzbget and post-process automatically....')
if all([CONFIG.POST_PROCESSING is True, CONFIG.API_ENABLED is True]):
logger.info('[POST-PROCESS-QUEUE] Post Process queue enabled & monitoring for api requests....')
PPPOOL = threading.Thread(target=helpers.postprocess_main, args=(PP_QUEUE,), name="POST-PROCESS-QUEUE")
PPPOOL.start()
logger.info('[POST-PROCESS-QUEUE] Succesfully started Post-Processing Queuer....')
helpers.latestdate_fix()

View File

@ -330,6 +330,7 @@ class Api(object):
return
def _forceProcess(self, **kwargs):
if 'nzb_name' not in kwargs:
self.data = self._error_with_message('Missing parameter: nzb_name')
return
@ -358,8 +359,16 @@ class Api(object):
comicid = kwargs['comicid']
if 'apc_version' not in kwargs:
fp = process.Process(self.nzb_name, self.nzb_folder, issueid=issueid, failed=failed, comicid=comicid, apicall=True)
self.data = fp.post_process()
logger.info('Received API Request for PostProcessing %s [%s]. Queueing...' % (self.nzb_name, self.nzb_folder))
mylar.PP_QUEUE.put({'nzb_name': self.nzb_name,
'nzb_folder': self.nzb_folder,
'issueid': issueid,
'failed': failed,
'comicid': comicid,
'apicall': True})
self.data = 'Successfully submitted request for post-processing for %s' % self.nzb_name
#fp = process.Process(self.nzb_name, self.nzb_folder, issueid=issueid, failed=failed, comicid=comicid, apicall=True)
#self.data = fp.post_process()
else:
logger.info('[API] Api Call from ComicRN detected - initiating script post-processing.')
fp = webserve.WebInterface()

View File

@ -114,6 +114,7 @@ _CONFIG_DEFINITIONS = OrderedDict({
'LOG_DIR' : (str, 'Logs', None),
'MAX_LOGSIZE' : (int, 'Logs', 10000000),
'MAX_LOGFILES': (int, 'Logs', 5),
'LOG_LEVEL': (int, 'Logs', 0),
'GIT_PATH' : (str, 'Git', None),
@ -151,6 +152,7 @@ _CONFIG_DEFINITIONS = OrderedDict({
'PUSHOVER_ENABLED': (bool, 'PUSHOVER', False),
'PUSHOVER_PRIORITY': (int, 'PUSHOVER', 0),
'PUSHOVER_APIKEY': (str, 'PUSHOVER', None),
'PUSHOVER_DEVICE': (str, 'PUSHOVER', None),
'PUSHOVER_USERKEY': (str, 'PUSHOVER', None),
'PUSHOVER_ONSNATCH': (bool, 'PUSHOVER', False),
@ -227,6 +229,7 @@ _CONFIG_DEFINITIONS = OrderedDict({
'EXTRA_NEWZNABS': (str, 'Newznab', ""),
'ENABLE_TORZNAB': (bool, 'Torznab', False),
'EXTRA_TORZNABS': (str, 'Torznab', ""),
'TORZNAB_NAME': (str, 'Torznab', None),
'TORZNAB_HOST': (str, 'Torznab', None),
'TORZNAB_APIKEY': (str, 'Torznab', None),
@ -365,7 +368,7 @@ class Config(object):
count = sum(1 for line in open(self._config_file))
else:
count = 0
self.newconfig = 7
self.newconfig = 8
if count == 0:
CONFIG_VERSION = 0
MINIMALINI = False
@ -479,11 +482,16 @@ class Config(object):
def read(self):
self.config_vals()
setattr(self, 'EXTRA_NEWZNABS', self.get_extra_newznabs())
setattr(self, 'EXTRA_TORZNABS', self.get_extra_torznabs())
if any([self.CONFIG_VERSION == 0, self.CONFIG_VERSION < self.newconfig]):
try:
shutil.move(self._config_file, os.path.join(mylar.DATA_DIR, 'config.ini.backup'))
except:
logger.warn('Unable to make proper backup of config file in %s' % os.path.join(mylar.DATA_DIR, 'config.ini.backup'))
print('Unable to make proper backup of config file in %s' % os.path.join(mylar.DATA_DIR, 'config.ini.backup'))
if self.newconfig == 8:
print('Attempting to update configuration..')
#torznab multiple entries merged into extra_torznabs value
self.config_update()
setattr(self, 'CONFIG_VERSION', str(self.newconfig))
config.set('General', 'CONFIG_VERSION', str(self.newconfig))
print('Updating config to newest version : %s' % self.newconfig)
@ -493,6 +501,25 @@ class Config(object):
self.configure()
return self
def config_update(self):
if self.newconfig == 8:
print('Updating Configuration from %s to %s' % (self.CONFIG_VERSION, self.newconfig))
print('Checking for existing torznab configuration...')
if not any([self.TORZNAB_NAME is None, self.TORZNAB_HOST is None, self.TORZNAB_APIKEY is None, self.TORZNAB_CATEGORY is None]):
torznabs =[(self.TORZNAB_NAME, self.TORZNAB_HOST, self.TORZNAB_APIKEY, self.TORZNAB_CATEGORY, str(int(self.ENABLE_TORZNAB)))]
setattr(self, 'EXTRA_TORZNABS', torznabs)
config.set('Torznab', 'EXTRA_TORZNABS', str(torznabs))
print('Successfully converted existing torznab for multiple configuration allowance. Removing old references.')
else:
print('No existing torznab configuration found. Just removing config references at this point..')
config.remove_option('Torznab', 'torznab_name')
config.remove_option('Torznab', 'torznab_host')
config.remove_option('Torznab', 'torznab_apikey')
config.remove_option('Torznab', 'torznab_category')
config.remove_option('Torznab', 'torznab_verify')
print('Successfully removed old entries.')
print('Configuration upgraded to version %s' % self.newconfig)
def check_section(self, section, key):
""" Check if INI section exists, if not create it """
if config.has_section(section):
@ -579,7 +606,7 @@ class Config(object):
Given a big bunch of key value pairs, apply them to the ini.
"""
for name, value in kwargs.items():
if not any([(name.startswith('newznab') and name[-1].isdigit()), name.startswith('Torznab')]):
if not any([(name.startswith('newznab') and name[-1].isdigit()), name.startswith('torznab') and name[-1].isdigit()]):
key, definition_type, section, ini_key, default = self._define(name)
if definition_type == str:
try:
@ -643,6 +670,8 @@ class Config(object):
logger.fdebug("Writing configuration to file")
self.provider_sequence()
config.set('Newznab', 'extra_newznabs', ', '.join(self.write_extras(self.EXTRA_NEWZNABS)))
config.set('Torznab', 'extra_torznabs', ', '.join(self.write_extras(self.EXTRA_TORZNABS)))
###this should be moved elsewhere...
if type(self.BLACKLISTED_PUBLISHERS) != list:
if self.BLACKLISTED_PUBLISHERS is None:
@ -853,6 +882,10 @@ class Config(object):
extra_newznabs = zip(*[iter(self.EXTRA_NEWZNABS.split(', '))]*6)
return extra_newznabs
def get_extra_torznabs(self):
extra_torznabs = zip(*[iter(self.EXTRA_TORZNABS.split(', '))]*5)
return extra_torznabs
def provider_sequence(self):
PR = []
PR_NUM = 0
@ -872,11 +905,8 @@ class Config(object):
if self.EXPERIMENTAL:
PR.append('Experimental')
PR_NUM +=1
if self.ENABLE_TORZNAB:
PR.append('Torznab')
PR_NUM +=1
PPR = ['32p', 'public torrents', 'nzb.su', 'dognzb', 'Experimental', 'Torznab']
PPR = ['32p', 'public torrents', 'nzb.su', 'dognzb', 'Experimental']
if self.NEWZNAB:
for ens in self.EXTRA_NEWZNABS:
if str(ens[5]) == '1': # if newznabs are enabled
@ -890,6 +920,19 @@ class Config(object):
PPR.append(en_name)
PR_NUM +=1
if self.ENABLE_TORZNAB:
for ets in self.EXTRA_TORZNABS:
if str(ets[4]) == '1': # if torznabs are enabled
if ets[0] == "":
et_name = ets[1]
else:
et_name = ets[0]
if et_name.endswith("\""):
et_name = re.sub("\"", "", str(et_name)).strip()
PR.append(et_name)
PPR.append(et_name)
PR_NUM +=1
if self.PROVIDER_ORDER is not None:
try:
PRO_ORDER = zip(*[iter(self.PROVIDER_ORDER.split(', '))]*2)
@ -901,7 +944,7 @@ class Config(object):
POR = ', '.join(PO)
PRO_ORDER = zip(*[iter(POR.split(', '))]*2)
logger.fdebug('Original provider_order sequence: %s' % self.PROVIDER_ORDER)
logger.fdebug(u"Original provider_order sequence: %s" % self.PROVIDER_ORDER)
#if provider order exists already, load it and then append to end any NEW entries.
logger.fdebug('Provider sequence already pre-exists. Re-loading and adding/remove any new entries')
@ -990,7 +1033,7 @@ class Config(object):
def write_extras(self, value):
flattened = []
for item in value: #self.EXTRA_NEWZNABS:
for item in value:
for i in item:
try:
if "\"" in i and " \"" in i:

View File

@ -2959,6 +2959,31 @@ def latestdate_update():
logger.info('updating latest date for : ' + a['ComicID'] + ' to ' + a['LatestDate'] + ' #' + a['LatestIssue'])
myDB.upsert("comics", newVal, ctrlVal)
def postprocess_main(queue):
while True:
if mylar.APILOCK is True:
time.sleep(5)
elif mylar.APILOCK is False and queue.qsize() >= 1: #len(queue) > 1:
item = queue.get(True)
logger.info('Now loading from post-processing queue: %s' % item)
if item == 'exit':
logger.info('Cleaning up workers for shutdown')
break
if mylar.APILOCK is False:
pprocess = process.Process(item['nzb_name'], item['nzb_folder'], item['failed'], item['issueid'], item['comicid'], item['apicall'])
pp = pprocess.post_process()
time.sleep(5) #arbitrary sleep to let the process attempt to finish pp'ing
if mylar.APILOCK is True:
logger.info('Another item is post-processing still...')
time.sleep(15)
#mylar.PP_QUEUE.put(item)
else:
time.sleep(5)
def worker_main(queue):
while True:
item = queue.get(True)

189
mylar/logger.py Executable file → Normal file
View File

@ -25,15 +25,161 @@ from logging import getLogger, WARN, ERROR, INFO, DEBUG, StreamHandler, Formatte
from mylar import helpers
# These settings are for file logging only
FILENAME = 'mylar.log'
MAX_LOGSIZE = 1000000
MAX_FILES = 5
try:
if mylar.LOG_LANG == 'en':
pass
except:
mylar.LOG_LANG = 'en'
# Mylar logger
logger = logging.getLogger('mylar')
class LogListHandler(logging.Handler):
if mylar.LOG_LANG != 'en':
# Simple rotating log handler that uses RotatingFileHandler
class RotatingLogger(object):
def __init__(self, filename):
self.filename = filename
self.filehandler = None
self.consolehandler = None
def stopLogger(self):
lg = logging.getLogger('mylar')
lg.removeHandler(self.filehandler)
lg.removeHandler(self.consolehandler)
def handle_exception(self, exc_type, exc_value, exc_traceback):
if issubclass(exc_type, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_value, exc_traceback)
return
logger.exception('Uncaught Exception', excinfo=(exc_type, exc_value, exc_traceback))
sys.__excepthook__(exc_type, exc_value, None)
return
def initLogger(self, loglevel=1):
import sys
sys.excepthook = RotatingLogger.handle_exception
logging.getLogger('apscheduler.scheduler').setLevel(logging.WARN)
logging.getLogger('apscheduler.threadpool').setLevel(logging.WARN)
logging.getLogger('apscheduler.scheduler').propagate = False
logging.getLogger('apscheduler.threadpool').propagate = False
lg = logging.getLogger('mylar')
lg.setLevel(logging.DEBUG)
self.filename = os.path.join(mylar.CONFIG.LOG_DIR, self.filename)
#concurrentLogHandler/0.8.7 (to deal with windows locks)
#since this only happens on windows boxes, if it's nix/mac use the default logger.
if mylar.OS_DETECT == 'Windows':
#set the path to the lib here - just to make sure it can detect cloghandler & portalocker.
import sys
sys.path.append(os.path.join(mylar.PROG_DIR, 'lib'))
try:
from ConcurrentLogHandler.cloghandler import ConcurrentRotatingFileHandler as RFHandler
mylar.LOGTYPE = 'clog'
except ImportError:
mylar.LOGTYPE = 'log'
from logging.handlers import RotatingFileHandler as RFHandler
else:
mylar.LOGTYPE = 'log'
from logging.handlers import RotatingFileHandler as RFHandler
filehandler = RFHandler(
self.filename,
maxBytes=mylar.CONFIG.MAX_LOGSIZE,
backupCount=mylar.CONFIG.MAX_LOGFILES)
filehandler.setLevel(logging.DEBUG)
fileformatter = logging.Formatter('%(asctime)s - %(levelname)-7s :: %(message)s', '%d-%b-%Y %H:%M:%S')
filehandler.setFormatter(fileformatter)
lg.addHandler(filehandler)
self.filehandler = filehandler
if loglevel:
consolehandler = logging.StreamHandler()
if loglevel == 1:
consolehandler.setLevel(logging.INFO)
if loglevel >= 2:
consolehandler.setLevel(logging.DEBUG)
consoleformatter = logging.Formatter('%(asctime)s - %(levelname)s :: %(message)s', '%d-%b-%Y %H:%M:%S')
consolehandler.setFormatter(consoleformatter)
lg.addHandler(consolehandler)
self.consolehandler = consolehandler
@staticmethod
def log(message, level):
logger = logging.getLogger('mylar')
threadname = threading.currentThread().getName()
# Get the frame data of the method that made the original logger call
if len(inspect.stack()) > 2:
frame = inspect.getframeinfo(inspect.stack()[2][0])
program = os.path.basename(frame.filename)
method = frame.function
lineno = frame.lineno
else:
program = ""
method = ""
lineno = ""
if PY2:
message = safe_unicode(message)
message = message.encode(mylar.SYS_ENCODING)
if level != 'DEBUG' or mylar.LOG_LEVEL >= 2:
mylar.LOGLIST.insert(0, (helpers.now(), message, threadname))
if len(mylar.LOGLIST) > 2500:
del mylar.LOGLIST[-1]
message = "%s : %s:%s:%s : %s" % (threadname, program, method, lineno, message)
if level == 'DEBUG':
logger.debug(message)
elif level == 'INFO':
logger.info(message)
elif level == 'WARNING':
logger.warning(message)
else:
logger.error(message)
mylar_log = RotatingLogger('mylar.log')
filename = 'mylar.log'
def debug(message):
if mylar.LOG_LEVEL > 1:
mylar_log.log(message, level='DEBUG')
def fdebug(message):
if mylar.LOG_LEVEL > 1:
mylar_log.log(message, level='DEBUG')
def info(message):
if mylar.LOG_LEVEL > 0:
mylar_log.log(message, level='INFO')
def warn(message):
mylar_log.log(message, level='WARNING')
def error(message):
mylar_log.log(message, level='ERROR')
def safe_unicode(obj, *args):
""" return the unicode representation of obj """
if not PY2:
return str(obj, *args)
try:
return unicode(obj, *args)
except UnicodeDecodeError:
ascii_text = str(obj).encode('string_escape')
return unicode(ascii_text)
else:
# Mylar logger
logger = logging.getLogger('mylar')
class LogListHandler(logging.Handler):
"""
Log handler for Web UI.
"""
@ -41,9 +187,10 @@ class LogListHandler(logging.Handler):
def emit(self, record):
message = self.format(record)
message = message.replace("\n", "<br />")
mylar.LOG_LIST.insert(0, (helpers.now(), message, record.levelname, record.threadName))
mylar.LOGLIST.insert(0, (helpers.now(), message, record.levelname, record.threadName))
def initLogger(console=False, log_dir=False, init=False, verbose=False):
def initLogger(console=False, log_dir=False, init=False, verbose=False):
#concurrentLogHandler/0.8.7 (to deal with windows locks)
#since this only happens on windows boxes, if it's nix/mac use the default logger.
if platform.system() == 'Windows':
@ -116,9 +263,9 @@ def initLogger(console=False, log_dir=False, init=False, verbose=False):
# Setup file logger
if log_dir:
filename = os.path.join(log_dir, FILENAME)
filename = os.path.join(log_dir, 'mylar.log')
file_formatter = Formatter('%(asctime)s - %(levelname)-7s :: %(name)s.%(funcName)s.%(lineno)s : %(threadName)s : %(message)s', '%d-%b-%Y %H:%M:%S')
file_handler = RFHandler(filename, "a", maxBytes=max_size, backupCount=MAX_FILES)
file_handler = RFHandler(filename, "a", maxBytes=max_size, backupCount=mylar.CONFIG.MAX_LOGFILES)
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(file_formatter)
@ -136,7 +283,7 @@ def initLogger(console=False, log_dir=False, init=False, verbose=False):
# Install exception hooks
initHooks()
def initHooks(global_exceptions=True, thread_exceptions=True, pass_original=True):
def initHooks(global_exceptions=True, thread_exceptions=True, pass_original=True):
"""
This method installs exception catching mechanisms. Any exception caught
will pass through the exception hook, and will be logged to the logger as
@ -184,12 +331,12 @@ def initHooks(global_exceptions=True, thread_exceptions=True, pass_original=True
# Monkey patch the run() by monkey patching the __init__ method
threading.Thread.__init__ = new_init
# Expose logger methods
info = logger.info
warn = logger.warn
error = logger.error
debug = logger.debug
warning = logger.warning
message = logger.info
exception = logger.exception
fdebug = logger.debug
# Expose logger methods
info = logger.info
warn = logger.warn
error = logger.error
debug = logger.debug
warning = logger.warning
message = logger.info
exception = logger.exception
fdebug = logger.debug

View File

@ -205,17 +205,26 @@ class NMA:
# No extra care has been put into API friendliness at the moment (read: https://pushover.net/api#friendly)
class PUSHOVER:
def __init__(self, test_apikey=None, test_userkey=None):
def __init__(self, test_apikey=None, test_userkey=None, test_device=None):
if all([test_apikey is None, test_userkey is None, test_device is None]):
self.PUSHOVER_URL = 'https://api.pushover.net/1/messages.json'
else:
self.PUSHOVER_URL = 'https://api.pushover.net/1/users/validate.json'
self.enabled = mylar.CONFIG.PUSHOVER_ENABLED
if test_apikey is None:
if mylar.CONFIG.PUSHOVER_APIKEY is None or mylar.CONFIG.PUSHOVER_APIKEY == 'None':
self.apikey = 'a1KZ1L7d8JKdrtHcUR6eFoW2XGBmwG'
logger.warn('No Pushover Apikey is present. Fix it')
return False
else:
self.apikey = mylar.CONFIG.PUSHOVER_APIKEY
else:
self.apikey = test_apikey
if test_device is None:
self.device = mylar.CONFIG.PUSHOVER_DEVICE
else:
self.device = test_device
if test_userkey is None:
self.userkey = mylar.CONFIG.PUSHOVER_USERKEY
else:
@ -244,10 +253,21 @@ class PUSHOVER:
'title': event,
'priority': mylar.CONFIG.PUSHOVER_PRIORITY}
if all([self.device is not None, self.device != 'None']):
data.update({'device': self.device})
r = self._session.post(self.PUSHOVER_URL, data=data, verify=True)
if r.status_code == 200:
logger.info(module + ' PushOver notifications sent.')
try:
response = r.json()
if 'devices' in response:
logger.info('%s PushOver notifications sent. Available devices: %s' % (module, response))
else:
logger.info('%s PushOver notifications sent.' % module)
except Exception as e:
logger.warn('%s[ERROR] - %s' % (module, e))
return True
elif r.status_code >= 400 and r.status_code < 500:
logger.error(module + ' PushOver request failed: %s' % r.content)

View File

@ -37,7 +37,7 @@ class NZBGet(object):
self.nzb_url = '%s://%s:%s@%s:%s/xmlrpc' % (protocol, mylar.CONFIG.NZBGET_USERNAME, mylar.CONFIG.NZBGET_PASSWORD, nzbget_host, mylar.CONFIG.NZBGET_PORT)
self.server = xmlrpclib.ServerProxy(self.nzb_url)
def sender(self, filename):
def sender(self, filename, test=False):
if mylar.CONFIG.NZBGET_PRIORITY:
if any([mylar.CONFIG.NZBGET_PRIORITY == 'Default', mylar.CONFIG.NZBGET_PRIORITY == 'Normal']):
nzbgetpriority = 0

View File

@ -546,7 +546,7 @@ def torrentdbsearch(seriesname, issue, comicid=None, nzbprov=None, oneoff=False)
if any([comicid is None, comicid == 'None', oneoff is True]):
pass
else:
logger.fdebug('ComicID: ' + str(comicid))
#logger.fdebug('ComicID: ' + str(comicid))
snm = myDB.selectone("SELECT * FROM comics WHERE comicid=?", [comicid]).fetchone()
if snm is None:
logger.fdebug('Invalid ComicID of ' + str(comicid) + '. Aborting search.')
@ -575,7 +575,7 @@ def torrentdbsearch(seriesname, issue, comicid=None, nzbprov=None, oneoff=False)
tsearch += '%'
tsearch += '#%s' % issue[8:10]
tsearch += '%'
logger.fdebug('tsearch : ' + tsearch)
#logger.fdebug('tsearch : ' + tsearch)
AS_Alt = []
tresults = []
tsearch = '%' + tsearch
@ -585,7 +585,7 @@ def torrentdbsearch(seriesname, issue, comicid=None, nzbprov=None, oneoff=False)
if mylar.CONFIG.ENABLE_PUBLIC and nzbprov == 'Public Torrents':
tresults += myDB.select("SELECT * FROM rssdb WHERE Title like ? AND (Site='DEM' OR Site='WWT')", [tsearch])
logger.fdebug('seriesname_alt:' + str(seriesname_alt))
#logger.fdebug('seriesname_alt:' + str(seriesname_alt))
if seriesname_alt is None or seriesname_alt == 'None':
if not tresults:
logger.fdebug('no Alternate name given. Aborting search.')
@ -639,43 +639,22 @@ def torrentdbsearch(seriesname, issue, comicid=None, nzbprov=None, oneoff=False)
#torsplit = torTITLE.split(' ')
if mylar.CONFIG.PREFERRED_QUALITY == 1:
if 'cbr' in torTITLE:
logger.fdebug('Quality restriction enforced [ cbr only ]. Accepting result.')
else:
logger.fdebug('Quality restriction enforced [ cbr only ]. Rejecting result.')
if 'cbr' not in torTITLE:
#logger.fdebug('Quality restriction enforced [ cbr only ]. Rejecting result.')
continue
elif mylar.CONFIG.PREFERRED_QUALITY == 2:
if 'cbz' in torTITLE:
logger.fdebug('Quality restriction enforced [ cbz only ]. Accepting result.')
else:
logger.fdebug('Quality restriction enforced [ cbz only ]. Rejecting result.')
if 'cbz' not in torTITLE:
#logger.fdebug('Quality restriction enforced [ cbz only ]. Rejecting result.')
continue
logger.fdebug('tor-Title: ' + torTITLE)
#logger.fdebug('tor-Title: ' + torTITLE)
#logger.fdebug('there are ' + str(len(torsplit)) + ' sections in this title')
i=0
if nzbprov is not None:
if nzbprov != tor['Site'] and not any([mylar.CONFIG.ENABLE_PUBLIC, tor['Site'] != 'WWT', tor['Site'] != 'DEM']):
logger.fdebug('this is a result from ' + str(tor['Site']) + ', not the site I am looking for of ' + str(nzbprov))
#logger.fdebug('this is a result from ' + str(tor['Site']) + ', not the site I am looking for of ' + str(nzbprov))
continue
#0 holds the title/issue and format-type.
#--- this was for old cbt feeds, no longer used for 32p
# while (i < len(torsplit)):
# #we'll rebuild the string here so that it's formatted accordingly to be passed back to the parser.
# logger.fdebug('section(' + str(i) + '): ' + torsplit[i])
# #remove extensions
# titletemp = torsplit[i]
# titletemp = re.sub('cbr', '', titletemp)
# titletemp = re.sub('cbz', '', titletemp)
# titletemp = re.sub('none', '', titletemp)
# if i == 0:
# rebuiltline = titletemp
# else:
# rebuiltline = rebuiltline + ' (' + titletemp + ')'
# i+=1
# logger.fdebug('rebuiltline is :' + rebuiltline)
#----
seriesname_mod = seriesname
foundname_mod = torTITLE #torsplit[0]
seriesname_mod = re.sub("\\band\\b", " ", seriesname_mod.lower())
@ -696,40 +675,23 @@ def torrentdbsearch(seriesname, issue, comicid=None, nzbprov=None, oneoff=False)
formatrem_torsplit = re.sub('[\-]', ' ', formatrem_torsplit) #we replace the - with space so we'll get hits if differnces
formatrem_torsplit = re.sub('[\/]', ' ', formatrem_torsplit) #not necessary since if has a /, should be removed in above line
formatrem_torsplit = re.sub('\s+', ' ', formatrem_torsplit)
logger.fdebug(str(len(formatrem_torsplit)) + ' - formatrem_torsplit : ' + formatrem_torsplit.lower())
logger.fdebug(str(len(formatrem_seriesname)) + ' - formatrem_seriesname :' + formatrem_seriesname.lower())
#logger.fdebug(str(len(formatrem_torsplit)) + ' - formatrem_torsplit : ' + formatrem_torsplit.lower())
#logger.fdebug(str(len(formatrem_seriesname)) + ' - formatrem_seriesname :' + formatrem_seriesname.lower())
if formatrem_seriesname.lower() in formatrem_torsplit.lower() or any(x.lower() in formatrem_torsplit.lower() for x in AS_Alt):
logger.fdebug('matched to : ' + torTITLE)
logger.fdebug('matched on series title: ' + seriesname)
#logger.fdebug('matched to : ' + torTITLE)
#logger.fdebug('matched on series title: ' + seriesname)
titleend = formatrem_torsplit[len(formatrem_seriesname):]
titleend = re.sub('\-', '', titleend) #remove the '-' which is unnecessary
#remove extensions
titleend = re.sub('cbr', '', titleend)
titleend = re.sub('cbz', '', titleend)
titleend = re.sub('none', '', titleend)
logger.fdebug('titleend: ' + titleend)
#logger.fdebug('titleend: ' + titleend)
sptitle = titleend.split()
extra = ''
#the title on 32P has a mix-mash of crap...ignore everything after cbz/cbr to cleanit
#ctitle = torTITLE.find('cbr')
#if ctitle == 0:
# ctitle = torTITLE.find('cbz')
# if ctitle == 0:
# ctitle = torTITLE.find('none')
# if ctitle == 0:
# logger.fdebug('cannot determine title properly - ignoring for now.')
# continue
#cttitle = torTITLE[:ctitle]
# if tor['Site'] == '32P':
# st_pub = rebuiltline.find('(')
# if st_pub < 2 and st_pub != -1:
# st_end = rebuiltline.find(')')
# rebuiltline = rebuiltline[st_end +1:]
tortheinfo.append({
'title': torTITLE, #cttitle,
'link': tor['Link'],

View File

@ -94,6 +94,9 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
torprovider = []
torp = 0
torznabs = 0
torznab_hosts = []
logger.fdebug("Checking for torrent enabled.")
checked_once = False
if mylar.CONFIG.ENABLE_TORRENT_SEARCH: #and mylar.CONFIG.ENABLE_TORRENTS:
@ -103,9 +106,13 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
if mylar.CONFIG.ENABLE_PUBLIC:
torprovider.append('public torrents')
torp+=1
if mylar.CONFIG.ENABLE_TORZNAB:
torprovider.append('torznab')
torp+=1
if mylar.CONFIG.ENABLE_TORZNAB is True:
for torznab_host in mylar.CONFIG.EXTRA_TORZNABS:
if torznab_host[4] == '1' or torznab_host[4] == 1:
torznab_hosts.append(torznab_host)
torprovider.append('torznab:' + str(torznab_host[0]))
torznabs+=1
##nzb provider selection##
##'dognzb' or 'nzb.su' or 'experimental'
nzbprovider = []
@ -136,20 +143,19 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
logger.fdebug('nzbprovider(s): ' + str(nzbprovider))
# --------
logger.fdebug("there are : " + str(torp) + " torrent providers you have selected.")
torpr = torp - 1
torproviders = torp + torznabs
logger.fdebug('There are %s torrent providers you have selected.' % torproviders)
torpr = torproviders - 1
if torpr < 0:
torpr = -1
providercount = int(nzbp + newznabs)
logger.fdebug("there are : " + str(providercount) + " nzb providers you have selected.")
if providercount > 0:
logger.fdebug("Usenet Retention : " + str(mylar.CONFIG.USENET_RETENTION) + " days")
#nzbpr = providercount - 1
#if nzbpr < 0:
# nzbpr == 0
findit = {}
findit['status'] = False
totalproviders = providercount + torp
totalproviders = providercount + torproviders
if totalproviders == 0:
logger.error('[WARNING] You have ' + str(totalproviders) + ' search providers enabled. I need at least ONE provider to work. Aborting search.')
@ -157,7 +163,7 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
nzbprov = None
return findit, nzbprov
prov_order, newznab_info = provider_sequence(nzbprovider, torprovider, newznab_hosts)
prov_order, torznab_info, newznab_info = provider_sequence(nzbprovider, torprovider, newznab_hosts, torznab_hosts)
# end provider order sequencing
logger.info('search provider order is ' + str(prov_order))
@ -271,12 +277,18 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
while (tmp_prov_count > prov_count):
send_prov_count = tmp_prov_count - prov_count
newznab_host = None
torznab_host = None
if prov_order[prov_count] == '32p':
searchprov = '32P'
elif prov_order[prov_count] == 'public torrents':
searchprov = 'Public Torrents'
elif prov_order[prov_count] == 'torznab':
searchprov = 'Torznab'
elif 'torznab' in prov_order[prov_count]:
searchprov = 'torznab'
for nninfo in torznab_info:
if nninfo['provider'] == prov_order[prov_count]:
torznab_host = nninfo['info']
if torznab_host is None:
logger.fdebug('there was an error - torznab information was blank and it should not be.')
elif 'newznab' in prov_order[prov_count]:
#this is for newznab
searchprov = 'newznab'
@ -287,6 +299,7 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
logger.fdebug('there was an error - newznab information was blank and it should not be.')
else:
newznab_host = None
torznab_host = None
searchprov = prov_order[prov_count].lower()
if searchprov == 'dognzb' and mylar.CONFIG.DOGNZB == 0:
@ -298,7 +311,7 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
prov_count+=1
continue
if searchmode == 'rss':
findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="yes", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=unaltered_ComicName, oneoff=oneoff, cmloopit=cmloopit, manual=manual)
findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="yes", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=unaltered_ComicName, oneoff=oneoff, cmloopit=cmloopit, manual=manual, torznab_host=torznab_host)
if findit['status'] is False:
if AlternateSearch is not None and AlternateSearch != "None":
chkthealt = AlternateSearch.split('##')
@ -308,7 +321,7 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
for calt in chkthealt:
AS_Alternate = re.sub('##', '', calt)
logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AS_Alternate))
findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="yes", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=AS_Alternate, allow_packs=allow_packs, oneoff=oneoff, cmloopit=cmloopit, manual=manual)
findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="yes", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=AS_Alternate, allow_packs=allow_packs, oneoff=oneoff, cmloopit=cmloopit, manual=manual, torznab_host=torznab_host)
if findit['status'] is True:
break
if findit['status'] is True:
@ -318,7 +331,7 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
break
else:
findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="no", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=unaltered_ComicName, allow_packs=allow_packs, oneoff=oneoff, cmloopit=cmloopit, manual=manual)
findit = NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="no", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=unaltered_ComicName, allow_packs=allow_packs, oneoff=oneoff, cmloopit=cmloopit, manual=manual, torznab_host=torznab_host)
if all([searchprov == '32P', checked_once is False]) or all([searchprov == 'Public Torrents', checked_once is False]):
checked_once = True
if findit['status'] is False:
@ -330,7 +343,7 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
for calt in chkthealt:
AS_Alternate = re.sub('##', '', calt)
logger.info(u"Alternate Search pattern detected...re-adjusting to : " + str(AS_Alternate))
findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="no", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=unaltered_ComicName, allow_packs=allow_packs, oneoff=oneoff, cmloopit=cmloopit, manual=manual)
findit = NZB_SEARCH(AS_Alternate, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, searchprov, send_prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host, ComicVersion=ComicVersion, SARC=SARC, IssueArcID=IssueArcID, RSS="no", ComicID=ComicID, issuetitle=issuetitle, unaltered_ComicName=unaltered_ComicName, allow_packs=allow_packs, oneoff=oneoff, cmloopit=cmloopit, manual=manual, torznab_host=torznab_host)
if findit['status'] is True:
break
if findit['status'] is True:
@ -341,6 +354,8 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
if searchprov == 'newznab':
searchprov = newznab_host[0].rstrip()
elif searchprov == 'torznab':
searchprov = torznab_host[0].rstrip()
if manual is not True:
if IssueNumber is not None:
issuedisplay = IssueNumber
@ -388,7 +403,7 @@ def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueD
return findit, 'None'
def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, nzbprov, prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host=None, ComicVersion=None, SARC=None, IssueArcID=None, RSS=None, ComicID=None, issuetitle=None, unaltered_ComicName=None, allow_packs=None, oneoff=False, cmloopit=None, manual=False):
def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, nzbprov, prov_count, IssDateFix, IssueID, UseFuzzy, newznab_host=None, ComicVersion=None, SARC=None, IssueArcID=None, RSS=None, ComicID=None, issuetitle=None, unaltered_ComicName=None, allow_packs=None, oneoff=False, cmloopit=None, manual=False, torznab_host=None):
if any([allow_packs is None, allow_packs == 'None', allow_packs == 0, allow_packs == '0']) and all([mylar.CONFIG.ENABLE_TORRENT_SEARCH, mylar.CONFIG.ENABLE_32P]):
allow_packs = False
@ -406,8 +421,15 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
elif nzbprov == 'experimental':
apikey = 'none'
verify = False
elif nzbprov == 'Torznab':
elif nzbprov == 'torznab':
name_torznab = torznab_host[0].rstrip()
host_torznab = torznab_host[1].rstrip()
apikey = torznab_host[2].rstrip()
verify = False
category_torznab = torznab_host[3]
if any([category_torznab is None, category_torznab == 'None']):
category_torznab = '8020'
logger.fdebug("using Torznab host of : " + str(name_torznab))
elif nzbprov == 'newznab':
#updated to include Newznab Name now
name_newznab = newznab_host[0].rstrip()
@ -431,11 +453,15 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
if RSS == "yes":
if 'newznab' in nzbprov:
tmpprov = name_newznab + '(' + nzbprov + ')' + ' [RSS]'
elif 'torznab' in nzbprov:
tmpprov = name_torznab + '(' + nzbprov + ')' + ' [RSS]'
else:
tmpprov = str(nzbprov) + " [RSS]"
else:
if 'newznab' in nzbprov:
tmpprov = name_newznab + ' (' + nzbprov + ')'
elif 'torznab' in nzbprov:
tmpprov = name_torznab + ' (' + nzbprov + ')'
else:
tmpprov = nzbprov
if IssueNumber is not None:
@ -558,6 +584,8 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
logger.fdebug("Sending request to RSS for " + str(findcomic) + " : " + str(mod_isssearch) + " (" + str(ComicYear) + ")")
if nzbprov == 'newznab':
nzbprov_fix = name_newznab
elif nzbprov == 'torznab':
nzbprov_fix = name_torznab
else: nzbprov_fix = nzbprov
bb = rsscheck.nzbdbsearch(findcomic, mod_isssearch, ComicID, nzbprov_fix, ComicYear, ComicVersion, oneoff)
if bb is None:
@ -601,15 +629,14 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
host_newznab_fix = str(host_newznab) + "/"
else: host_newznab_fix = host_newznab
findurl = str(host_newznab_fix) + "api?t=search&q=" + str(comsearch) + "&o=xml&cat=" + str(category_newznab)
elif nzbprov == 'Torznab':
if mylar.CONFIG.TORZNAB_HOST.endswith('/'):
#http://localhost:9117/api/iptorrents
torznab_fix = mylar.CONFIG.TORZNAB_HOST[:-1]
elif nzbprov == 'torznab':
if host_torznab[len(host_torznab)-1:len(host_torznab)] == '/':
torznab_fix = host_torznab[:-1]
else:
torznab_fix = mylar.CONFIG.TORZNAB_HOST
torznab_fix = host.torznab
findurl = str(torznab_fix) + "?t=search&q=" + str(comsearch)
if str(mylar.CONFIG.TORZNAB_CATEGORY): findurl += "&cat=" + str(mylar.CONFIG.TORZNAB_CATEGORY)
apikey = mylar.CONFIG.TORZNAB_APIKEY
if category_torznab is not None:
findurl += "&cat=" + str(category_torznab)
else:
logger.warn('You have a blank newznab entry within your configuration. Remove it, save the config and restart mylar to fix things. Skipping this blank provider until fixed.')
findurl = None
@ -1329,7 +1356,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
downloadit = True
else:
for x in mylar.COMICINFO:
if all([x['link'] == entry['link'], x['tmpprov'] == tmpprov]) or all([x['nzbid'] == nzbid, x['newznab'] == newznab_host]):
if all([x['link'] == entry['link'], x['tmpprov'] == tmpprov]) or all([x['nzbid'] == nzbid, x['newznab'] == newznab_host]) or all([x['nzbid'] == nzbid, x['torznab'] == torznab_host]):
nowrite = True
break
@ -1340,8 +1367,10 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
if newznab_host is not None:
tprov = newznab_host[0]
else:
kind = 'torrent'
tprov = nzbprov
kind = 'torrent'
if torznab_host is not None:
tprov = torznab_host[0]
mylar.COMICINFO.append({"ComicName": ComicName,
"ComicID": ComicID,
"IssueID": IssueID,
@ -1364,7 +1393,8 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
"kind": kind,
"SARC": SARC,
"IssueArcID": IssueArcID,
"newznab": newznab_host})
"newznab": newznab_host,
"torznab": torznab_host})
else:
@ -1662,7 +1692,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
#issue comparison now as well
if int(intIss) == int(comintIss):
nowrite = False
if nzbprov == 'Torznab' and 'worldwidetorrents' in entry['link']:
if nzbprov == 'torznab' and 'worldwidetorrents' in entry['link']:
nzbid = generate_id(nzbprov, entry['id'])
else:
nzbid = generate_id(nzbprov, entry['link'])
@ -1670,7 +1700,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
downloadit = True
else:
for x in mylar.COMICINFO:
if all([x['link'] == entry['link'], x['tmpprov'] == tmpprov]) or all([x['nzbid'] == nzbid, x['newznab'] == newznab_host]):
if all([x['link'] == entry['link'], x['tmpprov'] == tmpprov]) or all([x['nzbid'] == nzbid, x['newznab'] == newznab_host]) or all([x['nzbid'] == nzbid, x['torznab'] == torznab_host]):
nowrite = True
break
@ -1696,6 +1726,8 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
else:
kind = 'torrent'
tprov = nzbprov
if torznab_host is not None:
tprov = torznab_host[0]
mylar.COMICINFO.append({"ComicName": ComicName,
"ComicID": ComicID,
@ -1719,7 +1751,8 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
"kind": kind,
"SARC": SARC,
"IssueArcID": IssueArcID,
"newznab": newznab_host})
"newznab": newznab_host,
"torznab": torznab_host})
else:
log2file = log2file + "issues don't match.." + "\n"
downloadit = False
@ -1744,7 +1777,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
'link': entry['link']}
except:
links = entry['link']
searchresult = searcher(nzbprov, nzbname, mylar.COMICINFO, links, IssueID, ComicID, tmpprov, newznab=newznab_host)
searchresult = searcher(nzbprov, nzbname, mylar.COMICINFO, links, IssueID, ComicID, tmpprov, newznab=newznab_host, torznab=torznab_host)
if searchresult == 'downloadchk-fail':
foundc['status'] = False
@ -1833,7 +1866,8 @@ def searchforissue(issueid=None, new=False, rsscheck=None, manual=False):
myDB = db.DBConnection()
ens = [x for x in mylar.CONFIG.EXTRA_NEWZNABS if x[5] == '1']
if (any([mylar.CONFIG.NZBSU is True, mylar.CONFIG.DOGNZB is True, mylar.CONFIG.EXPERIMENTAL is True]) or all([mylar.CONFIG.NEWZNAB is True, len(ens) > 0]) and any([mylar.USE_SABNZBD is True, mylar.USE_NZBGET is True, mylar.USE_BLACKHOLE is True])) or (all([mylar.CONFIG.ENABLE_TORRENT_SEARCH is True, mylar.CONFIG.ENABLE_TORRENTS is True]) and any([mylar.CONFIG.ENABLE_PUBLIC is True, mylar.CONFIG.ENABLE_32P is True, mylar.CONFIG.ENABLE_TORZNAB is True])):
ets = [x for x in mylar.CONFIG.EXTRA_TORZNABS if x[4] == '1']
if (any([mylar.CONFIG.NZBSU is True, mylar.CONFIG.DOGNZB is True, mylar.CONFIG.EXPERIMENTAL is True]) or all([mylar.CONFIG.NEWZNAB is True, len(ens) > 0]) and any([mylar.USE_SABNZBD is True, mylar.USE_NZBGET is True, mylar.USE_BLACKHOLE is True])) or (all([mylar.CONFIG.ENABLE_TORRENT_SEARCH is True, mylar.CONFIG.ENABLE_TORRENTS is True]) and (any([mylar.CONFIG.ENABLE_PUBLIC is True, mylar.CONFIG.ENABLE_32P is True]) or all([mylar.CONFIG.ENABLE_TORZNAB is True, len(ets) > 0]))):
if not issueid or rsscheck:
if rsscheck:
@ -2053,8 +2087,8 @@ def searchforissue(issueid=None, new=False, rsscheck=None, manual=False):
def searchIssueIDList(issuelist):
myDB = db.DBConnection()
ens = [x for x in mylar.CONFIG.EXTRA_NEWZNABS if x[5] == '1']
logger.info('issuelist: %s' % issuelist)
if (any([mylar.CONFIG.NZBSU is True, mylar.CONFIG.DOGNZB is True, mylar.CONFIG.EXPERIMENTAL is True]) or all([mylar.CONFIG.NEWZNAB is True, len(ens) > 0]) and any([mylar.USE_SABNZBD is True, mylar.USE_NZBGET is True, mylar.USE_BLACKHOLE is True])) or (all([mylar.CONFIG.ENABLE_TORRENT_SEARCH is True, mylar.CONFIG.ENABLE_TORRENTS is True]) and any([mylar.CONFIG.ENABLE_PUBLIC is True, mylar.CONFIG.ENABLE_32P is True, mylar.CONFIG.ENABLE_TORZNAB is True])):
ets = [x for x in mylar.CONFIG.EXTRA_TORZNABS if x[4] == '1']
if (any([mylar.CONFIG.NZBSU is True, mylar.CONFIG.DOGNZB is True, mylar.CONFIG.EXPERIMENTAL is True]) or all([mylar.CONFIG.NEWZNAB is True, len(ens) > 0]) and any([mylar.USE_SABNZBD is True, mylar.USE_NZBGET is True, mylar.USE_BLACKHOLE is True])) or (all([mylar.CONFIG.ENABLE_TORRENT_SEARCH is True, mylar.CONFIG.ENABLE_TORRENTS is True]) and (any([mylar.CONFIG.ENABLE_PUBLIC is True, mylar.CONFIG.ENABLE_32P is True]) or all([mylar.CONFIG.NEWZNAB is True, len(ets) > 0]))):
for issueid in issuelist:
logger.info('searching for issueid: %s' % issueid)
issue = myDB.selectone('SELECT * from issues WHERE IssueID=?', [issueid]).fetchone()
@ -2089,20 +2123,23 @@ def searchIssueIDList(issuelist):
foundNZB, prov = search_init(comic['ComicName'], issue['Issue_Number'], str(IssueYear), comic['ComicYear'], Publisher, issue['IssueDate'], issue['ReleaseDate'], issue['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, ComicID=issue['ComicID'], filesafe=comic['ComicName_Filesafe'], allow_packs=AllowPacks)
if foundNZB['status'] is True:
updater.foundsearch(ComicID=issue['ComicID'], IssueID=issue['IssueID'], mode=mode, provider=prov, hash=foundNZB['info']['t_hash'])
logger.info('Completed search request.')
else:
logger.warn('There are no search providers enabled atm - not performing the requested search for obvious reasons')
def provider_sequence(nzbprovider, torprovider, newznab_hosts):
def provider_sequence(nzbprovider, torprovider, newznab_hosts, torznab_hosts):
#provider order sequencing here.
newznab_info = []
torznab_info = []
prov_order = []
nzbproviders_lower = [x.lower() for x in nzbprovider]
torproviders_lower = [y.lower() for y in torprovider]
if len(mylar.CONFIG.PROVIDER_ORDER) > 0:
for pr_order in sorted(mylar.CONFIG.PROVIDER_ORDER.items(), key=itemgetter(0), reverse=False):
if (pr_order[1].lower() in torprovider) or any(pr_order[1].lower() in x for x in nzbproviders_lower):
if any(pr_order[1].lower() in y for y in torproviders_lower) or any(pr_order[1].lower() in x for x in nzbproviders_lower):
if any(pr_order[1].lower() in x for x in nzbproviders_lower):
# this is for nzb providers
for np in nzbprovider:
@ -2123,13 +2160,27 @@ def provider_sequence(nzbprovider, torprovider, newznab_hosts):
elif pr_order[1].lower() in np.lower():
prov_order.append(pr_order[1])
break
else:
elif any(pr_order[1].lower() in y for y in torproviders_lower):
for tp in torprovider:
if (pr_order[1].lower() in tp.lower()):
prov_order.append(tp) #torrent provider
if all(['torznab' in tp, pr_order[1].lower() in tp.lower()]):
for torznab_host in torznab_hosts:
if torznab_host[0].lower() == pr_order[1].lower():
prov_order.append(tp)
torznab_info.append({"provider": tp,
"info": torznab_host})
break
else:
if torznab_host[0] == "":
if torznab_host[1].lower() == pr_order[1].lower():
prov_order.append(tp)
torznab_info.append({"provider": tp,
"info": torznab_host})
break
elif (pr_order[1].lower() in tp.lower()):
prov_order.append(pr_order[1])
break
return prov_order, newznab_info
return prov_order, torznab_info, newznab_info
def nzbname_create(provider, title=None, info=None):
#the nzbname here is used when post-processing
@ -2198,7 +2249,7 @@ def nzbname_create(provider, title=None, info=None):
logger.fdebug("nzbname used for post-processing:" + nzbname)
return nzbname
def searcher(nzbprov, nzbname, comicinfo, link, IssueID, ComicID, tmpprov, directsend=None, newznab=None):
def searcher(nzbprov, nzbname, comicinfo, link, IssueID, ComicID, tmpprov, directsend=None, newznab=None, torznab=None):
alt_nzbname = None
#load in the details of the issue from the tuple.
ComicName = comicinfo[0]['ComicName']
@ -2237,7 +2288,7 @@ def searcher(nzbprov, nzbname, comicinfo, link, IssueID, ComicID, tmpprov, direc
#if sab priority isn't selected, default to Normal (0)
nzbgetpriority = "0"
if nzbprov == 'Torznab':
if nzbprov == 'torznab':
nzbid = generate_id(nzbprov, link['id'])
link = link['link']
else:
@ -2292,7 +2343,7 @@ def searcher(nzbprov, nzbname, comicinfo, link, IssueID, ComicID, tmpprov, direc
else:
logger.fdebug('[FAILED_DOWNLOAD_CHECKER] Failed download checking is not available for one-off downloads atm. Fixed soon!')
if link and all([nzbprov != 'WWT', nzbprov != 'DEM', nzbprov != '32P', nzbprov != 'Torznab']):
if link and all([nzbprov != 'WWT', nzbprov != 'DEM', nzbprov != '32P', nzbprov != 'torznab']):
#generate nzbid here.
@ -2466,7 +2517,7 @@ def searcher(nzbprov, nzbname, comicinfo, link, IssueID, ComicID, tmpprov, direc
#blackhole
sent_to = None
t_hash = None
if mylar.USE_BLACKHOLE and all([nzbprov != '32P', nzbprov != 'WWT', nzbprov != 'DEM', nzbprov != 'Torznab']):
if mylar.USE_BLACKHOLE and all([nzbprov != '32P', nzbprov != 'WWT', nzbprov != 'DEM', nzbprov != 'torznab']):
logger.fdebug("using blackhole directory at : " + str(mylar.CONFIG.BLACKHOLE_DIR))
if os.path.exists(mylar.CONFIG.BLACKHOLE_DIR):
#copy the nzb from nzbpath to blackhole dir.
@ -2512,7 +2563,7 @@ def searcher(nzbprov, nzbname, comicinfo, link, IssueID, ComicID, tmpprov, direc
#end blackhole
#torrents (32P & DEM)
elif any([nzbprov == '32P', nzbprov == 'WWT', nzbprov == 'DEM', nzbprov == 'Torznab']):
elif any([nzbprov == '32P', nzbprov == 'WWT', nzbprov == 'DEM', nzbprov == 'torznab']):
logger.fdebug("ComicName:" + ComicName)
logger.fdebug("link:" + link)
logger.fdebug("Torrent Provider:" + nzbprov)
@ -3054,7 +3105,7 @@ def generate_id(nzbprov, link):
if '&id' not in tmpid or nzbid == '':
tmpid = urlparse.urlparse(link)[2]
nzbid = tmpid.rsplit('/', 1)[1]
elif nzbprov == 'Torznab':
elif nzbprov == 'torznab':
idtmp = urlparse.urlparse(link)[4]
idpos = idtmp.find('&')
nzbid = re.sub('id=', '', idtmp[:idpos]).strip()

View File

@ -44,7 +44,7 @@ class RTorrent(object):
mylar.CONFIG.RTORRENT_SSL,
mylar.CONFIG.RTORRENT_RPC_URL,
mylar.CONFIG.RTORRENT_CA_BUNDLE):
logger.error('could not connect to %s, exiting', mylar.CONFIG.RTORRENT_HOST)
logger.error('[ERROR] Could not connect to %s - exiting' % mylar.CONFIG.RTORRENT_HOST)
sys.exit(-1)
def main(self, torrent_hash=None, filepath=None, check=False):
@ -52,13 +52,13 @@ class RTorrent(object):
torrent = self.client.find_torrent(torrent_hash)
if torrent:
if check:
logger.fdebug('Successfully located torrent %s by hash on client. Detailed statistics to follow', torrent_hash)
logger.fdebug('Successfully located torrent %s by hash on client. Detailed statistics to follow' % torrent_hash)
else:
logger.warn("%s Torrent already exists. Not downloading at this time.", torrent_hash)
logger.warn("%s Torrent already exists. Not downloading at this time." % torrent_hash)
return
else:
if check:
logger.warn('Unable to locate torrent with a hash value of %s', torrent_hash)
logger.warn('Unable to locate torrent with a hash value of %s' % torrent_hash)
return
if filepath:
@ -76,7 +76,7 @@ class RTorrent(object):
torrent = self.client.find_torrent(torrent_hash)
if torrent is None:
logger.warn("Couldn't find torrent with hash: %s", torrent_hash)
logger.warn('Couldn\'t find torrent with hash: %s' % torrent_hash)
sys.exit(-1)
torrent_info = self.client.get_torrent(torrent)
@ -84,18 +84,18 @@ class RTorrent(object):
return torrent_info
if torrent_info['completed']:
logger.fdebug("Directory: %s", torrent_info['folder'])
logger.fdebug("Name: %s", torrent_info['name'])
logger.fdebug("FileSize: %s", helpers.human_size(torrent_info['total_filesize']))
logger.fdebug("Completed: %s", torrent_info['completed'])
logger.fdebug("Downloaded: %s", helpers.human_size(torrent_info['download_total']))
logger.fdebug("Uploaded: %s", helpers.human_size(torrent_info['upload_total']))
logger.fdebug("Ratio: %s", torrent_info['ratio'])
#logger.info("Time Started: %s", torrent_info['time_started'])
logger.fdebug("Seeding Time: %s", helpers.humanize_time(int(time.time()) - torrent_info['time_started']))
logger.fdebug('Directory: %s' % torrent_info['folder'])
logger.fdebug('Name: %s' % torrent_info['name'])
logger.fdebug('FileSize: %s' % helpers.human_size(torrent_info['total_filesize']))
logger.fdebug('Completed: %s' % torrent_info['completed'])
logger.fdebug('Downloaded: %s' % helpers.human_size(torrent_info['download_total']))
logger.fdebug('Uploaded: %s' % helpers.human_size(torrent_info['upload_total']))
logger.fdebug('Ratio: %s' % torrent_info['ratio'])
#logger.info('Time Started: %s' % torrent_info['time_started'])
logger.fdebug('Seeding Time: %s' % helpers.humanize_time(int(time.time()) - torrent_info['time_started']))
if torrent_info['label']:
logger.fdebug("Torrent Label: %s", torrent_info['label'])
logger.fdebug('Torrent Label: %s' % torrent_info['label'])
#logger.info(torrent_info)
return torrent_info
@ -106,5 +106,5 @@ class RTorrent(object):
metainfo = bencode.decode(torrent_file.read())
info = metainfo['info']
thehash = hashlib.sha1(bencode.encode(info)).hexdigest().upper()
logger.fdebug('Hash: ' + thehash)
logger.fdebug('Hash: %s' % thehash)
return thehash

View File

@ -2732,8 +2732,10 @@ class WebInterface(object):
valid_readingorder = None
#validate input here for reading order.
try:
if int(readingorder) > 0:
if int(readingorder) >= 0:
valid_readingorder = int(readingorder)
if valid_readingorder == 0:
valid_readingorder = 1
except ValueError:
logger.error('Non-Numeric/Negative readingorder submitted. Rejecting due to sequencing error.')
return
@ -2749,22 +2751,48 @@ class WebInterface(object):
return
new_readorder = []
for rc in readchk:
if issuearcid == rc['IssueArcID']:
oldreadorder = int(rc['ReadingOrder'])
new_readorder.append({'IssueArcID': issuearcid,
'IssueID': rc['IssueID'],
'ReadingOrder': valid_readingorder})
else:
if int(rc['ReadingOrder']) >= valid_readingorder:
reading_seq = int(rc['ReadingOrder']) + 1
else:
reading_seq = int(rc['ReadingOrder']) - 1
if reading_seq == 0:
oldreading_seq = None
logger.fdebug('[%s] Issue to renumber sequence from : %s' % (issuearcid, valid_readingorder))
reading_seq = 1
new_readorder.append({'IssueArcID': rc['IssueArcID'],
'IssueID': rc['IssueID'],
for rc in sorted(readchk, key=itemgetter('ReadingOrder'), reverse=False):
if str(issuearcid) == str(rc['IssueArcID']):
logger.fdebug('new order sequence detected at #: %s' % valid_readingorder)
if valid_readingorder > int(rc['ReadingOrder']):
oldreading_seq = int(rc['ReadingOrder'])
else:
oldreading_seq = int(rc['ReadingOrder']) + 1
reading_seq = valid_readingorder
issueid = rc['IssueID']
IssueArcID = issuearcid
elif int(rc['ReadingOrder']) < valid_readingorder:
logger.fdebug('keeping issue sequence of order #: %s' % rc['ReadingOrder'])
reading_seq = int(rc['ReadingOrder'])
issueid = rc['IssueID']
IssueArcID = rc['IssueArcID']
elif int(rc['ReadingOrder']) >= valid_readingorder:
if oldreading_seq is not None:
if valid_readingorder <= len(readchk):
reading_seq = int(rc['ReadingOrder'])
#reading_seq = oldreading_seq
else:
#valid_readingorder
if valid_readingorder < old_reading_seq:
logger.info('2')
reading_seq = int(rc['ReadingOrder'])
else:
logger.info('3')
reading_seq = oldreading_seq +1
logger.fdebug('old sequence discovered at %s to %s' % (oldreading_seq, reading_seq))
oldreading_seq = None
elif int(rc['ReadingOrder']) == valid_readingorder:
reading_seq = valid_readingorder +1
else:
reading_seq +=1 #valid_readingorder + (int(rc['ReadingOrder']) - valid_readingorder) +1
issueid = rc['IssueID']
IssueArcID = rc['IssueArcID']
logger.fdebug('reordering existing sequence as lower sequence has changed. Altering from %s to %s' % (rc['ReadingOrder'], reading_seq))
new_readorder.append({'IssueArcID': IssueArcID,
'IssueID': issueid,
'ReadingOrder': reading_seq})
#we resequence in the following way:
@ -2772,21 +2800,15 @@ class WebInterface(object):
# everything after the new reading order gets incremented
# add in the new reading order at the desired sequence
# check for empty spaces (missing numbers in sequence) and fill them in.
logger.fdebug(new_readorder)
newrl = 0
logger.fdebug('new reading order: %s' % new_readorder)
#newrl = 0
for rl in sorted(new_readorder, key=itemgetter('ReadingOrder'), reverse=False):
if rl['ReadingOrder'] - 1 != newrl:
rorder = newrl + 1
logger.fdebug(rl['IssueID'] + ' - changing reading order seq to : ' + str(rorder))
else:
rorder = rl['ReadingOrder']
logger.fdebug(rl['IssueID'] + ' - setting reading order seq to : ' + str(rorder))
rl_ctrl = {"IssueID": rl['IssueID'],
"IssueArcID": rl['IssueArcID'],
"StoryArcID": storyarcid}
r1_new = {"ReadingOrder": rorder}
newrl = rorder
r1_new = {"ReadingOrder": rl['ReadingOrder']}
myDB.upsert("storyarcs", r1_new, rl_ctrl)
@ -3516,7 +3538,7 @@ class WebInterface(object):
ReadMassCopy.exposed = True
def logs(self):
return serve_template(templatename="logs.html", title="Log", lineList=mylar.LOG_LIST)
return serve_template(templatename="logs.html", title="Log", lineList=mylar.LOGLIST)
logs.exposed = True
def config_dump(self):
@ -3524,7 +3546,7 @@ class WebInterface(object):
config_dump.exposed = True
def clearLogs(self):
mylar.LOG_LIST = []
mylar.LOGLIST = []
logger.info("Web logs cleared")
raise cherrypy.HTTPRedirect("logs")
clearLogs.exposed = True
@ -3544,9 +3566,9 @@ class WebInterface(object):
filtered = []
if sSearch == "" or sSearch == None:
filtered = mylar.LOG_LIST[::]
filtered = mylar.LOGLIST[::]
else:
filtered = [row for row in mylar.LOG_LIST for column in row if sSearch.lower() in column.lower()]
filtered = [row for row in mylar.LOGLIST for column in row if sSearch.lower() in column.lower()]
sortcolumn = 0
if iSortCol_0 == '1':
sortcolumn = 2
@ -3558,7 +3580,7 @@ class WebInterface(object):
rows = [[row[0], row[2], row[1]] for row in rows]
return json.dumps({
'iTotalDisplayRecords': len(filtered),
'iTotalRecords': len(mylar.LOG_LIST),
'iTotalRecords': len(mylar.LOGLIST),
'aaData': rows,
})
getLog.exposed = True
@ -4465,10 +4487,7 @@ class WebInterface(object):
"dognzb_verify": helpers.checked(mylar.CONFIG.DOGNZB_VERIFY),
"experimental": helpers.checked(mylar.CONFIG.EXPERIMENTAL),
"enable_torznab": helpers.checked(mylar.CONFIG.ENABLE_TORZNAB),
"torznab_name": mylar.CONFIG.TORZNAB_NAME,
"torznab_host": mylar.CONFIG.TORZNAB_HOST,
"torznab_apikey": mylar.CONFIG.TORZNAB_APIKEY,
"torznab_category": mylar.CONFIG.TORZNAB_CATEGORY,
"extra_torznabs": sorted(mylar.CONFIG.EXTRA_TORZNABS, key=itemgetter(4), reverse=True),
"newznab": helpers.checked(mylar.CONFIG.NEWZNAB),
"extra_newznabs": sorted(mylar.CONFIG.EXTRA_NEWZNABS, key=itemgetter(5), reverse=True),
"enable_rss": helpers.checked(mylar.CONFIG.ENABLE_RSS),
@ -4541,6 +4560,7 @@ class WebInterface(object):
"pushover_onsnatch": helpers.checked(mylar.CONFIG.PUSHOVER_ONSNATCH),
"pushover_apikey": mylar.CONFIG.PUSHOVER_APIKEY,
"pushover_userkey": mylar.CONFIG.PUSHOVER_USERKEY,
"pushover_device": mylar.CONFIG.PUSHOVER_DEVICE,
"pushover_priority": mylar.CONFIG.PUSHOVER_PRIORITY,
"boxcar_enabled": helpers.checked(mylar.CONFIG.BOXCAR_ENABLED),
"boxcar_onsnatch": helpers.checked(mylar.CONFIG.BOXCAR_ONSNATCH),
@ -4823,6 +4843,28 @@ class WebInterface(object):
mylar.CONFIG.EXTRA_NEWZNABS.append((newznab_name, newznab_host, newznab_verify, newznab_api, newznab_uid, newznab_enabled))
mylar.CONFIG.EXTRA_TORZNABS = []
for kwarg in [x for x in kwargs if x.startswith('torznab_name')]:
if kwarg.startswith('torznab_name'):
torznab_number = kwarg[12:]
torznab_name = kwargs['torznab_name' + torznab_number]
if torznab_name == "":
torznab_name = kwargs['torznab_host' + torznab_number]
if torznab_name == "":
continue
torznab_host = helpers.clean_url(kwargs['torznab_host' + torznab_number])
torznab_api = kwargs['torznab_apikey' + torznab_number]
torznab_category = kwargs['torznab_category' + torznab_number]
try:
torznab_enabled = str(kwargs['torznab_enabled' + torznab_number])
except KeyError:
torznab_enabled = '0'
del kwargs[kwarg]
mylar.CONFIG.EXTRA_TORZNABS.append((torznab_name, torznab_host, torznab_api, torznab_category, torznab_enabled))
mylar.CONFIG.process_kwargs(kwargs)
#this makes sure things are set to the default values if they're not appropriately set.
@ -4922,6 +4964,45 @@ class WebInterface(object):
return "Invalid SABnzbd host specified"
SABtest.exposed = True
def NZBGet_test(self, nzbhost=None, nzbport=None, nzbusername=None, nzbpassword=None):
if nzbhost is None:
nzbhost = mylar.CONFIG.NZBGET_HOST
if nzbport is None:
nzbport = mylar.CONFIG.NZBGET_PORT
if nzbusername is None:
nzbusername = mylar.CONFIG.NZBGET_USERNAME
if nzbpassword is None:
nzbpassword = mylar.CONFIG.NZBGET_PASSWORD
logger.fdebug('Now attempting to test NZBGet connection')
if nzbusername is None or nzbpassword is None:
logger.error('No Username / Password provided for NZBGet credentials. Unable to test API key')
return "Invalid Username/Password provided"
logger.info('Now testing connection to NZBGet @ %s:%s' % (nzbhost, nzbport))
if nzbhost[:5] == 'https':
protocol = 'https'
nzbgethost = nzbhost[8:]
elif nzbhost[:4] == 'http':
protocol = 'http'
nzbgethost = nzbhost[7:]
nzb_url = '%s://%s:%s@%s:%s/xmlrpc' % (protocol, nzbusername, nzbpassword, nzbgethost, nzbport)
logger.info('nzb_url: %s' % nzb_url)
import xmlrpclib
nzbserver = xmlrpclib.ServerProxy(nzb_url)
try:
r = nzbserver.status()
except Exception as e:
logger.warn('Error fetching data: %s' % e)
return 'Unable to retrieve data from NZBGet'
logger.info('Successfully verified connection to NZBGet at %s:%s' % (nzbgethost, nzbport))
return "Successfully verified connection to NZBGet"
NZBGet_test.exposed = True
def shutdown(self):
mylar.SIGNAL = 'shutdown'
message = 'Shutting Down...'
@ -5231,8 +5312,8 @@ class WebInterface(object):
return "Error sending test message to Boxcar"
testboxcar.exposed = True
def testpushover(self, apikey, userkey):
pushover = notifiers.PUSHOVER(test_apikey=apikey, test_userkey=userkey)
def testpushover(self, apikey, userkey, device):
pushover = notifiers.PUSHOVER(test_apikey=apikey, test_userkey=userkey, test_device=device)
result = pushover.test_notify()
if result == True:
return "Successfully sent PushOver test - check to make sure it worked"

View File

@ -69,8 +69,7 @@ def initialize(options):
else:
protocol = "http"
logger.info("Starting Mylar on %s://%s:%d%s", protocol,
options['http_host'], options['http_port'], options['http_root'])
logger.info("Starting Mylar on %s://%s:%d%s" % (protocol,options['http_host'], options['http_port'], options['http_root']))
cherrypy.config.update(options_dict)
conf = {