From dd1ec752a8cd7a55ec2e6db1f2b1c0ac62a3ce74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rnar=20Kaarevik?= Date: Sat, 1 Apr 2023 21:08:08 +0200 Subject: [PATCH] added modified data fetcher based on the implementation of adrlau, as well as update to the todo in the readme --- README.md | 62 +++++++++++++ data_fetcher/data_fetcher.py | 163 +++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 data_fetcher/data_fetcher.py diff --git a/README.md b/README.md index c7739cc..79fc202 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,19 @@ # Worblehat +More information on + ## 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: + +* + * 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 diff --git a/data_fetcher/data_fetcher.py b/data_fetcher/data_fetcher.py new file mode 100644 index 0000000..eb36cfd --- /dev/null +++ b/data_fetcher/data_fetcher.py @@ -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 +