From 683a049818fcd7446be6d1b33af3544ec0e8ed54 Mon Sep 17 00:00:00 2001 From: Mafke-Louise Date: Sat, 8 Jun 2024 14:48:20 +0200 Subject: [PATCH] Fix manually adjusting playstate + minor improvements --- main.py | 21 ++++++------- settings.json | 2 +- src/app.py | 50 +++++++++++++----------------- src/tab.py | 86 ++++++++++++++++++++++----------------------------- 4 files changed, 69 insertions(+), 90 deletions(-) diff --git a/main.py b/main.py index 0d92743..dfbd38d 100644 --- a/main.py +++ b/main.py @@ -9,18 +9,16 @@ def prepare_environment(): - global raw_settings try: raw_settings = json.load(open("settings.json")) except FileNotFoundError: - raw_settings = {"firstRun": True} + raw_settings = {"first_run": True} except json.decoder.JSONDecodeError: Logger.write(message="Invalid settings.json file.", level="ERROR") os.remove("settings.json") exit() - if raw_settings["firstRun"] is True: + if raw_settings["first_run"] is True: with open("settings.json", "w") as settings_file: - # TODO: add system tray icon or cmd prompt selection --> Done! --Nelly Logger.write(message="First run detected.") custom_clientid = input("Use custom ClientId? (yes/no): ") client_id = ( @@ -29,16 +27,17 @@ def prepare_environment(): else input("App | Enter your ClientId (number): ") ) profile = input("App | Enter your Profile Name (Default): ") - refreshRate = input("App | Refresh rate in seconds (number): ") - useTimeLeft = input( + #TODO: Sanitize refresh rate input, will crash if NaN + refresh_rate = input("App | Refresh rate in seconds (number): ") + use_time_left_choice = input( "App | Display time remaining instead of elapsed time? (yes/no): " ) raw_settings = { - "firstRun": False, + "first_run": False, "client_id": client_id, "profile_name": profile or "Default", - "RefreshRate": int(refreshRate) or 1, - "DisplayTimeLeft": useTimeLeft.lower() or "yes", + "refresh_rate": int(refresh_rate) or 1, + "display_time_left": True if use_time_left_choice.lower() == "yes" else False, } if not os.path.exists("./icon.ico"): print("WARNING | Icon not found! downloading now.") @@ -79,8 +78,8 @@ def prepare_environment(): version=__version__, title=__title__, profileName=settings["profile_name"], - refreshRate=settings["RefreshRate"], - useTimeLeft=settings["DisplayTimeLeft"], + refreshRate=settings["refresh_rate"], + useTimeLeft=settings["display_time_left"], ) app.sync() app.run() diff --git a/settings.json b/settings.json index 2d44593..253b9ce 100644 --- a/settings.json +++ b/settings.json @@ -1 +1 @@ -{"firstRun": true, "client_id": "828083725790609459", "profile_name": "Default", "RefreshRate": 1, "DisplayTimeLeft": "yes"} +{"first_run": true, "client_id": "828083725790609459", "profile_name": "Default", "refresh_rate": 1, "display_time_left": true} \ No newline at end of file diff --git a/src/app.py b/src/app.py index e1e6246..7796302 100644 --- a/src/app.py +++ b/src/app.py @@ -45,7 +45,7 @@ def __init__( title: str = None, profileName: str = "Default", refreshRate: int = 1, - useTimeLeft: str = "yes", + useTimeLeft: bool = True, ): os.system("title " + title + " v" + version) Logger.write(message=f"{title} v{version}", level="INFO", origin=self) @@ -139,10 +139,7 @@ def on_quit_callback(self, systray): Logger.write(message="stopped.", origin=self) def run(self) -> None: - global lastUpdated - global compareTab - compareTab = {"title": "", "artist": "", "artwork": "", "lastTime": 0} - lastUpdated = 1 + last_updated_time: int = 1 try: menu_options = (("Hide/Show Console", None, self.hideWindow), ("Force Update", None, self.update)) self.systray = SysTrayIcon("./icon.ico", "YT Music RPC", menu_options, on_quit=self.on_quit_callback) @@ -177,6 +174,7 @@ def run(self) -> None: time.sleep(3) while self.connected: self.silent = False + update_unix_time: float = time.time() tabs = self.update_tabs() tab = [tab for tab in tabs if tab.playing] or [ tab for tab in tabs if tab.pause @@ -202,36 +200,36 @@ def run(self) -> None: Logger.write(message="Ad detected.", origin=self) time.sleep(DISCORD_STATUS_LIMIT) continue - compareTab["title"] = tab.title - compareTab["artwork"] = tab.artwork - compareTab["artist"] = tab.artist - compareTab["lastTime"] = tab.start + if self.last_tab and self.last_tab == tab: # fixed problem where it didn't detect the page change (appears to happen sometimes in playlists) - self.silent = self.last_tab.end + self.refreshRate < time.time() + delta_estimated_end_times = abs(self.last_tab.projected_end_time - tab.projected_end_time) + playstate_manually_adjusted = delta_estimated_end_times > 1 + self.silent = self.last_tab.projected_end_time + self.refreshRate < update_unix_time or playstate_manually_adjusted if ( - compareTab["title"] == self.last_tab.title - and compareTab["artist"] == self.last_tab.artist - and self.last_tab.end + self.refreshRate > time.time() + tab.title == self.last_tab.title + and tab.artist == self.last_tab.artist + and tab.projected_end_time + self.refreshRate > update_unix_time + and not playstate_manually_adjusted and not tab.pause ): time.sleep(self.refreshRate) continue + if tab.pause: self.silent = True - if self.last_tab: - if self.last_tab.start == compareTab["lastTime"]: - time.sleep(self.refreshRate) - continue + if self.last_tab and self.last_tab.start_time == tab.start_time: + time.sleep(self.refreshRate) + continue - if lastUpdated + 15 > time.time(): - remaining = time.time() - (lastUpdated + 15) + if last_updated_time + 15 > update_unix_time: + remaining = update_unix_time - (last_updated_time + 15) if remaining < 0: remaining = 1 time.sleep(remaining) continue - lastUpdated = time.time() + last_updated_time = update_unix_time self.last_tab = tab Logger.write( @@ -239,11 +237,6 @@ def run(self) -> None: origin=self, silent=self.silent ) - - def useTimeLeft(answer): - if answer == "yes": - return self.last_tab.end + self.refreshRate - return None if not self.silent: try: @@ -272,9 +265,8 @@ def useTimeLeft(answer): "url": "https://manucabral.github.io/YoutubeMusicRPC/", }, ], - # TODO: enhance time left -> Done! --Nelly - start=self.last_tab.start, - end=useTimeLeft(self.useTimeLeft), + start=self.last_tab.start_time, + end=self.last_tab.projected_end_time + self.refreshRate if self.useTimeLeft else None ) # time.sleep(self.refreshRate) except Exception as exc: @@ -285,4 +277,4 @@ def useTimeLeft(answer): message="Please close all browser instances and try again. Also, close Youtube Music Desktop App if you are using it.", level="WARN", origin=self, - ) + ) \ No newline at end of file diff --git a/src/tab.py b/src/tab.py index 22a2977..df88f08 100644 --- a/src/tab.py +++ b/src/tab.py @@ -24,48 +24,34 @@ def connect(self): self.connected = True def sync(self): - global LastTime - LastTime = 4 - - def filterZeros(string: str): - if string.startswith("0") and len(string) > 1: - return int(string[1:]) - return int(string) - - def checkForUpdate(eclapsedTime): - if returnTimeInUnix(eclapsedTime) == LastTime: - startUnixTime = time.time() - return startUnixTime - return - - def returnTimeInUnix(dict: dict): - global TimeInUnix - global timeType - timeType = "Minutes" - TimeInUnix = 0 - if len(dict) == 3: - timeType = "Hours" - elif len(dict) == 2: - timeType = "Minutes" - - if timeType == "Hours": - for x in range(0, len(dict), 1): - filteredNumber = filterZeros(dict[x]) - if x == 0: - TimeInUnix = TimeInUnix + (filteredNumber * 3600) - elif x == 1: - TimeInUnix = TimeInUnix + (filteredNumber * 60) - elif x == 2: - TimeInUnix = TimeInUnix + filteredNumber - return TimeInUnix - if timeType == "Minutes": - for x in range(0, len(dict), 1): - filteredNumber = filterZeros(dict[x]) - if x == 0: - TimeInUnix = TimeInUnix + (filteredNumber * 60) - elif x == 1: - TimeInUnix = TimeInUnix + filteredNumber - return TimeInUnix + def remove_preceding_zero(int_as_string: str) -> int: + if int_as_string.startswith("0") and len(int_as_string) > 1: + return int(int_as_string[1:]) + return int(int_as_string) + + def filter_time_result_to_seconds(time_result: list[str]) -> int: + total_seconds: int = 0 + time_length : int = len(time_result) + if time_length > 3: + return 0 + includes_hours = time_length == 3 + if includes_hours: + for index, time_value in enumerate(time_result): + cleaned_time = remove_preceding_zero(time_value) + if(index == 0): + total_seconds += (cleaned_time * 3600) + elif(index == 1): + total_seconds += (cleaned_time * 60) + elif(index == 2 and includes_hours): + total_seconds += cleaned_time + else: + for index, time_value in enumerate(time_result): + cleaned_time = remove_preceding_zero(time_value) + if(index == 0): + total_seconds += (cleaned_time * 60) + elif(index == 1): + total_seconds += cleaned_time + return total_seconds def filter_metadata(metadata: str): """Adds empty char to 1 len metadata as PyPresence does not allow 1 len""" @@ -97,6 +83,7 @@ def filter_metadata(metadata: str): if not self.metadata: self.pause = False return + retrieval_time = time.time() self.playing = self.metadata["playbackState"] == "playing" self.pause = self.metadata["playbackState"] == "paused" self.ad = self.metadata["advertisement"] @@ -105,13 +92,14 @@ def filter_metadata(metadata: str): self.artwork = self.metadata["artwork"] if self.metadata["artwork"] else "logo" times = self.metadata["time"].split(" / ") - eclapsedTime = times[0].split(":") - timeLeft = times[1].split(":") - startUnixTime = time.time() - returnTimeInUnix(eclapsedTime) - EndUnixTime = time.time() + returnTimeInUnix(timeLeft) - LastTime = math.trunc(returnTimeInUnix(eclapsedTime)) - self.start = math.trunc(startUnixTime) - self.end = math.trunc(EndUnixTime - returnTimeInUnix(eclapsedTime)) + elapsed_seconds = filter_time_result_to_seconds(times[0].split(":")) + total_seconds = filter_time_result_to_seconds(times[1].split(":")) + + start_time_unix = retrieval_time - elapsed_seconds + self.start_time = math.trunc(start_time_unix) + + end_time_unix = retrieval_time + total_seconds # Would be end time if just started to play now + self.projected_end_time = math.trunc(end_time_unix - elapsed_seconds) def close(self): if self.connected: