Skip to content

Commit

Permalink
Fix logging and crashes for new users
Browse files Browse the repository at this point in the history
Fix logging and crashes for new users. Add .spec file and build.sh to generate binaries !
  • Loading branch information
casualsnek committed Oct 3, 2022
1 parent 065b994 commit 43affae
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 77 deletions.
9 changes: 9 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
rm -rf ./dist
rm -rf ./build
python3 -m venv venv
source ./venv/bin/activate
pip install pyinstaller
pip install -r requirements.txt
pyinstaller build.spec
chmod +x ./dist/onthespot
1 change: 0 additions & 1 deletion config.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def __init__(self, cfg_path=None):
with open(self.__cfg_path, "w") as cf:
cf.write(json.dumps(self.__template_data))
self.__config = self.__template_data
os.makedirs(os.path.dirname(self.get("dlid_cache")), exist_ok=True)
os.makedirs(self.get("download_root"), exist_ok=True)
os.makedirs(os.path.dirname(self.get("log_file")), exist_ok=True)

Expand Down
80 changes: 38 additions & 42 deletions onthespot.py

Large diffs are not rendered by default.

25 changes: 20 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
pyqt5
librespot
requests
pydub
music_tag
async-timeout==4.0.2
certifi==2022.9.24
charset-normalizer==2.1.1
defusedxml==0.7.1
idna==3.4
ifaddr==0.2.0
librespot==0.0.6
music-tag==0.4.3
mutagen==1.45.1
protobuf==3.20.1
pycryptodomex==3.15.0
pydub==0.25.1
PyOgg==0.6.14a1
PyQt5==5.15.7
PyQt5-Qt5==5.15.2
PyQt5-sip==12.11.0
requests==2.28.1
urllib3==1.26.12
websocket-client==1.4.0
zeroconf==0.39.0
6 changes: 3 additions & 3 deletions runtimedata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
from config import config
import logging
import sys
import sys, os
import logging
from logging.handlers import RotatingFileHandler

Expand All @@ -15,12 +15,12 @@
download_queue = Queue()
thread_pool = []
session_pool = []

loglevel = int(os.environ.get("LOGLEVEL", 20))
def get_logger(name):
logger = logging.getLogger(name)
logger.addHandler(log_handler)
logger.addHandler(stdout_handler)
logger.setLevel(logging.DEBUG)
logger.setLevel(loglevel)
return logger

def handle_exception(exc_type, exc_value, exc_traceback):
Expand Down
20 changes: 10 additions & 10 deletions spotutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def search_by_term(session, search_term, max_results=20)->dict:
"artists": resp.json()["artists"]["items"],
}
if len(results["tracks"]) + len(results["albums"]) + len(results["artists"]) + len(results["playlists"]) == 0:
logger.debug(f"No results for term '{search_term}', max items '{max_results}'")
logger.warning(f"No results for term '{search_term}', max items '{max_results}'")
raise EmptySearchResultException("No result found for search term '{}' ".format(search_term))
else:
return results
Expand Down Expand Up @@ -254,7 +254,7 @@ def download_track(self, session, track_id_str, extra_paths="", prefix=False, pr
else:
if os.path.isfile(filename) and os.path.getsize(filename) and SKIP_EXISTING_FILES:
self.progress.emit([track_id_str, "Already exists", [100, 100]])
logger.debug(f"File already exists, Skipping download for track by id '{track_id_str}'")
logger.info(f"File already exists, Skipping download for track by id '{track_id_str}'")
return False
else:
if track_id_str != scraped_song_id:
Expand All @@ -271,7 +271,7 @@ def download_track(self, session, track_id_str, extra_paths="", prefix=False, pr
with open(filename, 'wb') as file:
while downloaded < total_size:
data = stream.input_stream.stream().read(_CHUNK_SIZE)
logger.info(f"Reading chunk of {_CHUNK_SIZE} bytes for track by id '{track_id_str}'")
logger.debug(f"Reading chunk of {_CHUNK_SIZE} bytes for track by id '{track_id_str}'")
downloaded += len(data)
if len(data) != 0:
file.write(data)
Expand All @@ -292,7 +292,7 @@ def download_track(self, session, track_id_str, extra_paths="", prefix=False, pr
return None
self.progress.emit([track_id_str, None, [downloaded, total_size]])
if not config.get("force_raw"):
logger.debug(f"Force raw is disabled for track by id '{track_id_str}', media converting and tagging will be done !")
logger.warning(f"Force raw is disabled for track by id '{track_id_str}', media converting and tagging will be done !")
self.progress.emit([track_id_str, "Converting", None])
convert_audio_format(filename, quality)
self.progress.emit([track_id_str, "Writing metadata", None])
Expand Down Expand Up @@ -328,7 +328,7 @@ def download_track(self, session, track_id_str, extra_paths="", prefix=False, pr
return False

def download_episode(self, episode_id_str, extra_paths=""):
logger.debug(f"Downloading episode by id '{episode_id_str}'")
logger.info(f"Downloading episode by id '{episode_id_str}'")
ROOT_PODCAST_PATH = os.path.join(config.get("download_root"), "Podcasts")
quality = AudioQuality.HIGH
podcast_name, episode_name = get_episode_info(episode_id_str)
Expand Down Expand Up @@ -369,22 +369,22 @@ def download_episode(self, episode_id_str, extra_paths=""):
self.progress.emit([episode_id_str, "Downloaded", [100, 100]])
return True
else:
logger.debug(f"Downloading failed for episode by id '{episode_id_str}', partial download failed !")
logger.error(f"Downloading failed for episode by id '{episode_id_str}', partial download failed !")
self.progress.emit([episode_id_str, "Failed", [0, 100]])
return False
except:
logger.debug(f"Downloading failed for episode by id '{episode_id_str}', Unexpected Exception: {traceback.format_exc()}")
logger.error(f"Downloading failed for episode by id '{episode_id_str}', Unexpected Exception: {traceback.format_exc()}")
self.progress.emit([episode_id_str, "Failed", [0, 100]])
return False

def run(self):
logger.debug(f"Download worker {self.name} is running ")
logger.info(f"Download worker {self.name} is running ")
while not self.__stop:
item = self.__queue.get()
attempt = 0
if item[0] == "track":
while attempt < config.get("max_retries"):
logger.debug(f"Processing download for track by id '{item[1]}', Attempt: {attempt}")
logger.info(f"Processing download for track by id '{item[1]}', Attempt: {attempt}")
attempt = attempt + 1
self.progress.emit([item[1], "Downloading", None])
status = self.download_track(
Expand All @@ -403,7 +403,7 @@ def run(self):

elif item[0] == "episode":
while attempt < config.get("max_retries"):
logger.debug(f"Processing download for episode by id '{item[1]}', Attempt: {attempt}")
logger.info(f"Processing download for episode by id '{item[1]}', Attempt: {attempt}")
attempt = attempt + 1
self.progress.emit([item[1], "Downloading", None])
status = self.download_episode(
Expand Down
32 changes: 16 additions & 16 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@


def login_user(username: str, password: str, login_data_dir: str)->list:
logger.debug(f"logging in user '{username[:4]}****@****.***'")
logger.info(f"logging in user '{username[:4]}****@****.***'")
# Check the username and if pickled sessionfile exists load the session and append
# Returns: [Success: Bool, Session: Session, PicklePath: str, premium: Bool]
sessobj_pikpath = os.path.join(login_data_dir, username+"_GUZpotifylogin.json")
os.makedirs(os.path.dirname(sessobj_pikpath), exist_ok=True)
if os.path.isfile(sessobj_pikpath):
logger.debug(f"Session file exists for user, attempting to use it '{username[:4]}****@****.***'")
logger.info("Restoring user session")
logger.info(f"Session file exists for user, attempting to use it '{username[:4]}****@****.***'")
logger.debug("Restoring user session")
# Session exists try loading it
try:
config = Session.Configuration.Builder().set_stored_credential_file(sessobj_pikpath).build()
Expand All @@ -27,7 +27,7 @@ def login_user(username: str, password: str, login_data_dir: str)->list:
session = Session.Builder(conf=config).stored_file(sessobj_pikpath).create()
logger.debug("Session created")
premium = True if session.get_user_attribute("type") == "premium" else False
logger.debug(f"Login successful for user '{username[:4]}****@****.***'")
logger.info(f"Login successful for user '{username[:4]}****@****.***'")
return [True, session, sessobj_pikpath, premium]
except (RuntimeError, Session.SpotifyAuthenticationException):
logger.error(f"Failed logging in user '{username[:4]}****@****.***', invalid credentials")
Expand All @@ -36,14 +36,14 @@ def login_user(username: str, password: str, login_data_dir: str)->list:
logger.error(f"Failed to login user '{username[:4]}****@****.***' due to unexpected error: {traceback.format_exc()}")
return [False, None, "", False]
else:
logger.debug(f"Session file does not exist user '{username[:4]}****@****.***', attempting login with uname/pass")
logger.info(f"Session file does not exist user '{username[:4]}****@****.***', attempting login with uname/pass")
try:
logger.debug(f"logging in user '{username[:4]}****@****.***'")
logger.info(f"logging in user '{username[:4]}****@****.***'")
config = Session.Configuration.Builder().set_stored_credential_file(sessobj_pikpath).build()
print("logging in !")
session = Session.Builder(conf=config).user_pass(username, password).create()
premium = True if session.get_user_attribute("type") == "premium" else False
logger.debug(f"Login successful for user '{username[:4]}****@****.***'")
logger.info(f"Login successful for user '{username[:4]}****@****.***'")
return [True, session, sessobj_pikpath, premium]
except (RuntimeError, Session.SpotifyAuthenticationException):
logger.error(f"Failed logging in user '{username[:4]}****@****.***', invalid credentials")
Expand All @@ -54,7 +54,7 @@ def login_user(username: str, password: str, login_data_dir: str)->list:
return [False, None, "", False]

def remove_user(username: str, login_data_dir: str, config)->bool:
logger.debug(f"Removing user '{username[:4]}****@****.***' from saved entries")
logger.info(f"Removing user '{username[:4]}****@****.***' from saved entries")
sessobj_pikpath = os.path.join(login_data_dir, username+"_GUZpotifylogin.json")
if os.path.isfile(sessobj_pikpath):
os.remove(sessobj_pikpath)
Expand All @@ -69,14 +69,14 @@ def remove_user(username: str, login_data_dir: str, config)->bool:
removed = True
break
if removed:
logger.debug(f"Saved Account user '{username[:4]}****@****.***' found and removed")
logger.info(f"Saved Account user '{username[:4]}****@****.***' found and removed")
config.set_("accounts", accounts_copy)
config.update()
return removed


def regex_input_for_urls(search_input):
logger.debug(f"Parsing url '{search_input}'")
logger.info(f"Parsing url '{search_input}'")
track_uri_search = re.search(
r"^spotify:track:(?P<TrackID>[0-9a-zA-Z]{22})$", search_input)
track_url_search = re.search(
Expand Down Expand Up @@ -165,22 +165,22 @@ def regex_input_for_urls(search_input):
def get_url_data(url):
track_id_str, album_id_str, playlist_id_str, episode_id_str, show_id_str, artist_id_str = regex_input_for_urls(url)
if track_id_str is not None:
logger.debug(f"Parse result for url '{url}'-> track, {track_id_str}")
logger.info(f"Parse result for url '{url}'-> track, {track_id_str}")
return "track", track_id_str
elif album_id_str is not None:
logger.debug(f"Parse result for url '{url}'-> album, {album_id_str}")
logger.info(f"Parse result for url '{url}'-> album, {album_id_str}")
return "album", album_id_str
elif playlist_id_str is not None:
logger.debug(f"Parse result for url '{url}'-> playlist, {playlist_id_str}")
logger.info(f"Parse result for url '{url}'-> playlist, {playlist_id_str}")
return "playlist", playlist_id_str
elif episode_id_str is not None:
logger.debug(f"Parse result for url '{url}'-> episode, {episode_id_str}")
logger.info(f"Parse result for url '{url}'-> episode, {episode_id_str}")
return "episode", episode_id_str
elif show_id_str is not None:
logger.debug(f"Parse result for url '{url}'-> podcast, {show_id_str}")
logger.info(f"Parse result for url '{url}'-> podcast, {show_id_str}")
return "podcast", show_id_str
elif artist_id_str is not None:
logger.debug(f"Parse result for url '{url}'-> artist, {artist_id_str}")
logger.info(f"Parse result for url '{url}'-> artist, {artist_id_str}")
return "artist", artist_id_str
else:
logger.error(f"Parse result for url '{url}' failed, invalid spotify url !")
Expand Down

0 comments on commit 43affae

Please sign in to comment.