Skip to content

Commit

Permalink
Merge pull request #1270 from philborman/master
Browse files Browse the repository at this point in the history
Various fixes and enhancements
  • Loading branch information
philborman authored Mar 19, 2018
2 parents 61caa2d + 741b775 commit 2f89a49
Show file tree
Hide file tree
Showing 19 changed files with 580 additions and 362 deletions.
16 changes: 10 additions & 6 deletions LazyLibrarian.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,27 @@
import locale
import os
import platform
import stat
import sys
import threading
import time
import re

import lazylibrarian
from lazylibrarian import webStart, logger, versioncheck, dbupgrade
from lazylibrarian.formatter import check_int

# noinspection PyUnresolvedReferences
from lib.six.moves import configparser

# The following should probably be made configurable at the settings level
# This fix is put in place for systems with broken SSL (like QNAP)
opt_out_of_certificate_verification = True
if opt_out_of_certificate_verification:
# noinspection PyBroadException
try:
import ssl
# noinspection PyProtectedMember
ssl._create_default_https_context = ssl._create_unverified_context
except:
except Exception:
pass
# ==== end block (should be configurable at settings level)

Expand Down Expand Up @@ -135,7 +136,7 @@ def main():
lazylibrarian.PIDFILE = str(options.pidfile)

# create and check (optional) paths
if not os.path.exists(lazylibrarian.DATADIR):
if not os.path.isdir(lazylibrarian.DATADIR):
try:
os.makedirs(lazylibrarian.DATADIR)
except OSError:
Expand All @@ -161,7 +162,8 @@ def main():
versioncheck.checkForUpdates()

logger.debug('Current Version [%s] - Latest remote version [%s] - Install type [%s]' % (
lazylibrarian.CONFIG['CURRENT_VERSION'], lazylibrarian.CONFIG['LATEST_VERSION'], lazylibrarian.CONFIG['INSTALL_TYPE']))
lazylibrarian.CONFIG['CURRENT_VERSION'], lazylibrarian.CONFIG['LATEST_VERSION'],
lazylibrarian.CONFIG['INSTALL_TYPE']))

if lazylibrarian.CONFIG['VERSIONCHECK_INTERVAL'] == 0:
logger.debug('Automatic update checks are disabled')
Expand Down Expand Up @@ -219,7 +221,9 @@ def main():
})

if lazylibrarian.CONFIG['LAUNCH_BROWSER'] and not options.nolaunch:
lazylibrarian.launch_browser(lazylibrarian.CONFIG['HTTP_HOST'], lazylibrarian.CONFIG['HTTP_PORT'], lazylibrarian.CONFIG['HTTP_ROOT'])
lazylibrarian.launch_browser(lazylibrarian.CONFIG['HTTP_HOST'],
lazylibrarian.CONFIG['HTTP_PORT'],
lazylibrarian.CONFIG['HTTP_ROOT'])

if curr_ver:
threading.Thread(target=dbupgrade.dbupgrade, name="DB_UPGRADE", args=[curr_ver]).start()
Expand Down
16 changes: 1 addition & 15 deletions data/interfaces/bookstrap/audio.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,6 @@ <h1>${title}</h1>
<script type="text/javascript">
$(document).ready(function() {

$('#go').click(function () {
var action = $("#action").val();
if (action == "Delete") {
if (confirm('Are you sure you want to permanently delete the selected books?')) {
return
} else {
$("#action").val("Leave")
return
}
} else {
return
}
});

$('#chooselanguage').val(getUrlVars()['BookLang']);

var show = ""+${lazylibrarian.CONFIG['BOOK_IMG']};
Expand Down Expand Up @@ -183,7 +169,7 @@ <h1>${title}</h1>
"sPaginationType": "full_numbers",
"aaSorting": [[0, 'asc']],
"bServerSide": true,
"sAjaxSource": 'getBooks?source=Audio&booklang=${booklang}',
"sAjaxSource": 'getBooks?source=Audio&library=AudioBook&booklang=${booklang}',
"bFilter": true,
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
%if perm&lazylibrarian.perm_status:
Expand Down
23 changes: 22 additions & 1 deletion data/interfaces/bookstrap/author.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<a href="libraryScanAuthor?AuthorID=${author['AuthorID']}&library=AudioBook" class="btn btn-sm btn-primary"><i class="fa fa-refresh"></i> AudioBook Scan</a>
%endif
% endif
<a href="removeAuthor?AuthorID=${author['AuthorID']}" class="btn btn-sm btn-primary"><i class="fa fa-remove"></i> Remove Author</a>
<button class="button btn btn-sm btn-primary" type="button" value="removeme" id="removeme"><i class="fa fa-remove"></i> Remove Author</button>
<a href="authorPage?AuthorID=${author['AuthorID']}&amp;Ignored=True" class="btn btn-sm btn-primary"><i class="fa fa-ban"></i> Ignored Books</a>
%endif
%if showseries >= 1:
Expand Down Expand Up @@ -200,6 +200,26 @@ <h1><a href="${author['AuthorLink']}" target="_blank" rel="noreferrer">${author[
<script type="text/javascript">
$(document).ready(function()
{
$('#removeme').click(function () {
bootbox.confirm({
message: "Are you sure you want to permanently delete the author?",
buttons: {
confirm: {
label: 'Yes',
className: 'btn-success'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
if (result) { $.get("removeAuthor", {'AuthorID': ${author['AuthorID']} },
function (data) { window.location = 'home' }); }
}
});
});

$('#chooselanguage').change(function(){
new_settings = 'authorPage?AuthorID=${author['AuthorID']}&BookLang=' + $(this).val()
if (typeof $("#chooselib").val() != 'undefined') {
Expand Down Expand Up @@ -317,6 +337,7 @@ <h1><a href="${author['AuthorLink']}" target="_blank" rel="noreferrer">${author[
column.visible( ! column.visible() );
} );
});

// Read a page's GET URL variables and return them as an associative array.
function getUrlVars() {
var vars = [], hash;
Expand Down
13 changes: 10 additions & 3 deletions data/interfaces/bookstrap/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -703,13 +703,19 @@ <h1>${title}</h1>
<input type="text" id="deluge_host" name="deluge_host" value="${lazylibrarian.CONFIG['DELUGE_HOST']}" class="form-control" placeholder="Deluge Host">
</div>
<div class="form-group col-md-4">
<label for="deluge_port" class="control-label">Deluge Port:</label>
<label for="deluge_port" class="control-label">Daemon or webUI Port:</label>
<input type="text" id="deluge_port" name="deluge_port" value="${lazylibrarian.CONFIG['DELUGE_PORT']}" class="form-control" placeholder="Deluge Port">
</div>
</div>
<div class="row">
<div class="form-group col-md-8">
<label for="deluge_cert">Deluge Certificate: (webUI only)</label>
<input type="text" id="deluge_cert" name="deluge_cert" value="${lazylibrarian.CONFIG['DELUGE_CERT']}" class="form-control" placeholder="Deluge Certificate">
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="deluge_user" class="controllabel">Username:</label>
<label for="deluge_user" class="controllabel">Username: (daemon only)</label>
<input type="text" id="deluge_user" name="deluge_user" value="${lazylibrarian.CONFIG['DELUGE_USER']}" class="form-control" placeholder="Deluge Username">
</div>
<div class="form-group col-md-6">
Expand Down Expand Up @@ -3124,11 +3130,12 @@ <h1>${title}</h1>

$('#testDeluge').on('click', function() {
var host = $.trim($("#deluge_host").val());
var cert = $.trim($("#deluge_cert").val());
var port = $.trim($("#deluge_port").val());
var user = $.trim($("#deluge_user").val());
var pwd = $.trim($("#deluge_pass").val());
var label = $.trim($("#deluge_label").val());
$.get("testDeluge", {'host': host, 'port': port, 'user': user, 'pwd': pwd, 'label': label},
$.get("testDeluge", {'host': host, 'port': port, 'cert': cert, 'user': user, 'pwd': pwd, 'label': label},
function(data) {
bootbox.dialog({
title: 'Deluge Connection',
Expand Down
1 change: 1 addition & 0 deletions data/interfaces/bookstrap/managebooks.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ <h1>${title}</h1>
<br>
<form action="markBooks" method="get" class="form-inline">
<input type="hidden" name="redirect" value="manage">
<input type="hidden" name="library" value="${library}">
<div class="table-responsive">
<table class="display table table-striped table-hover table-bordered" id="book_table">
<thead>
Expand Down
2 changes: 1 addition & 1 deletion data/interfaces/bookstrap/manualsearch.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ <h2>${title}</h2>
<tr>
<td class="bookid">${item['score']} %</td>
<td class="filename">${item['title']}</td>
<td class="provider"><a href="${item['url']}">${item['provider']}</a></td>
<td class="provider">${item['provider']}</td>
<td class="size text-right">${item['size']}</td>
<td class="dateadded">${item['date']}</td>
<td class="status text-center"> <a class="btn btn-xs btn-info button"
Expand Down
7 changes: 6 additions & 1 deletion data/interfaces/legacy/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ <h3>Torrents</h3>
<label>Deluge Port:</label>
<input type="text" id="deluge_port" name="deluge_port" value="${lazylibrarian.CONFIG['DELUGE_PORT']}" size="26">
</div>
<div class="row">
<label>Deluge Cert:</label>
<input type="text" id="deluge_cert" name="deluge_cert" value="${lazylibrarian.CONFIG['DELUGE_CERT']}" size="26">
</div>
<div class="row">
<label>Username:</label>
<input type="text" id="deluge_user" name="deluge_user" value="${lazylibrarian.CONFIG['DELUGE_USER']}" size="26">
Expand Down Expand Up @@ -2554,11 +2558,12 @@ <h3>Magazine Reject Lists (per title)</h3>

$('#testDeluge').click(function () {
var host = $.trim($("#deluge_host").val());
var cert = $.trim($("#deluge_cert").val());
var port = $.trim($("#deluge_port").val());
var user = $.trim($("#deluge_user").val());
var pwd = $.trim($("#deluge_pass").val());
var label = $.trim($("#deluge_label").val());
$.get("testDeluge", {'host': host, 'port': port, 'user': user, 'pwd': pwd, 'label': label},
$.get("testDeluge", {'host': host, 'port': port, 'cert': cert, 'user': user, 'pwd': pwd, 'label': label},
function (data) { alert(data); });
});

Expand Down
27 changes: 14 additions & 13 deletions lazylibrarian/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
'TRANSMISSION_USER': ('str', 'TRANSMISSION', ''),
'TRANSMISSION_PASS': ('str', 'TRANSMISSION', ''),
'TRANSMISSION_DIR': ('str', 'TRANSMISSION', ''),
'DELUGE_CERT': ('str', 'DELUGE', ''),
'DELUGE_HOST': ('str', 'DELUGE', ''),
'DELUGE_PORT': ('int', 'DELUGE', 0),
'DELUGE_USER': ('str', 'DELUGE', ''),
Expand Down Expand Up @@ -540,10 +541,10 @@ def initialize():
CONFIG['LOGDIR'] = os.path.join(DATADIR, 'Logs')

# Create logdir
try:
os.makedirs(CONFIG['LOGDIR'])
except OSError as e:
if LOGLEVEL:
if not os.path.isdir(CONFIG['LOGDIR']):
try:
os.makedirs(CONFIG['LOGDIR'])
except OSError as e:
print('%s : Unable to create folder for logs: %s' % (CONFIG['LOGDIR'], str(e)))

# Start the logger, silence console logging if we need to
Expand Down Expand Up @@ -571,18 +572,18 @@ def initialize():

# Put the cache dir in the data dir for now
CACHEDIR = os.path.join(DATADIR, 'cache')
try:
os.makedirs(CACHEDIR)
except OSError as e:
if not os.path.isdir(CACHEDIR):
if not os.path.isdir(CACHEDIR):
try:
os.makedirs(CACHEDIR)
except OSError as e:
logger.error('Could not create cachedir; %s' % e)

for item in ['book', 'author', 'SeriesCache', 'JSONCache', 'XMLCache', 'WorkCache', 'magazine']:
cachelocation = os.path.join(CACHEDIR, item)
try:
os.makedirs(cachelocation)
except OSError as e:
if not os.path.isdir(cachelocation):
if not os.path.isdir(cachelocation):
try:
os.makedirs(cachelocation)
except OSError as e:
logger.error('Could not create %s: %s' % (cachelocation, e))

# keep track of last api calls so we don't call more than once per second
Expand Down Expand Up @@ -1105,7 +1106,7 @@ def DIRECTORY(dirname):
f.write('test')
os.remove(os.path.join(usedir, 'll_temp'))
except Exception as why:
logger.warn("%s dir [%s] not usable, using %s: %s" % (dirname, usedir, DATADIR, str(why)))
logger.warn("%s dir [%s] not writeable, using %s: %s" % (dirname, usedir, DATADIR, str(why)))
logger.debug("Folder: %s Mode: %s UID: %s GID: %s W_OK: %s X_OK: %s" % (usedir,
oct(os.stat(usedir).st_mode), os.stat(usedir).st_uid, os.stat(usedir).st_gid,
os.access(usedir, os.W_OK), os.access(usedir, os.X_OK)))
Expand Down
14 changes: 10 additions & 4 deletions lazylibrarian/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@
'loadCFG': 'reload config from file',
'getBookCover': '&id= [&src=] fetch cover link from cache/cover/librarything/goodreads/google for BookID',
'getAllBooks': 'list all books in the database',
'getNoLang': 'list all books in the database with unknown language',
'listNoLang': 'list all books in the database with unknown language',
'listNoISBN': 'list all books in the database with no isbn',
'listIgnoredAuthors': 'list all authors in the database marked ignored',
'listIgnoredBooks': 'list all books in the database marked ignored',
'listIgnoredSeries': 'list all series in the database marked ignored',
Expand All @@ -120,7 +121,7 @@
'showThreads': 'show threaded processes',
'checkRunningJobs': 'ensure all needed jobs are running',
'vacuum': 'vacuum the database',
'getWorkSeries': '&id= Get series from Librarything BookWork using BookID',
'getWorkSeries': '&id= Get series from Librarything BookWork using BookID or GoodReads using WorkID',
'getSeriesMembers': '&id= Get list of series members from Librarything using SeriesID',
'getSeriesAuthors': '&id= Get all authors from Librarything for a series and import them',
'getWorkPage': '&id= Get url of Librarything BookWork using BookID',
Expand All @@ -129,7 +130,7 @@
'cleanCache': '[&wait] Clean unused and expired files from the LazyLibrarian caches',
'deleteEmptySeries': 'Delete any book series that have no members',
'setWorkPages': '[&wait] Set the WorkPages links in the database',
'setAllBookSeries': '[&wait] Set the series details from book workpages',
'setAllBookSeries': '[&wait] Set the series details from librarything workpages',
'setAllBookAuthors': '[&wait] Set all authors for all books from book workpages',
'importAlternate': '[&wait] [&dir=] Import books from named or alternate folder and any subfolders',
'importCSVwishlist': '[&wait] [&dir=] Import a CSV wishlist from named or alternate directory',
Expand Down Expand Up @@ -433,11 +434,16 @@ def _getIndex(self):
self.data = self._dic_from_query(
'SELECT * from authors order by AuthorName COLLATE NOCASE')

def _getNoLang(self):
def _listNoLang(self):
q = 'SELECT BookID,BookISBN,BookName,AuthorName from books,authors where books.AuthorID = authors.AuthorID'
q += ' and BookLang="Unknown" or BookLang="" or BookLang is NULL'
self.data = self._dic_from_query(q)

def _listNoISBN(self):
q = 'SELECT BookID,BookName,AuthorName from books,authors where books.AuthorID = authors.AuthorID'
q += ' and BookISBN is NULL'
self.data = self._dic_from_query(q)

def _listIgnoredSeries(self):
q = 'SELECT SeriesID,SeriesName from series where Status="Ignored"'
self.data = self._dic_from_query(q)
Expand Down
16 changes: 8 additions & 8 deletions lazylibrarian/csvfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
from lazylibrarian.importer import search_for, import_book, addAuthorNameToDB
from lazylibrarian.librarysync import find_book_in_db
try:
import csv
from csv import writer, reader, QUOTE_MINIMAL
except ImportError:
if PY2:
import lib.csv as csv
from lib.csv import writer, reader, QUOTE_MINIMAL
else:
import lib3.csv as csv
from lib3.csv import writer, reader, QUOTE_MINIMAL


def export_CSV(search_dir=None, status="Wanted"):
Expand Down Expand Up @@ -64,8 +64,8 @@ def export_CSV(search_dir=None, status="Wanted"):
else:
fmode = 'w'
with open(csvFile, fmode) as csvfile:
csvwrite = csv.writer(csvfile, delimiter=',',
quotechar='"', quoting=csv.QUOTE_MINIMAL)
csvwrite = writer(csvfile, delimiter=',',
quotechar='"', quoting=QUOTE_MINIMAL)

# write headers, change AuthorName BookName BookIsbn to match import csv names (Author, Title, ISBN10)
csvwrite.writerow(['BookID', 'Author', 'Title', 'ISBN', 'AuthorID'])
Expand Down Expand Up @@ -157,9 +157,9 @@ def import_CSV(search_dir=None):
return msg
else:
logger.debug('Reading file %s' % csvFile)
reader = csv.reader(open(csvFile, 'rU'))
for row in reader:
if reader.line_num == 1:
csvreader = reader(open(csvFile, 'rU'))
for row in csvreader:
if csvreader.line_num == 1:
# If we are on the first line, create the headers list from the first row
headers = row
else:
Expand Down
Loading

0 comments on commit 2f89a49

Please sign in to comment.