From 5772edf88a619440ab3aff28a4bb99b4cc0c6827 Mon Sep 17 00:00:00 2001 From: Kristy Fournier Date: Wed, 21 Jan 2026 16:49:04 -0500 Subject: [PATCH] Using dotenv, refactored some stuff, made making database slightly faster with art --- Server/databaseGenerator.py | 28 +++++++++++++++------------- Server/example.env | 3 +++ Server/webbyBits.py | 21 ++++++++++----------- wishlist.md | 4 ++-- 4 files changed, 30 insertions(+), 26 deletions(-) create mode 100644 Server/example.env diff --git a/Server/databaseGenerator.py b/Server/databaseGenerator.py index e758efb..99e2fe5 100644 --- a/Server/databaseGenerator.py +++ b/Server/databaseGenerator.py @@ -4,26 +4,27 @@ from mutagen.mp3 import MP3 import mutagen.flac import mutagen.wave import sqlite3 as sql -import requests, ast, time, math, argparse +import requests, ast, time, math, argparse, dotenv loading = ["-","\\","|","/"] parser=argparse.ArgumentParser(description="Options for the generation of the song database") -parser.add_argument('-k','--apikey', help='String: LastFM api key', default="") +# parser.add_argument('-k','--apikey', help='String: LastFM api key', default="") parser.add_argument('-m', '--mode', help='new/update: Remake database or update current', default= "update") parser.add_argument('-a', '--art', help="True/False: Add art to the database using LastFm (takes minimum 0.25s per song)", default="True") parser.add_argument('-d','--directory',help="Directory of the song files", default="./sound/") args = parser.parse_args() -apikeylastfm = args.apikey +dotenv.load_dotenv() +apikeylastfm = os.getenv("API_KEY") +soundLocation = os.getenv("DIRECTORY") +# apikeylastfm = args.apikey if args.directory[-1] == "/" or args.directory[-1] == "\\": soundLocation = args.directory elif "/" in args.directory: soundLocation = args.directory + "/" else: soundLocation = args.directory + "\\" -# if you want to set the api key/sound directory permenantly for your setup just uncomment the next line -# apikeylastfm = "KeyHere" -# soundLocation = "directoryHere" + songFiles = os.listdir(soundLocation) fileOfDB = sql.connect("songDatabase.db") songDatabase = fileOfDB.cursor() @@ -54,12 +55,12 @@ elif args.mode.lower()=="new": else: raise ValueError("Must be \"new\" or \"update\"") -if args.art.lower() == "true" and not(args.apikey == ""): - x = len(songFiles)*0.25 - if x > 60: - print("ETA "+ str(x/60) + " minutes") +if args.art.lower() == "true" and not(apikeylastfm == ""): + eta = len(songFiles)*0.25 + if eta > 60: + print(f"ETA {eta/60:.2f} minutes") else: - print("ETA "+ str(x) + " seconds") + print(f"ETA {eta} seconds") # will be used soon validFormats = ["mp3","flac","wav"] @@ -103,7 +104,8 @@ for i in songFiles: #if the file is not formatted with an underscore or hyphen, the title is the file name title = i artist = None - if args.art.lower() == "true" and not(args.apikey == ""): + if args.art.lower() == "true" and not(apikeylastfm == "") and artist: + # and artist just means anything that only has the x.mp3 title won't bother to check since it'll never exist on last fm try: # get the images from last fm, try 2 different sizes image = ast.literal_eval(requests.post(url="http://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key="+apikeylastfm+"&artist="+artist+"&track="+title+"&format=json").text)["track"]["album"]["image"][2]["#text"] @@ -111,7 +113,7 @@ for i in songFiles: image = ast.literal_eval(requests.post(url="http://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key="+apikeylastfm+"&artist="+artist+"&track="+title+"&format=json").text)["track"]["album"]["image"][1]["#text"] if image == "": image = None - time.sleep(0.25) + time.sleep(0.01) except: image=None else: diff --git a/Server/example.env b/Server/example.env new file mode 100644 index 0000000..98fc312 --- /dev/null +++ b/Server/example.env @@ -0,0 +1,3 @@ +API_KEY= +DIRECTORY=./sound +SERVER_PORT=19054 \ No newline at end of file diff --git a/Server/webbyBits.py b/Server/webbyBits.py index 795ff4e..7e684b6 100644 --- a/Server/webbyBits.py +++ b/Server/webbyBits.py @@ -2,14 +2,14 @@ from flask import Flask from flask import request from flask_cors import CORS import sqlite3 as sql -import vlc,threading,time,random, argparse +import vlc,threading,time,random,argparse,dotenv,os # Argparse Stuff parser=argparse.ArgumentParser(description="Options for the Webby Bits") -parser.add_argument('-p','--port',help="Port to host on, not the same as the web (client) port",default='19054') +# parser.add_argument('-p','--port',help="Port to host on, not the same as the web (client) port",default='19054') parser.add_argument('-a','--admin',help="Add an admin password to be used in the client. DO NOT use a password you use elsewhere",default="") args = parser.parse_args() - -portTheUserPicked=args.port +dotenv.load_dotenv() +portTheUserPicked=os.getenv("SERVER_PORT") # Just a note that the return code "401" as of now is used to mean "you don't have the password" # This is not great design, and the whole "returning string codes" thing is something to add to the todo list # I mean returning 200 when no return is necesary i think is fine but we'll see @@ -20,11 +20,11 @@ if not(ADMIN_PASS): # True = everyone, False = admin only. Change in client while in use. # play-pause,skip,addsong,partymode,volume in order controlPerms = { - "PP":True, #done - "SK":True, #done - "AS":True, #done - "PM":True, #done - "VOL":True #done + "PP":True, + "SK":True, + "AS":True, + "PM":True, + "VOL":True } fileofDB = sql.connect("songDatabase.db") @@ -150,8 +150,7 @@ def settingsControl(): return ERR_NO_ADMIN elif recieveData["setting"] == "getsettings": # probably should have made this a different request type or something but it works - x = {"partymode":partyMode,"volume":player.audio_get_volume(),"admin":controlPerms} - return x + return {"partymode":partyMode,"volume":player.audio_get_volume(),"admin":controlPerms} else: return "400" diff --git a/wishlist.md b/wishlist.md index d745d7e..1b20f9b 100644 --- a/wishlist.md +++ b/wishlist.md @@ -7,8 +7,8 @@ - [ ] Verify all if-else sequences are correct and not redundant - [x] Remove old comments - [ ] Security Updates - - [ ] `.env` file for the api keys and other runtime info to be set, rather than in the `.py` files - - [ ] Hashing rather than plaintext sending (that way at least the password text itself stays private) + - [x] `.env` file for the api keys and other runtime info to be set, rather than in the `.py` files + - [ ] Hashing rather than plaintext sending passwords (that way at least the password text itself isn't transmitted over the network) - [ ] Actually use SSL, for posting (CORS seems like an issue) - [ ] Accessibility - [ ] Better use of semantic HTML tags