import requests from rich.console import Console from rich.prompt import Prompt from rich.table import Table from fuzzywuzzy import process from requests.auth import HTTPBasicAuth API_BASE_URL = "https://localhost:3000" # Replace with your actual API base URL console = Console() # Use environment variables or a secure method to store credentials USERNAME = 'admin' PASSWORD = 'library@123' # Replace with your actual password def list_books(): response = requests.get(f"{API_BASE_URL}/api/books-with-images", verify=False) if response.status_code == 200: books = response.json() table = Table(title="Books") table.add_column("ISBN", justify="right", style="cyan", no_wrap=True) table.add_column("Title", style="magenta") table.add_column("Authors", style="green") for book in books: table.add_row(book['isbn'], book['title'], book['authors']) console.print(table) else: console.print("Failed to fetch books.", style="bold red") def add_book(): isbn = Prompt.ask("Enter ISBN") title = Prompt.ask("Enter Title") authors = Prompt.ask("Enter Authors") data = { "isbn": isbn, "title": title, "authors": authors } response = requests.post( f"{API_BASE_URL}/store-book", json=data, verify=False, auth=HTTPBasicAuth(USERNAME, PASSWORD) ) if response.status_code == 200: console.print("Book added successfully.", style="bold green") else: console.print("Failed to add book.", style="bold red") def remove_book(): isbn = Prompt.ask("Enter ISBN of the book to remove") response = requests.delete( f"{API_BASE_URL}/book/{isbn}", verify=False, auth=HTTPBasicAuth(USERNAME, PASSWORD) ) if response.status_code == 200: console.print("Book removed successfully.", style="bold green") else: console.print("Failed to remove book.", style="bold red") def change_book_status(): isbn = Prompt.ask("Enter ISBN of the book to change status") status = Prompt.ask("Enter new status (e.g., Available, Checked Out)") data = {"status": status} response = requests.put( f"{API_BASE_URL}/book/{isbn}", json=data, verify=False, auth=HTTPBasicAuth(USERNAME, PASSWORD) ) if response.status_code == 200: console.print("Book status updated successfully.", style="bold green") else: console.print("Failed to update book status.", style="bold red") def search_books(): query = Prompt.ask("Enter search query") response = requests.get(f"{API_BASE_URL}/api/books-with-images", verify=False) if response.status_code == 200: books = response.json() book_titles = [book['title'] for book in books] matches = process.extract(query, book_titles, limit=5) if matches: table = Table(title="Search Results") table.add_column("ISBN", justify="right", style="cyan", no_wrap=True) table.add_column("Title", style="magenta") table.add_column("Authors", style="green") table.add_column("Score", justify="right", style="yellow") for match in matches: title, score = match book = next(book for book in books if book['title'] == title) table.add_row(book['isbn'], book['title'], book['authors'], str(score)) console.print(table) else: console.print("No matches found.", style="bold red") else: console.print("Failed to fetch books.", style="bold red") def list_books_on_loan(): response = requests.get(f"{API_BASE_URL}/api/books-on-loan", verify=False) if response.status_code == 200: loans = response.json() table = Table(title="Books on Loan") table.add_column("ISBN", justify="right", style="cyan", no_wrap=True) table.add_column("Title", style="magenta") table.add_column("User Name", style="blue") table.add_column("Checkout Date", style="green") table.add_column("Return Date", style="yellow") for loan in loans: table.add_row(loan['isbn'], loan['title'], loan['name'], loan['checkout_date'], loan['return_date']) console.print(table) else: console.print("Failed to fetch books on loan.", style="bold red") def rebuild_book_entries(): isbn = Prompt.ask("Enter ISBN of the book to rebuild") response = requests.get(f"{API_BASE_URL}/book/confirm/{isbn}", verify=False) if response.status_code == 200: book_data = response.json() console.print("Current Book Data from Local Database:", style="bold blue") console.print(f"Title: {book_data['data']['title']}") console.print(f"Authors: {book_data['data']['authors']}") console.print(f"Published Date: {book_data['data'].get('publishedDate', 'N/A')}") console.print(f"Description: {book_data['data'].get('description', 'N/A')}") # Allow the user to select fields to search with console.print("\nSelect fields to search the Google Books API with:") use_title = Prompt.ask("Use Title? (yes/no)", choices=["yes", "no"], default="yes") == "yes" use_authors = Prompt.ask("Use Authors? (yes/no)", choices=["yes", "no"], default="yes") == "yes" use_isbn = Prompt.ask("Use ISBN? (yes/no)", choices=["yes", "no"], default="yes") == "yes" # Build search query based on selected fields query_components = [] if use_title: query_components.append(f'intitle:{book_data["data"]["title"]}') if use_authors: query_components.append(f'inauthor:{book_data["data"]["authors"]}') if use_isbn: query_components.append(f'isbn:{book_data["data"]["isbn"]}') query = '+'.join(query_components) # Query the Google Books API directly google_response = requests.get(f"https://www.googleapis.com/books/v1/volumes?q={query}") if google_response.status_code == 200: google_data = google_response.json() if google_data["totalItems"] > 0: # Take the first result volumes = google_data["items"] console.print("\nMultiple volumes found. Please select one:") for i, item in enumerate(volumes): volume_info = item["volumeInfo"] title = volume_info.get('title', 'N/A') authors = ', '.join(volume_info.get('authors', [])) published_date = volume_info.get('publishedDate', 'N/A') # Limit the length of the title and authors to 32 characters if len(title) > 32: title = title[:29] + '...' if len(authors) > 32: authors = authors[:29] + '...' console.print(f"{i + 1}. Title: {title}, Authors: {authors}, Published Date: {published_date}") selected_index = int(Prompt.ask("Enter the number of the volume you want to select")) - 1 volume_info = volumes[selected_index]["volumeInfo"] console.print("\nBook Data Found from Google Books API:", style="bold green") console.print(f"Title: {volume_info.get('title', 'N/A')}") console.print(f"Authors: {', '.join(volume_info.get('authors', []))}") console.print(f"Published Date: {volume_info.get('publishedDate', 'N/A')}") console.print(f"Description: {volume_info.get('description', 'N/A')}") # isbn (use 13, then 10 if 13 is not present) ISBN: [{'type': 'ISBN_10', 'identifier': '0521274559'}, {'type': 'ISBN_13', 'identifier': '9780521274555'}] isbn = volume_info.get('industryIdentifiers', []) isbn = next((identifier['identifier'] for identifier in isbn if identifier['type'] == 'ISBN_13'), None) if not isbn: isbn = next((identifier['identifier'] for identifier in isbn if identifier['type'] == 'ISBN_10'), None) console.print(f"ISBN: {isbn}") # Ask the user if they want to update the entry update = Prompt.ask("Do you want to update this book entry? (yes/no)", choices=["yes", "no"], default="no") if update == "yes": data = { "title": volume_info.get('title'), "authors": ', '.join(volume_info.get('authors', [])), "publishedDate": volume_info.get('publishedDate'), "description": volume_info.get('description'), "isbn": isbn } update_response = requests.put( f"{API_BASE_URL}/book/{book_data['data']['isbn']}", json=data, verify=False, auth=HTTPBasicAuth(USERNAME, PASSWORD) ) if update_response.status_code == 200: console.print("Book entry updated successfully.", style="bold green") else: console.print("Failed to update book entry.", style="bold red") print(update_response.json()) print(update_response.status_code) else: console.print("No data found on Google Books API.", style="bold red") else: console.print("Failed to fetch data from Google Books API.", style="bold red") else: console.print("Book not found in local database.", style="bold red") def main(): while True: console.print("\n[bold]Admin Console[/bold]") console.print("1. List Books") console.print("2. Add Book") console.print("3. Remove Book") console.print("4. Change Book Status") console.print("5. Search Books") console.print("6. List Books on Loan") console.print("7. Rebuild Book Entries") console.print("8. Exit") choice = Prompt.ask("Choose an option", choices=["1", "2", "3", "4", "5", "6", "7", "8"], default="8") if choice == "1": list_books() elif choice == "2": add_book() elif choice == "3": remove_book() elif choice == "4": change_book_status() elif choice == "5": search_books() elif choice == "6": list_books_on_loan() elif choice == "7": rebuild_book_entries() elif choice == "8": console.print("Exiting...", style="bold yellow") break if __name__ == "__main__": main()