mirror of https://github.com/evilhero/mylar
Merge branch 'development'
This commit is contained in:
commit
04fc85c4b0
|
@ -0,0 +1,83 @@
|
|||
div.alphabet {
|
||||
clear:both;
|
||||
position:relative;
|
||||
margin:0.5em 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width:963px){
|
||||
div.alphabet {
|
||||
text-align:center;
|
||||
}
|
||||
}
|
||||
|
||||
div.alphabet ul {
|
||||
display:inline-block;
|
||||
margin:0;
|
||||
padding:0;
|
||||
list-style:none;
|
||||
}
|
||||
|
||||
div.alphabet li {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
div.alphabet a {
|
||||
display:inline-block;
|
||||
cursor:pointer;
|
||||
text-align:center;
|
||||
text-decoration:none;
|
||||
box-sizing:content-box;
|
||||
padding:0.2em 0.1em;
|
||||
min-width:1.3em;
|
||||
color:#333 !important;
|
||||
border:1px solid transparent;
|
||||
border-radius:2px;
|
||||
}
|
||||
|
||||
div.alphabet a:hover {
|
||||
color:#FFF !important;
|
||||
border:1px solid #111;
|
||||
background-color:#585858;
|
||||
background:linear-gradient(to bottom, #585858 0%, #111 100%);
|
||||
}
|
||||
|
||||
div.alphabet a:active {
|
||||
outline:none;
|
||||
background-color:#2b2b2b;
|
||||
background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
|
||||
box-shadow:inset 0 0 3px #111;
|
||||
}
|
||||
|
||||
div.alphabet a.empty {
|
||||
color:#888 !important;
|
||||
}
|
||||
|
||||
div.alphabet a.active,
|
||||
div.alphabet a.active.empty {
|
||||
color:#333 !important;
|
||||
border:1px solid #979797;
|
||||
background-color:#FFF;
|
||||
background:linear-gradient(to bottom, #fff 0%, #dcdcdc 100%)
|
||||
}
|
||||
|
||||
div.alphabet .alphabet-info-display {
|
||||
margin-right:0.5em;
|
||||
}
|
||||
|
||||
div.alphabet div.alphabet-info {
|
||||
position:absolute;
|
||||
border:1px solid #111;
|
||||
background-color:#585858;
|
||||
background:linear-gradient(to bottom, #585858 0%, #111 100%);
|
||||
border-radius:2px;
|
||||
color:#FFF;
|
||||
margin-top:0.2em;
|
||||
padding:0.2em 0.4em;
|
||||
text-align:center;
|
||||
opacity:0;
|
||||
z-index:9999;
|
||||
}
|
||||
|
||||
tr.alphabet-group, tr.alphabet-group:hover {
|
||||
background-color:rgba(0,0,0,0.15) !important;
|
||||
}
|
|
@ -228,6 +228,7 @@
|
|||
</div>
|
||||
<div id="opdsoptions">
|
||||
<div class="row_checkbox">
|
||||
<small>Access the OPDS server at http://mylarhost/opds/ - keep in mind your scheme (http or https), your hostname, port, and any http_root you may have set. </small></br>
|
||||
<input id="opds_authentication" type="checkbox" name="opds_authentication" value="1" ${config['opds_authentication']} /><label>OPDS Requires Credentials</label>
|
||||
<%
|
||||
opds_notes = "Require authentication for OPDS. If checked\nyou will need to provide a username/password.\nThe service user name will work (if set). Additionally,\nyou can provide a user with only OPDS access below.\nNOTE: If this is not checked, OPDS will be available\nwithout a password."
|
||||
|
|
|
@ -101,18 +101,20 @@
|
|||
|
||||
<%def name="headIncludes()">
|
||||
<link rel="stylesheet" href="interfaces/default/css/data_table.css">
|
||||
<link type="text/css" href="css/dataTables.alphabetSearch.css" rel="stylesheet">
|
||||
</%def>
|
||||
|
||||
<%def name="javascriptIncludes()">
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script src="js/libs/full_numbers_no_ellipses.js"></script>
|
||||
<script src="js/dataTables.alphabetSearch.min.js"></script>
|
||||
<script>
|
||||
|
||||
function initThisPage() {
|
||||
$.fn.DataTable.ext.pager.numbers_length = 3;
|
||||
$('#series_table').dataTable( {
|
||||
var table = $('#series_table').dataTable( {
|
||||
"destroy": true,
|
||||
"sDom": '<"clear"f><"clear"lp><"clear">rt<"clear"ip>',
|
||||
"sDom": '<"clear"Af><"clear"lp><"clear">rt<"clear"ip>',
|
||||
"columnDefs": [
|
||||
{ "orderable": false, "targets": [5, 7, 10] },
|
||||
{ "visible": false, "targets": [5, 7, 10] },
|
||||
|
@ -132,7 +134,10 @@
|
|||
"search" : ""},
|
||||
"stateSave": true,
|
||||
"pageLength": 25,
|
||||
"pagingType": "simple_numbers"
|
||||
"pagingType": "simple_numbers",
|
||||
alphabetSearch: {
|
||||
column:1
|
||||
}
|
||||
});
|
||||
resetFilters("comic");
|
||||
}
|
||||
|
|
|
@ -28,17 +28,25 @@
|
|||
</br></br>
|
||||
<table width="100%" align="center">
|
||||
<tr>
|
||||
<td style="vertical-align: middle; text-align: right"><a href="pullist?week=${weekinfo['prev_weeknumber']}&year=${weekinfo['prev_year']}" title="Previous Week (${weekinfo['prev_weeknumber']})"><img src="interfaces/default/images/prev.gif" width="16" height="18" Alt="Previous"/></td>
|
||||
<td style="vertical-align: middle; text-align: right">
|
||||
<a href="pullist?week=${weekinfo['prev_weeknumber']}&year=${weekinfo['prev_year']}" title="Previous Week (${weekinfo['prev_weeknumber']})" onclick="$('#pull_table').page('first').draw('page');">
|
||||
<img src="interfaces/default/images/prev.gif" width="16" height="18" Alt="Previous"/>
|
||||
</a>
|
||||
</td>
|
||||
<td style="vertical-align: middle; text-align: center">
|
||||
%if wantedcount == 0:
|
||||
<h1><center>Weekly Pull list for week ${weekinfo['weeknumber']} :</br>${weekinfo['startweek']} - ${weekinfo['endweek']}</center></h1>
|
||||
%else:
|
||||
<h1><center>Weekly Pull list for week ${weekinfo['weeknumber']} :</br>${weekinfo['startweek']} - ${weekinfo['endweek']} (${wantedcount})</center></h1>
|
||||
%endif
|
||||
</td><td style="vertical-align: middle; text-align: left">
|
||||
<a href="pullist?week=${weekinfo['next_weeknumber']}&year=${weekinfo['next_year']}" title="Next Week (${weekinfo['next_weeknumber']})"><img src="interfaces/default/images/next.gif" width="16" height="18" Alt="Next"/></a></td>
|
||||
<tr>
|
||||
</table>
|
||||
</td>
|
||||
<td style="vertical-align: middle; text-align: left">
|
||||
<a href="pullist?week=${weekinfo['next_weeknumber']}&year=${weekinfo['next_year']}" title="Next Week (${weekinfo['next_weeknumber']})" onclick="$('#pull_table').page('first').draw('page');">
|
||||
<img src="interfaces/default/images/next.gif" width="16" height="18" Alt="Next"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*! AlphabetSearch for DataTables v1.2.4
|
||||
* 2014 SpryMedia Ltd - datatables.net/license
|
||||
* Gyrocode - MIT License
|
||||
*/
|
||||
(function() { $.fn.dataTable.Api.register("alphabetSearch()", function(searchTerm) { this.iterator("table", function(context) { context.alphabetSearch.letter = searchTerm; }); return this; });
|
||||
$.fn.dataTable.Api.register("alphabetSearch.recalc()", function() { this.iterator("table", function(context) { draw(new $.fn.dataTable.Api(context), $("div.alphabet", this.table()
|
||||
.container()), context); }); return this; });
|
||||
$.fn.dataTable.ext.search.push(function(context, searchData) { if (!context.hasOwnProperty("alphabetSearch")) { return true; } if (!context.alphabetSearch.letterSearch) { return true; } var letter = searchData[context.alphabetSearch.column].toString()
|
||||
.replace(/<.*?>/g, "")
|
||||
.charAt(0)
|
||||
.toUpperCase(); if (context.alphabetSearch.letterSearch !== "#") { if (letter === context.alphabetSearch.letterSearch) { return true; } } else { if (/[^a-zA-Z]/.test(letter)) { return true; } } return false; });
|
||||
$.fn.dataTable.ext.order["alphabetSearch"] = function(context, col) { var order_col = this.api()
|
||||
.order()[0][0]; var order_method = this.api()
|
||||
.order()[0][1]; if (order_col !== context.alphabetSearch.column) { context.alphabetSearch.pass = 0; } var data = this.api()
|
||||
.column(col, { order: "index" })
|
||||
.data()
|
||||
.map(function(value, index) { var letter = value.replace(/<.*?>/g, "")
|
||||
.charAt(0)
|
||||
.toUpperCase(); return (order_col === context.alphabetSearch.column) ? ((!context.alphabetSearch.pass) ? "" : ((order_method === "asc") ? letter : String.fromCharCode(65535 - letter.charCodeAt(0)))) : letter; }); if (order_col === context.alphabetSearch.column) { if (!context.alphabetSearchPass) { context.alphabetSearch.pass = 0; } context.alphabetSearch.pass = (context.alphabetSearch.pass + 1) % 2; } return data; };
|
||||
|
||||
function bin(data) { var letter, bins = {}; for (var i = 0, ien = data.length; i < ien; i++) { letter = data[i].toString()
|
||||
.replace(/<.*?>/g, "")
|
||||
.charAt(0)
|
||||
.toUpperCase(); if (/[^a-zA-Z]/.test(letter)) { letter = "#"; } if (bins[letter]) { bins[letter]++; } else { bins[letter] = 1; } } return bins; }
|
||||
|
||||
function draw(table, alphabet, context) { alphabet.empty(); if (context.oLanguage.alphabetSearch.infoDisplay !== "") { $('<span class="alphabet-info-display"></span>')
|
||||
.html(context.oLanguage.alphabetSearch.infoDisplay)
|
||||
.appendTo(alphabet); } var columnData = table.column(context.alphabetSearch.column, { search: "applied" })
|
||||
.data(); var bins = bin(columnData); var alphabetList = $("<ul/>");
|
||||
$("<a/>")
|
||||
.attr("href", "javascript:;")
|
||||
.data("letter", "")
|
||||
.data("match-count", columnData.length)
|
||||
.addClass(((!context.alphabetSearch.letter) ? "active" : ""))
|
||||
.html("<span>" + context.oLanguage.alphabetSearch.infoAll + "</span>")
|
||||
.wrap("<li/>")
|
||||
.parent()
|
||||
.appendTo(alphabetList); for (var i = 0; i < context.oLanguage.alphabetSearch.alphabet.length; i++) { var letter = context.oLanguage.alphabetSearch.alphabet[i];
|
||||
$("<a/>")
|
||||
.attr("href", "javascript:;")
|
||||
.data("letter", letter)
|
||||
.data("match-count", bins[letter] || 0)
|
||||
.addClass((!bins[letter] ? "empty" : "") + ((context.alphabetSearch.letter === letter) ? " active" : ""))
|
||||
.html("<span>" + letter + "</span>")
|
||||
.wrap("<li/>")
|
||||
.parent()
|
||||
.appendTo(alphabetList); } alphabetList.appendTo(alphabet);
|
||||
$('<div class="alphabet-info"></div>')
|
||||
.appendTo(alphabet); if (context.alphabetSearch.letter) { context.alphabetSearch.letterSearch = context.alphabetSearch.letter;
|
||||
table.draw();
|
||||
context.alphabetSearch.letterSearch = ""; } table.one("search", function(e, context) { var api = new $.fn.dataTable.Api(context);
|
||||
api.alphabetSearch.recalc(); }); } $.fn.dataTable.AlphabetSearch = function(context) { var table = new $.fn.dataTable.Api(context); var alphabet = $('<div class="alphabet"/>');
|
||||
context.oLanguage.alphabetSearch = $.extend({ "alphabet": "#ABCDEFGHIJKLMNOPQRSTUVWXYZ", "infoDisplay": "Display:", "infoAll": "All" }, ((context.oLanguage.alphabetSearch) ? context.oLanguage.alphabetSearch : {}));
|
||||
context.oLanguage.alphabetSearch.alphabet.toUpperCase();
|
||||
context.alphabetSearch = $.extend({ column: 0 }, $.isPlainObject(context.oInit.alphabetSearch) ? context.oInit.alphabetSearch : {}, { letter: "", letterSearch: "", pass: 0 }); if (context.alphabetSearch.column >= 0 && context.alphabetSearch.column < context.aoColumns.length) { context.aoColumns[context.alphabetSearch.column].sSortDataType = "alphabetSearch"; } if (context.hasOwnProperty("aaSortingFixed") && typeof context.aaSortingFixed === "object") { if ($.isArray(context.aaSortingFixed)) { if (context.aaSortingFixed.length && !$.isArray(context.aaSortingFixed[0])) { context.aaSortingFixed = [
|
||||
[context.alphabetSearch.column, "asc"], context.aaSortingFixed
|
||||
]; } else { context.aaSortingFixed.unshift([context.alphabetSearch.column, "asc"]); } } else { if (!context.aaSortingFixed.hasOwnProperty("pre")) { context.aaSortingFixed.pre = []; } if (context.aaSortingFixed.pre.length && !$.isArray(context.aaSortingFixed.pre[0])) { context.aaSortingFixed.pre = [
|
||||
[context.alphabetSearch.column, "asc"], context.aaSortingFixed.pre
|
||||
]; } else { context.aaSortingFixed.pre.unshift([context.alphabetSearch.column, "asc"]); } } } else { context.aaSortingFixed = [context.alphabetSearch.column, "asc"]; } draw(table, alphabet, context);
|
||||
alphabet.on("click", "a", function(e) { e.preventDefault();
|
||||
alphabet.find(".active")
|
||||
.removeClass("active");
|
||||
$(this)
|
||||
.addClass("active");
|
||||
table.alphabetSearch($(this)
|
||||
.data("letter"))
|
||||
.draw(); });
|
||||
alphabet.on("mouseenter", "a", function() { var $el = $(this); var el_pos = $el.position(); var $alphabet_info = $(".alphabet-info", alphabet);
|
||||
$alphabet_info.html($el.data("match-count"));
|
||||
$alphabet_info.css({ opacity: 1, left: el_pos.left + Math.round(($el.outerWidth() - $alphabet_info.outerWidth()) / 2), top: $(this)
|
||||
.position()
|
||||
.top + $el.outerHeight() }); })
|
||||
.on("mouseleave", "a", function() { alphabet.find("div.alphabet-info")
|
||||
.css("opacity", 0); });
|
||||
table.on("draw", function(e, context) { var api = new $.fn.dataTable.Api(context); var col_total = api.columns()
|
||||
.nodes()
|
||||
.length; var rows = api.rows({ page: "current" })
|
||||
.nodes(); var group_last = null;
|
||||
api.column(context.alphabetSearch.column, { page: "current" })
|
||||
.data()
|
||||
.each(function(name, index) { var group = name.replace(/<.*?>/g, "")
|
||||
.charAt(0)
|
||||
.toUpperCase(); if (group_last !== group) { $(rows)
|
||||
.eq(index)
|
||||
.before('<tr class="alphabet-group" style="display:none;"><td colspan="' + col_total + '">' + group + "</td></tr>");
|
||||
group_last = group; } }); if (!rows.length && context.alphabetSearch) { var letter = context.alphabetSearch.letter;
|
||||
$(api.table()
|
||||
.body())
|
||||
.prepend('<tr class="alphabet-group" style="display:none;"><td colspan="' + col_total + '">' + letter + "</td></tr>"); } });
|
||||
this.node = function() { return alphabet; }; };
|
||||
$.fn.DataTable.AlphabetSearch = $.fn.dataTable.AlphabetSearch;
|
||||
$.fn.dataTable.ext.feature.push({ fnInit: function(settings) { var search = new $.fn.dataTable.AlphabetSearch(settings); return search.node(); }, cFeature: "A" }); }());
|
||||
|
||||
|
|
@ -1707,10 +1707,9 @@ class PostProcessor(object):
|
|||
if ml is not None and mylar.CONFIG.SNATCHEDTORRENT_NOTIFY:
|
||||
snatchnzb = myDB.selectone("SELECT * from snatched WHERE IssueID=? AND ComicID=? AND (provider=? OR provider=? OR provider=? OR provider=?) AND Status='Snatched'", [issueid, comicid, 'TPSE', 'DEM', 'WWT', '32P']).fetchone()
|
||||
if snatchnzb is None:
|
||||
logger.fdebug(module + ' Was not snatched as a torrent. Disabling torrent manual post-processing completion notification.')
|
||||
logger.fdebug(module + ' Was not snatched as a torrent. Using manual post-processing.')
|
||||
else:
|
||||
logger.fdebug(module + ' Was downloaded from ' + snatchnzb['Provider'] + '. Enabling torrent manual post-processing completion notification.')
|
||||
snatchedtorrent = True
|
||||
if issuenzb is None:
|
||||
issuenzb = myDB.selectone("SELECT * from annuals WHERE issueid=? and comicid=?", [issueid, comicid]).fetchone()
|
||||
annchk = "yes"
|
||||
|
@ -2361,20 +2360,16 @@ class PostProcessor(object):
|
|||
|
||||
if ml is not None:
|
||||
#we only need to return self.log if it's a manual run and it's not a snatched torrent
|
||||
if snatchedtorrent:
|
||||
#manual run + snatched torrent
|
||||
pass
|
||||
else:
|
||||
#manual run + not snatched torrent (or normal manual-run)
|
||||
logger.info(module + ' Post-Processing completed for: ' + series + ' ' + dispiss)
|
||||
self._log(u"Post Processing SUCCESSFUL! ")
|
||||
self.valreturn.append({"self.log": self.log,
|
||||
"mode": 'stop',
|
||||
"issueid": issueid,
|
||||
"comicid": comicid})
|
||||
if self.apicall is True:
|
||||
self.sendnotify(series, issueyear, dispiss, annchk, module)
|
||||
return self.queue.put(self.valreturn)
|
||||
#manual run + not snatched torrent (or normal manual-run)
|
||||
logger.info(module + ' Post-Processing completed for: ' + series + ' ' + dispiss)
|
||||
self._log(u"Post Processing SUCCESSFUL! ")
|
||||
self.valreturn.append({"self.log": self.log,
|
||||
"mode": 'stop',
|
||||
"issueid": issueid,
|
||||
"comicid": comicid})
|
||||
if self.apicall is True:
|
||||
self.sendnotify(series, issueyear, dispiss, annchk, module)
|
||||
return self.queue.put(self.valreturn)
|
||||
|
||||
self.sendnotify(series, issueyear, dispiss, annchk, module)
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ _CONFIG_DEFINITIONS = OrderedDict({
|
|||
'INDIE_PUB': (int, 'Weekly', 75),
|
||||
'BIGGIE_PUB': (int, 'Weekly', 55),
|
||||
'PACK_0DAY_WATCHLIST_ONLY': (bool, 'Weekly', True),
|
||||
'RESET_PULLIST_PAGINATION': (bool, 'Weekly', True),
|
||||
|
||||
'HTTP_PORT' : (int, 'Interface', 8090),
|
||||
'HTTP_HOST' : (str, 'Interface', '0.0.0.0'),
|
||||
|
|
|
@ -292,7 +292,7 @@ def addComictoDB(comicid, mismatch=None, pullupd=None, imported=None, ogcname=No
|
|||
if mylar.CONFIG.ENFORCE_PERMS:
|
||||
filechecker.setperms(comiclocal)
|
||||
except IOError as e:
|
||||
logger.error('Unable to save cover (' + str(coverfile) + ') into series directory (' + str(comiclocal) + ') at this time.')
|
||||
logger.error('Unable to save cover (' + str(comiclocal) + ') into series directory (' + str(comlocation) + ') at this time.')
|
||||
else:
|
||||
ComicImage = None
|
||||
|
||||
|
@ -1418,8 +1418,6 @@ def annual_check(ComicName, SeriesYear, comicid, issuetype, issuechk, annualslis
|
|||
|
||||
annual_types_ignore = {'paperback', 'collecting', 'reprints', 'collected edition', 'print edition', 'tpb', 'available in print', 'collects'}
|
||||
|
||||
if len(sresults) == 1:
|
||||
logger.fdebug('[IMPORTER-ANNUAL] - 1 result')
|
||||
if len(sresults) > 0:
|
||||
logger.fdebug('[IMPORTER-ANNUAL] - there are ' + str(len(sresults)) + ' results.')
|
||||
num_res = 0
|
||||
|
|
|
@ -208,8 +208,10 @@ class PUSHOVER:
|
|||
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'
|
||||
self.test = False
|
||||
else:
|
||||
self.PUSHOVER_URL = 'https://api.pushover.net/1/users/validate.json'
|
||||
self.test = True
|
||||
self.enabled = mylar.CONFIG.PUSHOVER_ENABLED
|
||||
if test_apikey is None:
|
||||
if mylar.CONFIG.PUSHOVER_APIKEY is None or mylar.CONFIG.PUSHOVER_APIKEY == 'None':
|
||||
|
@ -236,8 +238,7 @@ class PUSHOVER:
|
|||
self._session.headers = {'Content-type': "application/x-www-form-urlencoded"}
|
||||
|
||||
def notify(self, event, message=None, snatched_nzb=None, prov=None, sent_to=None, module=None):
|
||||
if not mylar.CONFIG.PUSHOVER_ENABLED:
|
||||
return
|
||||
|
||||
if module is None:
|
||||
module = ''
|
||||
module += '[NOTIFIER]'
|
||||
|
@ -261,23 +262,36 @@ class PUSHOVER:
|
|||
if r.status_code == 200:
|
||||
try:
|
||||
response = r.json()
|
||||
if 'devices' in response:
|
||||
logger.info('%s PushOver notifications sent. Available devices: %s' % (module, response))
|
||||
if 'devices' in response and self.test is True:
|
||||
logger.fdebug('%s Available devices: %s' % (module, response))
|
||||
if any([self.device is None, self.device == 'None']):
|
||||
self.device = 'all available devices'
|
||||
|
||||
r = self._session.post('https://api.pushover.net/1/messages.json', data=data, verify=True)
|
||||
if r.status_code == 200:
|
||||
logger.info('%s PushOver notifications sent to %s.' % (module, self.device))
|
||||
elif r.status_code >=400 and r.status_code < 500:
|
||||
logger.error('%s PushOver request failed to %s: %s' % (module, self.device, r.content))
|
||||
return False
|
||||
else:
|
||||
logger.error('%s PushOver notification failed serverside.' % module)
|
||||
return False
|
||||
else:
|
||||
logger.info('%s PushOver notifications sent.' % module)
|
||||
except Exception as e:
|
||||
logger.warn('%s[ERROR] - %s' % (module, e))
|
||||
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif r.status_code >= 400 and r.status_code < 500:
|
||||
logger.error(module + ' PushOver request failed: %s' % r.content)
|
||||
logger.error('%s PushOver request failed: %s' % (module, r.content))
|
||||
return False
|
||||
else:
|
||||
logger.error(module + ' PushOver notification failed serverside.')
|
||||
logger.error('%s PushOver notification failed serverside.' % module)
|
||||
return False
|
||||
|
||||
def test_notify(self):
|
||||
return self.notify(message='Release the Ninjas!',event='Test Message')
|
||||
return self.notify(event='Test Message', message='Release the Ninjas!')
|
||||
|
||||
class BOXCAR:
|
||||
|
||||
|
@ -468,12 +482,19 @@ class TELEGRAM:
|
|||
class SLACK:
|
||||
def __init__(self, test_webhook_url=None):
|
||||
self.webhook_url = mylar.CONFIG.SLACK_WEBHOOK_URL if test_webhook_url is None else test_webhook_url
|
||||
|
||||
def notify(self, text, attachment_text, module=None):
|
||||
|
||||
def notify(self, text, attachment_text, snatched_nzb=None, prov=None, sent_to=None, module=None):
|
||||
if module is None:
|
||||
module = ''
|
||||
module += '[NOTIFIER]'
|
||||
|
||||
|
||||
if all([sent_to is not None, prov is not None]):
|
||||
attachment_text += ' from %s and sent to %s' % (prov, sent_to)
|
||||
elif sent_to is None:
|
||||
attachment_text += ' from %s' % prov
|
||||
else:
|
||||
pass
|
||||
|
||||
payload = {
|
||||
# "text": text,
|
||||
# "attachments": [
|
||||
|
@ -499,6 +520,6 @@ class SLACK:
|
|||
|
||||
logger.info(module + u"Slack notifications sent.")
|
||||
return sent_successfuly
|
||||
|
||||
|
||||
def test_notify(self):
|
||||
return self.notify('Test Message', 'Release the Ninjas!')
|
||||
|
|
114
mylar/opds.py
114
mylar/opds.py
|
@ -17,11 +17,12 @@
|
|||
# along with Mylar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import mylar
|
||||
from mylar import db, mb, importer, search, PostProcessor, versioncheck, logger, readinglist
|
||||
from mylar import db, mb, importer, search, PostProcessor, versioncheck, logger, readinglist, helpers
|
||||
import simplejson as simplejson
|
||||
import cherrypy
|
||||
from xml.sax.saxutils import escape
|
||||
import os
|
||||
import glob
|
||||
import urllib2
|
||||
from urllib import urlencode, quote_plus
|
||||
import cache
|
||||
|
@ -30,8 +31,9 @@ from operator import itemgetter
|
|||
from cherrypy.lib.static import serve_file, serve_download
|
||||
import datetime
|
||||
from mylar.webserve import serve_template
|
||||
import re
|
||||
|
||||
cmd_list = ['root', 'Publishers', 'AllTitles', 'StoryArcs', 'ReadList', 'Comic', 'Publisher', 'Issue', 'StoryArc', 'Recent']
|
||||
cmd_list = ['root', 'Publishers', 'AllTitles', 'StoryArcs', 'ReadList', 'OneOffs', 'Comic', 'Publisher', 'Issue', 'StoryArc', 'Recent', 'deliverFile']
|
||||
|
||||
class OPDS(object):
|
||||
|
||||
|
@ -119,7 +121,8 @@ class OPDS(object):
|
|||
myDB = db.DBConnection()
|
||||
feed = {}
|
||||
feed['title'] = 'Mylar OPDS'
|
||||
feed['id'] = 'OPDSRoot'
|
||||
currenturi = cherrypy.url()
|
||||
feed['id'] = re.sub('/', ':', currenturi)
|
||||
feed['updated'] = mylar.helpers.now()
|
||||
links = []
|
||||
entries=[]
|
||||
|
@ -196,7 +199,20 @@ class OPDS(object):
|
|||
'rel': 'subsection',
|
||||
}
|
||||
)
|
||||
|
||||
gbd = mylar.CONFIG.GRABBAG_DIR + '/*'
|
||||
oneofflist = glob.glob(gbd)
|
||||
if len(oneofflist) > 0:
|
||||
entries.append(
|
||||
{
|
||||
'title': 'One-Offs (%s)' % len(oneofflist),
|
||||
'id': 'OneOffs',
|
||||
'updated': mylar.helpers.now(),
|
||||
'content': 'OneOffs',
|
||||
'href': '%s?cmd=OneOffs' % self.opdsroot,
|
||||
'kind': 'navigation',
|
||||
'rel': 'subsection',
|
||||
}
|
||||
)
|
||||
feed['links'] = links
|
||||
feed['entries'] = entries
|
||||
self.data = feed
|
||||
|
@ -267,10 +283,10 @@ class OPDS(object):
|
|||
if comic['haveissues'] > 0:
|
||||
entries.append(
|
||||
{
|
||||
'title': escape('%s (%s) (%s)' % (comic['ComicName'], comic['ComicYear'], comic['haveissues'])),
|
||||
'id': escape('comic:%s (%s)' % (comic['ComicName'], comic['ComicYear'])),
|
||||
'title': escape('%s (%s) (comicID: %s)' % (comic['ComicName'], comic['ComicYear'], comic['ComicID'])),
|
||||
'id': escape('comic:%s (%s) [%s]' % (comic['ComicName'], comic['ComicYear'], comic['ComicID'])),
|
||||
'updated': comic['DateAdded'],
|
||||
'content': escape('%s (%s) (%s)' % (comic['ComicName'], comic['ComicYear'], comic['haveissues'])),
|
||||
'content': escape('%s (%s)' % (comic['ComicName'], comic['ComicYear'])),
|
||||
'href': '%s?cmd=Comic&comicid=%s' % (self.opdsroot, quote_plus(comic['ComicID'])),
|
||||
'kind': 'acquisition',
|
||||
'rel': 'subsection',
|
||||
|
@ -304,10 +320,10 @@ class OPDS(object):
|
|||
if comic['ComicPublisher'] == kwargs['pubid'] and comic['haveissues'] > 0:
|
||||
entries.append(
|
||||
{
|
||||
'title': escape('%s (%s) (%s)' % (comic['ComicName'], comic['ComicYear'], comic['haveissues'])),
|
||||
'title': escape('%s (%s)' % (comic['ComicName'], comic['ComicYear'])),
|
||||
'id': escape('comic:%s (%s)' % (comic['ComicName'], comic['ComicYear'])),
|
||||
'updated': comic['DateAdded'],
|
||||
'content': escape('%s (%s) (%s)' % (comic['ComicName'], comic['ComicYear'], comic['haveissues'])),
|
||||
'content': escape('%s (%s)' % (comic['ComicName'], comic['ComicYear'])),
|
||||
'href': '%s?cmd=Comic&comicid=%s' % (self.opdsroot, quote_plus(comic['ComicID'])),
|
||||
'kind': 'acquisition',
|
||||
'rel': 'subsection',
|
||||
|
@ -383,7 +399,7 @@ class OPDS(object):
|
|||
entries.append(
|
||||
{
|
||||
'title': title,
|
||||
'id': escape('comic:%s - %s' % (issue['ComicName'], issue['Issue_Number'])),
|
||||
'id': escape('comic:%s (%s) [%s] - %s' % (issue['ComicName'], comic['ComicYear'], comic['ComicID'], issue['Issue_Number'])),
|
||||
'updated': updated,
|
||||
'content': escape('%s' % (metainfo[0]['summary'])),
|
||||
'href': '%s?cmd=Issue&issueid=%s&file=%s' % (self.opdsroot, quote_plus(issue['IssueID']),quote_plus(issue['Location'].encode('utf-8'))),
|
||||
|
@ -460,7 +476,7 @@ class OPDS(object):
|
|||
entries.append(
|
||||
{
|
||||
'title': title,
|
||||
'id': escape('comic:%s - %s' % (issuebook['ComicName'], issuebook['Issue_Number'])),
|
||||
'id': escape('comic:%s (%s) - %s' % (issuebook['ComicName'], comic['ComicYear'], issuebook['Issue_Number'])),
|
||||
'updated': updated,
|
||||
'content': escape('%s' % (metainfo[0]['summary'])),
|
||||
'href': '%s?cmd=Issue&issueid=%s&file=%s' % (self.opdsroot, quote_plus(issuebook['IssueID']),quote_plus(location)),
|
||||
|
@ -489,7 +505,16 @@ class OPDS(object):
|
|||
self.data = feed
|
||||
return
|
||||
|
||||
|
||||
def _deliverFile(self, **kwargs):
|
||||
logger.fdebug("_deliverFile: kwargs: %s" % kwargs)
|
||||
if 'file' not in kwargs:
|
||||
self.data = self._error_with_message('No file provided')
|
||||
elif 'filename' not in kwargs:
|
||||
self.data = self._error_with_message('No filename provided')
|
||||
else:
|
||||
self.filename = os.path.split(str(kwargs['file']))[1]
|
||||
self.file = str(kwargs['file'])
|
||||
return
|
||||
|
||||
def _Issue(self, **kwargs):
|
||||
if 'issueid' not in kwargs:
|
||||
|
@ -573,6 +598,71 @@ class OPDS(object):
|
|||
self.data = feed
|
||||
return
|
||||
|
||||
def _OneOffs(self, **kwargs):
|
||||
index = 0
|
||||
if 'index' in kwargs:
|
||||
index = int(kwargs['index'])
|
||||
links = []
|
||||
entries = []
|
||||
flist = []
|
||||
book = ''
|
||||
gbd = str(mylar.CONFIG.GRABBAG_DIR + '/*').encode('utf-8')
|
||||
flist = glob.glob(gbd)
|
||||
readlist = []
|
||||
for book in flist:
|
||||
issue = {}
|
||||
fileexists = True
|
||||
book = book.encode('utf-8')
|
||||
issue['Title'] = book
|
||||
issue['IssueID'] = book
|
||||
issue['fileloc'] = book
|
||||
issue['filename'] = book
|
||||
issue['image'] = None
|
||||
issue['thumbnail'] = None
|
||||
issue['updated'] = helpers.now()
|
||||
if not os.path.isfile(issue['fileloc']):
|
||||
fileexists = False
|
||||
if fileexists:
|
||||
readlist.append(issue)
|
||||
if len(readlist) > 0:
|
||||
if index <= len(readlist):
|
||||
subset = readlist[index:(index + self.PAGE_SIZE)]
|
||||
for issue in subset:
|
||||
metainfo = None
|
||||
metainfo = [{'writer': None,'summary': ''}]
|
||||
entries.append(
|
||||
{
|
||||
'title': escape(issue['Title']),
|
||||
'id': escape('comic:%s' % issue['IssueID']),
|
||||
'updated': issue['updated'],
|
||||
'content': escape('%s' % (metainfo[0]['summary'])),
|
||||
'href': '%s?cmd=deliverFile&file=%s&filename=%s' % (self.opdsroot, quote_plus(issue['fileloc']), quote_plus(issue['filename'])),
|
||||
'kind': 'acquisition',
|
||||
'rel': 'file',
|
||||
'author': metainfo[0]['writer'],
|
||||
'image': issue['image'],
|
||||
'thumbnail': issue['thumbnail'],
|
||||
}
|
||||
)
|
||||
|
||||
feed = {}
|
||||
feed['title'] = 'Mylar OPDS - One-Offs'
|
||||
feed['id'] = escape('OneOffs')
|
||||
feed['updated'] = mylar.helpers.now()
|
||||
links.append(getLink(href=self.opdsroot,type='application/atom+xml; profile=opds-catalog; kind=navigation', rel='start', title='Home'))
|
||||
links.append(getLink(href='%s?cmd=OneOffs' % self.opdsroot,type='application/atom+xml; profile=opds-catalog; kind=navigation',rel='self'))
|
||||
if len(readlist) > (index + self.PAGE_SIZE):
|
||||
links.append(
|
||||
getLink(href='%s?cmd=OneOffs&index=%s' % (self.opdsroot, index+self.PAGE_SIZE), type='application/atom+xml; profile=opds-catalog; kind=navigation', rel='next'))
|
||||
if index >= self.PAGE_SIZE:
|
||||
links.append(
|
||||
getLink(href='%s?cmd=Read&index=%s' % (self.opdsroot, index-self.PAGE_SIZE), type='application/atom+xml; profile=opds-catalog; kind=navigation', rel='previous'))
|
||||
|
||||
feed['links'] = links
|
||||
feed['entries'] = entries
|
||||
self.data = feed
|
||||
return
|
||||
|
||||
def _ReadList(self, **kwargs):
|
||||
index = 0
|
||||
if 'index' in kwargs:
|
||||
|
|
|
@ -635,7 +635,7 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
|
|||
if host_torznab[len(host_torznab)-1:len(host_torznab)] == '/':
|
||||
torznab_fix = host_torznab[:-1]
|
||||
else:
|
||||
torznab_fix = host.torznab
|
||||
torznab_fix = host_torznab
|
||||
findurl = str(torznab_fix) + "?t=search&q=" + str(comsearch)
|
||||
if category_torznab is not None:
|
||||
findurl += "&cat=" + str(category_torznab)
|
||||
|
@ -2981,7 +2981,7 @@ def notify_snatch(nzbname, sent_to, modcomicname, comyear, IssueNumber, nzbprov)
|
|||
if mylar.CONFIG.SLACK_ENABLED and mylar.CONFIG.SLACK_ONSNATCH:
|
||||
logger.info(u"Sending Slack notification")
|
||||
slack = notifiers.SLACK()
|
||||
slack.notify("Snatched", snline)
|
||||
slack.notify("Snatched", snline, snatched_nzb=nzbname, sent_to=sent_to, prov=nzbprov)
|
||||
|
||||
return
|
||||
|
||||
|
|
|
@ -5393,7 +5393,7 @@ class WebInterface(object):
|
|||
if result == True:
|
||||
return "Successfully sent PushOver test - check to make sure it worked"
|
||||
else:
|
||||
logger.warn('Test variables used [APIKEY: %s][USERKEY: %s]' % (apikey, userkey))
|
||||
logger.warn('Last six characters of the test variables used [APIKEY: %s][USERKEY: %s]' % (apikey[-6:], userkey[-6:]))
|
||||
return "Error sending test message to Pushover"
|
||||
testpushover.exposed = True
|
||||
|
||||
|
|
Loading…
Reference in New Issue