added modified data fetcher based on the implementation of adrlau, as well as update to the todo in the readme

This commit is contained in:
Bjornar Orjansen Kaarevik 2023-04-01 21:08:08 +02:00
parent 55d2064f0d
commit dd1ec752a8
2 changed files with 225 additions and 0 deletions

View File

@ -1,11 +1,19 @@
# Worblehat
More information on <https://www.pvv.ntnu.no/pvv/Bokhyllen/Worblehat/>
## What?
Worblehat is a simple library management system written specifically for Programvareverkstedet.
## Why?
Programvareverkstedet is a small community with many books and games. A simple web platform is needed to manage the library. We need to know who owns each item, if we can loan it out and where it is.
Programvareverkstedet har en rekke bøker, og en konstant tilstrøm av nye.
Teoretisk sett skal disse ryddes og kategoriseres jevntlig, men da dette ikke gjøres ofte nok kan det være et varig strev å finne ut hvor bøker står til enhver tid.
Styret har derfor tatt initiativ til å opprette et biblioteksystem for å systematisere bøkene.
Prosjektet har fått navn Worblehat etter en bibliotekar i Terry Pratchetts discworld serie.
Worblehatt har vært påbegynnt flere ganger opp gjennom historien uten å komme i noen form for funksjonell tilstand enda.
## How?
The entire application is written in flask.
@ -39,3 +47,57 @@ The resulting web page is rendered on the server by jinja templates in flask.
### Python packages
* See [requirements.txt](requirements.txt)
## TODO
### Funksjonalitet
* Høy prioritet:
* Bokdatabase med alle PVVs bøker må lages
* Bokdatabasebyggingsverktøy for å bygge bokdatabasen (sjekker online ISBN-database for informasjon om boken)
* Utlånsmuligheter på PVVs lokaler for eksempel gjennom Dibbler sin strekkodescanner
* Lav prioritet:
* Utlånsmuligheter gjennom nettportal på PVVs nettsider
* Søkemuligheter gjennom en nettportal på PVVs nettsider
* Til diskusjon:
* Skal Worblehat kjøre i en annen tty-instans på Dibbler sin Raspberry Pi ELLER skal man skifte mellom Worblehat-mode og Dibbler-mode i samme tty?
### Ellers
* Legge til håndtering av flere ISBN-databaser
* Legge til batch-prosessering av ISBN-er
* For å kunne scanne en hel hylle og så dumpe hele listen av ISBN-er til databasene vi henter fra
* Lage en database vi kan lagre _våre_ bøker i
* Finne en måte å håndtere kollisjon dersom vi har flere eksemplarer av samme bok
* Klistremerke med eksemplar-nummer ved siden av ISBN, kanskje
## Tilfeldig
En relativt stor online ISBN-database er lokalisert:
* <https://openlibrary.org//>
* Eksporterer json-objekter med alle mulig slags rare felter
* google books databasen er også mulig å benytte.
* Kanskje ISBNdb.com er mulig å benytte også.
Noen viktige felter til databasen er som følger:
* ISBN (faktisk eller pvv generert)
* Forfatter
* Tittel
* Utgivelsesår
* Antall sider
* Sjanger
* Språk
* Om boken er utlånbar
* Bruker som har lånt boken
* Dato på når boken ble lånt ut
Prosedyre for bokdatabasebygging:
* Systematisk arbeid, hylle for hylle
* Tre bunker: "ikke scannet", "scannet" og "manuell innlegging"
* Scanning sjekker live om info kan hentes fra online database(r)
* Dersom finnes: legg i "scannet", ellers legg i "manuell innlegging"
* Legg inn manuelle bøker
* Sett tilbake i hyllen og fortsett til neste

View File

@ -0,0 +1,163 @@
# A simple script to fetch bookdata from multiple sources to the library format.
# Felter hver bok bør ha: (pr. 01.04.2023)
# ISBN
# Forfatter
# Tittel
# Utgivelsesår
# Antall sider
# Sjanger
# Språk
# Bruker som har lånt boken
# Dato på når boken ble lånt ut
import requests
import json
def get_isbn():
# TODO: validate ISBN using checksums
# TODO: wrap in a loop until either ISBN is valid or user quits
# isbn = 9780135166307 #input gir ett isbn 10 eller 13 nummer # kaster en error.
# isbn = "0801859034" #input gir ett isbn 10 eller 13 nummer
isbn = input("Scan a book or add manually: ") # input gir ett isbn 10 eller 13 nummer
if (len(isbn) == 10 or len(isbn) == 13):
return isbn
else:
return None
def get_from_api(isbn) -> dict:
try:
json_input = json.loads(requests.get("https://openlibrary.org/isbn/"+str(isbn)+".json").text)
except:
return f"Error fetching data for: {isbn}" # TODO: add more databases for fetching info from
try:
authors = json_input.get("authors")
for i in range(len(authors)):
authors[i] = json.loads(requests.get("https://openlibrary.org"+str(authors[i].get("key"))+".json").text).get("name") #henter navn fra api
authors = list(set(authors))
title = json_input.get("title")
publish_date = json_input.get("publish_date")
number_of_pages = json_input.get("number_of_pages")
languages = json_input.get("languages")
for i in range(len(languages)):
languages[i] = json.loads(requests.get("https://openlibrary.org"+str(languages[i].get("key"))+".json").text).get("name")
book_data = {
"isbn": isbn,
"authors": authors,
"title": title,
"publishDate": publish_date,
"numberOfPages": number_of_pages,
"languages": languages,
}
return book_data
except:
return f"Error processing data for {isbn}"
def push_to_database(book_info, db_file = "book_info.dat") -> None:
print(f"Pushing to database: Writing to file {db_file}") # TODO: actually connect to our database and push there
f = open(db_file, "w")
json.dump(book_info, f)
f.close()
def validate_book_info_with_user(book_info) -> bool:
"""
Takes a book_info dictionary and asks the user to update fields until they're satisfied with the information.
Updates the inputted dictionary directly.
Input:
* book_info: dict holding fields of book information
Returns:
* bool: True if book is now valid, false if something went wrong
"""
print("Is the following information correct?")
print(book_info)
answer = input("y/n: ")
if answer == "n":
print("What is wrong?")
incorrrect_category = input("""
1. Authors
2. ...
3. ...
q. Quit (done/continue)
""")
is_corrected = False
while not is_corrected:
if incorrrect_category == "1":
authors = input("Input correct authors separated by ',': ")
#TODO: actually put the authors into the book info json thing
elif incorrrect_category =="q":
is_corrected = True
else:
print("No valid option supplied.")
return True # Book has been corrected and is (presumably) valid
elif answer == "y":
return True # Book information is valid
else:
return False # Something went wrong
def add_book_location(book_info) -> None:
"""
Prompts the user for which bookcase and shelf the book came from and adds them to the book_info dictionary.
Inputs:
* book_info: dict holding the book information
Returns:
* None: the book_info dict is updated diretly
"""
print("Where is the book located?")
bookcase = input("Bookcase: ")
shelf = input("Shelf: ")
book_info["bookcase"] = bookcase
book_info["shelf"] = shelf
if __name__ == '__main__':
is_running = True
while is_running:
# Asking user for ISBN and fetching data online
isbn = get_isbn()
if isbn is not None:
book_info = get_from_api(isbn)
print(f"Fetched: {book_info}")
else:
book_info = {}
print("Error: Inputted ISBN was invalid.")
# Adding physical location (case, shelf) to the book
add_book_location(book_info)
# Ensuring the user is satisfied with the information
book_is_correct = validate_book_info_with_user(book_info)
# Pushing to the database to commit the valid book
if book_is_correct:
print("Should we push this book to the database?")
push_answer = input("y/n: ")
if push_answer == "y":
push_to_database(book_info)
else:
pass
else:
print("Error: Book was not corrected properly, we might try again.")
# Moving on to the next book which should be added to the library
print("Should we continue?")
cont_answer = input("y/n: ")
if cont_answer == "y":
is_running = True
else:
is_running = False