diff --git a/caliGraph.py b/caliGraph.py index e769fb5..0364e1f 100755 --- a/caliGraph.py +++ b/caliGraph.py @@ -18,6 +18,9 @@ import plotly.graph_objects as go import wikipedia +class Error(Exception): + pass + def getAllAuthors(books): authors = set() for book in books: @@ -476,7 +479,7 @@ def readColor(book): return 'gray' def loadBooksFromDB(): - books = loadBooksFromCalibreDB() + books = calibreDB.getBooks() infuseDataFromMRB(books) #infuseDataFromTGB(books) return books @@ -527,8 +530,61 @@ def infuseDataFromTGB(books): if tgb: book['tgb_rank'] = int(tgb['id']) -def loadBooksFromCalibreDB(): - return json.loads(os.popen("calibredb list --for-machine -f all").read()) +class calibreDB(): + @classmethod + def _getTxt(cls, request): + ret = os.popen("calibredb "+request).read() + if not ret: + raise Error('Unable to connect to CalibreDB. Please close all open instances of Calibre.') + return ret + + @classmethod + def _getJson(cls, request): + return json.loads(cls._getTxt(request)) + + @classmethod + def getBooks(cls): + return cls._getJson('list --for-machine -f all') + + @classmethod + def getCustomColumns(cls): + lines = cls._getTxt('custom_columns').split('\n') + cols = [line.split(' ')[0] for line in lines] + return cols + + @classmethod + def _requireCaliceColumn(cls): + if not 'calice' in cls.getCustomColumns(): + raise Error('Custom Column missing from CalibreDB. Create it using the "createColumns" command.') + + @classmethod + def createCaliceColumn(cls): + if 'calice' in cls.getCustomColumns(): + raise Error('Custom Column already exists.') + cls._getTxt("add_custom_column calice 'Calice AI Rating' rating") + + @classmethod + def writeCaliceColumn(cls, bookId, rating): + cls.writeCaliceColumnMultiple({bookId: rating}) + + @classmethod + def writeCaliceColumnMultiple(cls, ratings): + from tqdm.auto import tqdm + cls._requireCaliceColumn() + for bookId in tqdm(ratings): + rating = ratings[bookId] + cls._getTxt('set_custom calice '+str(bookId)+' '+str(int(round(rating)))) + +def calice(G): + ratings = {} + for n in list(G.nodes): + node = G.nodes[n] + if node['t'] in ['book']: + if 'score' in node and node['score'] != None: + ratings[node['calibreID']] = node['score'] + print('Inserting '+str(len(ratings))+' ratings into the calibreDB') + calibreDB.writeCaliceColumnMultiple(ratings) + print('Done.') def remove_html_tags(text): clean = re.compile('<.*?>') @@ -592,7 +648,7 @@ def buildBookGraph(books, darkMode=False, extractKeywords=True, mergeTags=True): else: series = None series_index = None - G.add_node(book['id'], t='book', label=book['title'], title=book['title'], shape='image', image=book['cover'], rating=rating, tags=tags, keywords=keywords, desc=desc, isbn=book['isbn'], files=book['formats'], authors=getAuthors(book), series=series, series_index=series_index) + G.add_node(book['id'], t='book', label=book['title'], title=book['title'], shape='image', image=book['cover'], rating=rating, tags=tags, keywords=keywords, desc=desc, isbn=book['isbn'], files=book['formats'], authors=getAuthors(book), series=series, series_index=series_index, calibreID=book['id']) return G @@ -1363,6 +1419,8 @@ def cliInterface(imgDef=False): p_new = cmds.add_parser('newBooks', description="TODO", aliases=[]) p_new.add_argument('-n', type=int, default=10, help='number of books to recommend') + p_col = cmds.add_parser('calice', description="TODO", aliases=[]) + p_full = cmds.add_parser('full', description="TODO", aliases=[]) args = parser.parse_args() @@ -1438,6 +1496,11 @@ def mainCLI(args): elif args.cmd=="newBooks": bestListT = 'newBook' newBooks(G, books, args.n, mu, std) + elif args.cmd=="calice": + args.no_list = True + args.no_web = True + args.imgs = False + calice(G) else: raise Exception("Bad") @@ -1467,4 +1530,7 @@ def mainCLI(args): weights = loadWeights() if __name__ == "__main__": - cliInterface(imgDef=True) + try: + cliInterface(imgDef=True) + except Error as e: + print("[!] {0}".format(e))