Easy Book Manager

What is it?

Easy Book Manager is a simple application that allows you to sort and manager your reading list. You can keep track of all your books, when you started reading them, and when you finished reading them. On top of this, you can catagorize your books into 3 catagories: read, reading, and to-read.

These are all color coded for your convincience. Additionally, there is a search functionality which uses natural language processing (NLP) to sort your search results based on how relevent they are to your search




Why I made it

The main reason I made this was because I had a stack of books I needed to sort and I didn't want to make a physical register -because I'd probably lose it. Therefore, I thought that wasting 2 days of my life and making a nice digital one would be a good way to vent my frusteration about life.

In the future, I may update this and add a bit more support by including android as well as syncing across platoforms. This will most likely be done with firebase.





Some more stuff

Speaking of code, this entire code has been created in python, html, css, and javascript. I'm relitively happy with the result, however, it could do with some polish. I also forgot to mention there's a download feature as well, so you can get your entire reading list to share with a friend, teacher, or employer (if they want it for some reason).



Some code

Python (main.py)

# -*- coding: utf-8 -*-
"""
Created on Mon Nov  2 00:40:20 2020

@author: Aditya Rao
"""

import eel
import sqlite3
import datetime as dt
from fuzzywuzzy import process
from fpdf import FPDF

CURRENT_BOOK = None

def open_db():        
    db_ = sqlite3.connect('books.db')
    db = db_.cursor()
    db.execute('''CREATE TABLE IF NOT EXISTS books 
                   (isbn13 VARCHAR(13) PRIMARY KEY, isbn TEXT, title TEXT NOT NULL, 
                   author TEXT NOT NULL, genre TEXT, status TEXT NOT NULL, start_date DATE, end_date DATE)
                   ''')
    return db, db_

eel.init("web")

@eel.expose
def add_book(isbn13, isbn, title, author, genre, status, st_date, ed_date):
    print(isbn13, isbn, title, author, genre, status, st_date, ed_date)
    #try:
    db, db_ = open_db()
    db.execute("INSERT OR REPLACE INTO books (isbn13, isbn, title, author, genre, status, start_date, end_date) 
    VALUES (?, ?, ?, ?, ?, ?, ?, ?);", (isbn13, isbn, title, author, genre, status, st_date, ed_date))

    db_.commit()
    db_.close()
    print('here')
    #    return True
    #except:
    #    print('Failed')
    #    return False

@eel.expose
def get_books(single, query=None, query_type=None, num_results=None):
    print(query_type,'|',query)
    db, db_ = open_db()
    if single:
        data = []
        #df = pd.read_sql_query("SELECT * FROM books WHERE {}={};", db_)
        db.execute("SELECT isbn13,"+query_type+" FROM books")
        psb_books = db.fetchall()

        print(psb_books)

        books = [x[1] for x in psb_books]

        y = process.extract(query, books, limit=int(num_results))
        print(y)

        for i in range(0,len(y)):
            for k in range(0,len(books)):
                if books[k]==y[i][0]:
                    print(books[k], psb_books[k], y[i])
                    db.execute("SELECT * FROM books WHERE isbn13=?", (psb_books[k][0],))
                    data.append(db.fetchall()[0])
        return data

    else:
        #df = pd.read_sql_query("SELECT * FROM books;", db_)
        #x = df.dropna.values.tolist() 
        db.execute("SELECT * FROM books")
        x = db.fetchall()   
        return x

    db_.close() 

@eel.expose
def delete_book():
    global CURRENT_BOOK
    try:
        db, db_ = open_db()
        db_.execute("DELETE FROM books WHERE isbn13=?", (CURRENT_BOOK,))
        db_.commit()

        db_.close()
        return True
    except:
        return False

@eel.expose
def edit_book(status):
    global CURRENT_BOOK

    try:
        db, db_ = open_db()
        db_.execute("UPDATE books SET status=? WHERE isbn13=?", (status, CURRENT_BOOK))
        db_.commit()

        db_.close()
        return True
    except:
        return False

@eel.expose
def info(idx):
    global CURRENT_BOOK
    CURRENT_BOOK = idx

    db, db_ = open_db()

    db.execute("SELECT * FROM books WHERE isbn13=?", (idx,))
    x = db.fetchall()[0]
    return x


months = {1:'Jan',2:'Feb',3:'Mar',4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'}    

@eel.expose
def get_pdf():
    print('downloading...')

    f = open('user_info.txt','r')
    name = f.read().rstrip().split('|')[1]

    db, db_ = open_db()
    #df = pd.read_sql_query("SELECT title, author, start_date, end_date FROM books", db_)
    db.execute("SELECT title, author, end_date FROM books")
    books=db.fetchall()
    pdf = FPDF()
    pdf.add_page()
    pdf.add_font('Century Gothic', '', 'temp/GOTHIC.ttf', uni=True)
    pdf.set_font('Century Gothic', size=16)

    now = dt.datetime.now()

    pdf.cell(200, 10, txt = "{}'s Reading List".format(name), ln = 1, align = 'L')
    pdf.cell(200, 10, txt = "Date: {} {}, {}".format(months[now.month], now.day, now.year), ln = 2, align = 'L')

    #plt.axis('off')
    #plt.axis('tight')
    #pdf.cell(200, 10, txt= 'Title', ln=3, align='L')
    #pdf.cell(200, 10, txt= 'Author', ln=3, align='C')
    #pdf.cell(200, 10, txt= 'Date', ln=3, align='R')

    for i in range(3, len(books)+3):
        pdf.cell(200, 10, txt = "-------------------------------------------------------------------------------------------------------", ln=i, align='C')
        pdf.multi_cell(200, 10, txt=books[i-3][0], align = 'L')
        #pdf.cell(200, 10, txt= '{}'.format(books[i-6][0]), ln=i+1, align='L')
        pdf.cell(200, 10, txt= 'By: {}'.format(books[i-3][1]), ln=i+2, align='L')
        pdf.cell(200, 10, txt= 'Date: {}'.format(books[i-3][2]), ln=i+3, align='L')
    #plt.table(cellText=df.values, colLabels=df.columns, loc='center')
    #plt.savefig('temp/books.png', dpi=500)
    #plt.show()
    #plt.close()

    #pdf.image('temp/books.png', w=500)

    pdf.output(name='DOWNLOADS/Reading_List.pdf').encode('latin-1')
    print("pdf has been created successfully....")
    #os.remove('temp/books.png')

    db_.close()


eel.start("index.html")
            

JavaScript (main.js)

/*Global Initialization*/
/*eslint-env es6*/
/*global eel, document */

function get_books(func){
    if (func==0){
        console.log('here func 0');     
        eel.get_books(false)(set_books);
    } else if (func==1) {
        console.log('here func 1');
        console.log(document.getElementById('query').value);
        console.log(document.getElementById('query-type').value);
        let query=document.getElementById('query').value;
        let query_type=document.getElementById('query-type').value
        let num_results=document.getElementById('num-results').value;
        
        eel.get_books(true, query, query_type, num_results)(set_books);
    }
}

eel.expose(set_books);
function set_books(results){
    var html = '';

    for (let i=0; i
'+results[i][2]+'

By: '+results[i][3]+''; } else if (status==2) { html += ''; } else if (status==3){ html += ''; } } document.getElementById('grid').innerHTML = html; } function add_book(){ let isbn13=document.getElementById('new-isbn13').value; let isbn=document.getElementById('new-isbn').value; let title=document.getElementById('new-title').value; let author=document.getElementById('new-author').value; let genre=document.getElementById('new-genre').value; let status=document.getElementById('new-status-val').value; let st_date = document.getElementById('new-stdate').value; let ed_date = document.getElementById('new-eddate').value; eel.add_book(isbn13, isbn, title, author, genre, status, st_date, ed_date)(); location.href='view-books.html'; } function search(query) { //location.reload(); //document.getElementById('grid').innerHTML=" "; eel.get_books(query, query_type, true)(search_results); } eel.expose(search_results); function search_results(results){ for (i=0; i

Download the program here

Download PROJECT_NAME now!


About the Author

Created by: Aditya Rao

I've done quite a few projects in the past and have started trying to diversify my toolset. I develop primarily in python, however, I do html css and js now aswell. I'm going to start learning C++ in the future. I love hardware and have done some stuff in NASM x86 Assembler. More about me at my website.



License Information

Licensed under Apache Version 2.0, Information availible at https://www.apache.org/licenses/LICENSE-2.0

Copyright 2020 Aditya Rao Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

© Aditya Rao 2020