From e3881f12cc9c15e7af51fc8630c4914ee3ebe111 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 14 May 2024 20:00:43 +0200 Subject: [PATCH 001/122] Patch for Twitch API changes 2024/5 and tweaks --- channel.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ constants.py | 12 ++++++++++++ main.py | 4 ++-- manual.txt | 9 ++++++++- run_dev.bat | 1 + 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/channel.py b/channel.py index 0550aa15..fdf1a4e4 100644 --- a/channel.py +++ b/channel.py @@ -377,6 +377,58 @@ def _payload(self) -> JsonType: return {"data": (b64encode(json_minify(payload).encode("utf8"))).decode("utf8")} async def send_watch(self) -> bool: + #------------------------------------------------- + # FIX 2024/5 + # | + # v + try: + response: JsonType = await self._twitch.gql_request( + GQL_OPERATIONS["PlaybackAccessToken"].with_variables({"login": self._login}) + ) + except MinerException as exc: + raise MinerException(f"Channel: {self._login}") from exc + signature: JsonType | None = response["data"]['streamPlaybackAccessToken']["signature"] + value: JsonType | None = response["data"]['streamPlaybackAccessToken']["value"] + if not signature or not value: + return None + + RequestBroadcastQualitiesURL = f"https://usher.ttvnw.net/api/channel/hls/{self._login}.m3u8?sig={signature}&token={value}" + + try: + async with self._twitch.request( # Gets list of streams + "GET", RequestBroadcastQualitiesURL + ) as response1: + BroadcastQualities = await response1.text() + except RequestException: + return False + + LowestQualityBroadcastURL = BroadcastQualities.split("\n")[-1] # Just takes the last line, this should probably be handled better in the future + print(f"\n \n url_broadcast:{LowestQualityBroadcastURL} \n") + + try: + async with self._twitch.request( # Gets actual streams + "GET", LowestQualityBroadcastURL + ) as response2: + StreamURLList = await response2.text() + print(f"StreamURLList: {StreamURLList}") + print(f"response status 200 {response2.status == 200}") + except RequestException: + return False + splitURL = StreamURLList.split("\n") + print(f" \n \n StreamURLList.split: \n {splitURL} \n") + StreamLowestQualityURL = StreamURLList.split("\n")[-2] # For whatever reason this includes a blank line at the end, this should probably be handled better in the future + print(f" \n \n url_stream: {StreamLowestQualityURL} \n") + + try: + async with self._twitch.request( # Downloads the stream + "GET", StreamLowestQualityURL + ) as response3: # I lied, well idk, but this code doesn't listen for the actual video data + return response3.status == 200 + except RequestException: + return False + + # FIX 2024/5 END + #------------------------------------------------- """ This uses the encoded payload on spade url to simulate watching the stream. Optimally, send every 60 seconds to advance drops. diff --git a/constants.py b/constants.py index bad23184..dcde07ab 100644 --- a/constants.py +++ b/constants.py @@ -238,6 +238,18 @@ def with_variables(self, variables: JsonType) -> GQLOperation: GQL_OPERATIONS: dict[str, GQLOperation] = { + # retuns PlaybackAccessToken_Template, for fix 2024/5 + "PlaybackAccessToken": GQLOperation( + "PlaybackAccessToken", + "3093517e37e4f4cb48906155bcd894150aef92617939236d2508f3375ab732ce", #no idea what this does, was: a5f2e34d626a9f4f5c0204f910bab2194948a9502089be558bb6e779a9e1b3d2 + variables={ + "isLive": True, + "login": "carbinecarlito", + "isVod": False, + "vodID": "", + "playerType": "site" + }, + ), # returns stream information for a particular channel "GetStreamInfo": GQLOperation( "VideoPlayerStreamInfoOverlayChannel", diff --git a/main.py b/main.py index f87c60d9..1865b8aa 100644 --- a/main.py +++ b/main.py @@ -105,10 +105,10 @@ def debug_gql(self) -> int: parser.add_argument("--log", action="store_true") # undocumented debug args parser.add_argument( - "--debug-ws", dest="_debug_ws", action="store_true", help=argparse.SUPPRESS + "--debug-ws", dest="_debug_ws", action="store_true" ) parser.add_argument( - "--debug-gql", dest="_debug_gql", action="store_true", help=argparse.SUPPRESS + "--debug-gql", dest="_debug_gql", action="store_true" ) args = parser.parse_args(namespace=ParsedArgs()) # load settings diff --git a/manual.txt b/manual.txt index 7fefdbfa..0a9805fe 100644 --- a/manual.txt +++ b/manual.txt @@ -12,8 +12,15 @@ Available command line arguments: • --log Enables logging of runtime information into a 'log.txt' file. Verbosity level of this logging matches the level set by `-v`. + • --version - Show application version information + Show application version information and exits +• --debug-gql + Show GQL debug info +• --debug-ws + Show WS debug info +• --help, -h + Shows help prompt and exits Note: Additional settings are available within the application GUI. diff --git a/run_dev.bat b/run_dev.bat index 8652562c..519f3b01 100644 --- a/run_dev.bat +++ b/run_dev.bat @@ -3,6 +3,7 @@ cls set dirpath=%~dp0 if "%dirpath:~-1%" == "\" set dirpath=%dirpath:~0,-1% set /p "choice=Start with a console? (y/n) " +if /i "%choice%"=="" set "choice=y" if "%choice%"=="y" ( set "exepath=%dirpath%\env\scripts\python" ) else ( From f143daeb39543d877cc938f7eea57e2e2f2215cf Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 14 May 2024 20:22:25 +0200 Subject: [PATCH 002/122] further cleanup and added a comment --- channel.py | 11 +++-------- run_dev.bat | 4 +++- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/channel.py b/channel.py index fdf1a4e4..760d431d 100644 --- a/channel.py +++ b/channel.py @@ -382,7 +382,7 @@ async def send_watch(self) -> bool: # | # v try: - response: JsonType = await self._twitch.gql_request( + response: JsonType = await self._twitch.gql_request( # Gets signature and value GQL_OPERATIONS["PlaybackAccessToken"].with_variables({"login": self._login}) ) except MinerException as exc: @@ -402,22 +402,17 @@ async def send_watch(self) -> bool: except RequestException: return False - LowestQualityBroadcastURL = BroadcastQualities.split("\n")[-1] # Just takes the last line, this should probably be handled better in the future - print(f"\n \n url_broadcast:{LowestQualityBroadcastURL} \n") + LowestQualityBroadcastURL = BroadcastQualities.split("\n")[-1] # Just takes the last line, this should probably be handled better in the future try: async with self._twitch.request( # Gets actual streams "GET", LowestQualityBroadcastURL ) as response2: StreamURLList = await response2.text() - print(f"StreamURLList: {StreamURLList}") - print(f"response status 200 {response2.status == 200}") except RequestException: return False - splitURL = StreamURLList.split("\n") - print(f" \n \n StreamURLList.split: \n {splitURL} \n") + StreamLowestQualityURL = StreamURLList.split("\n")[-2] # For whatever reason this includes a blank line at the end, this should probably be handled better in the future - print(f" \n \n url_stream: {StreamLowestQualityURL} \n") try: async with self._twitch.request( # Downloads the stream diff --git a/run_dev.bat b/run_dev.bat index 519f3b01..171f285d 100644 --- a/run_dev.bat +++ b/run_dev.bat @@ -3,10 +3,12 @@ cls set dirpath=%~dp0 if "%dirpath:~-1%" == "\" set dirpath=%dirpath:~0,-1% set /p "choice=Start with a console? (y/n) " -if /i "%choice%"=="" set "choice=y" if "%choice%"=="y" ( set "exepath=%dirpath%\env\scripts\python" ) else ( + if "%choice%"=="" ( + set "exepath=%dirpath%\env\scripts\python" + ) set "exepath=%dirpath%\env\scripts\pythonw" ) start "TwitchDropsMiner" "%exepath%" "%dirpath%\main.py" From 62ce0c62db7041a22826a427294351c6dd444000 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 14 May 2024 20:24:29 +0200 Subject: [PATCH 003/122] updated manual.txt --- manual.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manual.txt b/manual.txt index 0a9805fe..d74b5d40 100644 --- a/manual.txt +++ b/manual.txt @@ -14,13 +14,13 @@ Available command line arguments: matches the level set by `-v`. • --version - Show application version information and exits + Show application version information and exit • --debug-gql Show GQL debug info • --debug-ws Show WS debug info • --help, -h - Shows help prompt and exits + Show help prompt and exit Note: Additional settings are available within the application GUI. From 43609193efdde70a12916b8d220ad4e748fb5cfc Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 14 May 2024 20:25:50 +0200 Subject: [PATCH 004/122] removed unnecessary comment --- constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.py b/constants.py index dcde07ab..f91f3f43 100644 --- a/constants.py +++ b/constants.py @@ -241,7 +241,7 @@ def with_variables(self, variables: JsonType) -> GQLOperation: # retuns PlaybackAccessToken_Template, for fix 2024/5 "PlaybackAccessToken": GQLOperation( "PlaybackAccessToken", - "3093517e37e4f4cb48906155bcd894150aef92617939236d2508f3375ab732ce", #no idea what this does, was: a5f2e34d626a9f4f5c0204f910bab2194948a9502089be558bb6e779a9e1b3d2 + "3093517e37e4f4cb48906155bcd894150aef92617939236d2508f3375ab732ce", variables={ "isLive": True, "login": "carbinecarlito", From efad885a156902660c74fa77c0a1e7123db21ff1 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 14 May 2024 22:44:51 +0200 Subject: [PATCH 005/122] fixed run_dev.bat --- run_dev.bat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/run_dev.bat b/run_dev.bat index 171f285d..0f183668 100644 --- a/run_dev.bat +++ b/run_dev.bat @@ -8,7 +8,8 @@ if "%choice%"=="y" ( ) else ( if "%choice%"=="" ( set "exepath=%dirpath%\env\scripts\python" + ) else ( + set "exepath=%dirpath%\env\scripts\pythonw" ) - set "exepath=%dirpath%\env\scripts\pythonw" ) start "TwitchDropsMiner" "%exepath%" "%dirpath%\main.py" From 59df728e6212d44a95bb71bbb260240f429ed1b7 Mon Sep 17 00:00:00 2001 From: Windows200000 <72623832+Windows200000@users.noreply.github.com> Date: Tue, 14 May 2024 23:36:56 +0200 Subject: [PATCH 006/122] Update constants.py Co-authored-by: DevilXD <4180725+DevilXD@users.noreply.github.com> --- constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.py b/constants.py index f91f3f43..4d8e5581 100644 --- a/constants.py +++ b/constants.py @@ -244,7 +244,7 @@ def with_variables(self, variables: JsonType) -> GQLOperation: "3093517e37e4f4cb48906155bcd894150aef92617939236d2508f3375ab732ce", variables={ "isLive": True, - "login": "carbinecarlito", + "login": "...", "isVod": False, "vodID": "", "playerType": "site" From c11af9b7430458c79cb5a23bc48bb38b28d8930c Mon Sep 17 00:00:00 2001 From: Windows200000 <72623832+Windows200000@users.noreply.github.com> Date: Tue, 14 May 2024 23:37:26 +0200 Subject: [PATCH 007/122] Update channel.py Co-authored-by: DevilXD <4180725+DevilXD@users.noreply.github.com> --- channel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channel.py b/channel.py index 760d431d..9423115d 100644 --- a/channel.py +++ b/channel.py @@ -390,7 +390,7 @@ async def send_watch(self) -> bool: signature: JsonType | None = response["data"]['streamPlaybackAccessToken']["signature"] value: JsonType | None = response["data"]['streamPlaybackAccessToken']["value"] if not signature or not value: - return None + return False RequestBroadcastQualitiesURL = f"https://usher.ttvnw.net/api/channel/hls/{self._login}.m3u8?sig={signature}&token={value}" From c1fda7bddd687a6324c56e42169c9e30254713e1 Mon Sep 17 00:00:00 2001 From: Windows200000 <72623832+Windows200000@users.noreply.github.com> Date: Tue, 14 May 2024 23:38:05 +0200 Subject: [PATCH 008/122] Update main.py Co-authored-by: DevilXD <4180725+DevilXD@users.noreply.github.com> --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 1865b8aa..ff5eb932 100644 --- a/main.py +++ b/main.py @@ -103,7 +103,7 @@ def debug_gql(self) -> int: parser.add_argument("-v", dest="_verbose", action="count", default=0) parser.add_argument("--tray", action="store_true") parser.add_argument("--log", action="store_true") - # undocumented debug args + # debug options parser.add_argument( "--debug-ws", dest="_debug_ws", action="store_true" ) From 03a4c4cbe6a219e79bac575bacf04989210eb81b Mon Sep 17 00:00:00 2001 From: Windows200000 <72623832+Windows200000@users.noreply.github.com> Date: Tue, 14 May 2024 23:49:57 +0200 Subject: [PATCH 009/122] Update channel.py changed comments marking the section of coded edited for this fix --- channel.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/channel.py b/channel.py index 9423115d..22f0fdbf 100644 --- a/channel.py +++ b/channel.py @@ -377,10 +377,7 @@ def _payload(self) -> JsonType: return {"data": (b64encode(json_minify(payload).encode("utf8"))).decode("utf8")} async def send_watch(self) -> bool: - #------------------------------------------------- - # FIX 2024/5 - # | - # v + # Start of fix for 2024/5 API Change try: response: JsonType = await self._twitch.gql_request( # Gets signature and value GQL_OPERATIONS["PlaybackAccessToken"].with_variables({"login": self._login}) @@ -422,8 +419,7 @@ async def send_watch(self) -> bool: except RequestException: return False - # FIX 2024/5 END - #------------------------------------------------- + # End of fix for 2024/5 API Change """ This uses the encoded payload on spade url to simulate watching the stream. Optimally, send every 60 seconds to advance drops. From 3b10a3f0409ddaf12d04377263202ac877872c9b Mon Sep 17 00:00:00 2001 From: Windows200000 <72623832+Windows200000@users.noreply.github.com> Date: Tue, 14 May 2024 23:51:43 +0200 Subject: [PATCH 010/122] Update channel.py fixed indentation for comment --- channel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channel.py b/channel.py index 22f0fdbf..8a327b8c 100644 --- a/channel.py +++ b/channel.py @@ -377,7 +377,7 @@ def _payload(self) -> JsonType: return {"data": (b64encode(json_minify(payload).encode("utf8"))).decode("utf8")} async def send_watch(self) -> bool: - # Start of fix for 2024/5 API Change + # Start of fix for 2024/5 API Change try: response: JsonType = await self._twitch.gql_request( # Gets signature and value GQL_OPERATIONS["PlaybackAccessToken"].with_variables({"login": self._login}) From bf87077ac7c876e86cd55bc6c7cb691d5451e068 Mon Sep 17 00:00:00 2001 From: Windows200000 <72623832+Windows200000@users.noreply.github.com> Date: Wed, 15 May 2024 00:41:25 +0200 Subject: [PATCH 011/122] Update channel.py replaced "GET" with "HEAD" on the last request, to prevent body data from being sent. --- channel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channel.py b/channel.py index 8a327b8c..be7fbfb2 100644 --- a/channel.py +++ b/channel.py @@ -413,7 +413,7 @@ async def send_watch(self) -> bool: try: async with self._twitch.request( # Downloads the stream - "GET", StreamLowestQualityURL + "HEAD", StreamLowestQualityURL ) as response3: # I lied, well idk, but this code doesn't listen for the actual video data return response3.status == 200 except RequestException: From 95e8799c9912b639ec4744603ce406dcffddff9f Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Wed, 15 May 2024 14:53:30 +0200 Subject: [PATCH 012/122] Updated watch frequency to 20s --- constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.py b/constants.py index 4d8e5581..7fc49fe9 100644 --- a/constants.py +++ b/constants.py @@ -116,7 +116,7 @@ def _merge_vars(base_vars: JsonType, vars: JsonType) -> None: PING_INTERVAL = timedelta(minutes=3) PING_TIMEOUT = timedelta(seconds=10) ONLINE_DELAY = timedelta(seconds=120) -WATCH_INTERVAL = timedelta(seconds=59) +WATCH_INTERVAL = timedelta(seconds=20) # Strings WINDOW_TITLE = f"Twitch Drops Miner v{__version__} (by DevilXD)" # Logging From 80ab1d00293ecb5850eb8bbda045114fdad60ef0 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Wed, 15 May 2024 16:56:30 +0200 Subject: [PATCH 013/122] Fixed displaying seconds --- cache.py | 11 +++++++++++ gui.py | 2 ++ twitch.py | 15 +++++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cache.py b/cache.py index f33cbb12..7c272579 100644 --- a/cache.py +++ b/cache.py @@ -32,6 +32,17 @@ class ExpiringHash(TypedDict): default_database: Hashes = {} +class CurrentSeconds: + LIFETIME = timedelta(days=7) + + def set_current_seconds(value): + global current_seconds + current_seconds = value + + def get_current_seconds(): + return current_seconds + + class ImageCache: LIFETIME = timedelta(days=7) diff --git a/gui.py b/gui.py index ddc3be55..24695a78 100644 --- a/gui.py +++ b/gui.py @@ -28,6 +28,7 @@ import win32con import win32gui +from cache import CurrentSeconds from translate import _ from cache import ImageCache from exceptions import ExitRequest @@ -667,6 +668,7 @@ def _update_time(self, seconds: int): drop_vars: _DropVars = self._vars["drop"] campaign_vars: _CampaignVars = self._vars["campaign"] dseconds = seconds % 60 + CurrentSeconds.set_current_seconds(dseconds) hours, minutes = self._divmod(drop_minutes, seconds) drop_vars["remaining"].set( _("gui", "progress", "remaining").format(time=f"{hours:>2}:{minutes:02}:{dseconds:02}") diff --git a/twitch.py b/twitch.py index 89aed302..5e9eaff8 100644 --- a/twitch.py +++ b/twitch.py @@ -34,6 +34,7 @@ ) from exc raise +from cache import CurrentSeconds from translate import _ from gui import GUIManager from channel import Channel @@ -1101,12 +1102,14 @@ async def _watch_loop(self) -> NoReturn: # NOTE: get_active_drop uses the watching channel by default, # so there's no point to pass it here if (drop := self.get_active_drop()) is not None: - drop.bump_minutes() - drop.display() - drop_text = ( - f"{drop.name} ({drop.campaign.game}, " - f"{drop.current_minutes}/{drop.required_minutes})" - ) + current_seconds = CurrentSeconds.get_current_seconds() + if current_seconds < 1: + drop.bump_minutes() + drop.display() + drop_text = ( + f"{drop.name} ({drop.campaign.game}, " + f"{drop.current_minutes}/{drop.required_minutes})" + ) logger.log(CALL, f"Drop progress from active search: {drop_text}") else: logger.log(CALL, "No active drop could be determined") From d0afcb726e09bd84da3d4dd47f4a91cada56a0f0 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Wed, 15 May 2024 18:21:54 +0200 Subject: [PATCH 014/122] Changed documentation string to match others --- channel.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/channel.py b/channel.py index be7fbfb2..f60bb93f 100644 --- a/channel.py +++ b/channel.py @@ -377,7 +377,9 @@ def _payload(self) -> JsonType: return {"data": (b64encode(json_minify(payload).encode("utf8"))).decode("utf8")} async def send_watch(self) -> bool: - # Start of fix for 2024/5 API Change + """ + Start of fix for 2024/5 API Change + """ try: response: JsonType = await self._twitch.gql_request( # Gets signature and value GQL_OPERATIONS["PlaybackAccessToken"].with_variables({"login": self._login}) @@ -419,7 +421,11 @@ async def send_watch(self) -> bool: except RequestException: return False - # End of fix for 2024/5 API Change + """ + End of fix for 2024/5 API Change. + Old code below. + """ + """ This uses the encoded payload on spade url to simulate watching the stream. Optimally, send every 60 seconds to advance drops. From 7920e9a4bb1c1b555f0736eff9afc87db366c7fb Mon Sep 17 00:00:00 2001 From: Windows200000 <72623832+Windows200000@users.noreply.github.com> Date: Thu, 16 May 2024 13:31:57 +0200 Subject: [PATCH 015/122] Updated README to reflect changes in how the application farms drops. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2dc95678..1f60fad8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This application allows you to AFK mine timed Twitch drops, without having to wo ### How It Works: -Every ~60 seconds, the application sends a "minute watched" event to the channel that's currently being watched - this is enough to advance the drops. Note that this completely bypasses the need to download any actual stream video and sound. To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection established that receives events about streams going up or down, or updates regarding the current amount of viewers. +Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. It then fetches the metadata of this stream - this is enough to advance the drops. Note that this completely bypasses the need to download any actual stream video and sound. To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection established that receives events about streams going up or down, or updates regarding the current amount of viewers. ### Features: From 698afc22b8c4bc528dab75403592acb6af812dcb Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 16 May 2024 19:46:21 +0200 Subject: [PATCH 016/122] check URLs and hardcoded 60s -> WATCH_INTERVAL --- channel.py | 9 +++++++-- twitch.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/channel.py b/channel.py index f60bb93f..7bd32531 100644 --- a/channel.py +++ b/channel.py @@ -3,6 +3,7 @@ import re import asyncio import logging +import validators from base64 import b64encode from functools import cached_property from typing import Any, SupportsInt, TYPE_CHECKING @@ -401,17 +402,21 @@ async def send_watch(self) -> bool: except RequestException: return False - LowestQualityBroadcastURL = BroadcastQualities.split("\n")[-1] # Just takes the last line, this should probably be handled better in the future + BroadcastLowestQualityURL = BroadcastQualities.split("\n")[-1] # Just takes the last line, this could probably be handled better in the future + if not validators.url(BroadcastLowestQualityURL): + return False try: async with self._twitch.request( # Gets actual streams - "GET", LowestQualityBroadcastURL + "GET", BroadcastLowestQualityURL ) as response2: StreamURLList = await response2.text() except RequestException: return False StreamLowestQualityURL = StreamURLList.split("\n")[-2] # For whatever reason this includes a blank line at the end, this should probably be handled better in the future + if not validators.url(StreamLowestQualityURL): + return False try: async with self._twitch.request( # Downloads the stream diff --git a/twitch.py b/twitch.py index 5e9eaff8..6ae0a35a 100644 --- a/twitch.py +++ b/twitch.py @@ -1048,7 +1048,7 @@ async def _watch_loop(self) -> NoReturn: if not succeeded: # this usually means the campaign expired in the middle of mining # NOTE: the maintenance task should switch the channel right after this happens - await self._watch_sleep(60) + await self._watch_sleep(interval) continue last_watch = time() self._drop_update = asyncio.Future() From ebad208e392ce7e8f08afc3326d2c310e31ae437 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 16 May 2024 20:17:11 +0200 Subject: [PATCH 017/122] Updated ENglish, Czech and German translation --- README.md | 2 +- lang/Deutsch.json | 2 +- "lang/\304\214e\305\241tina.json" | 2 +- translate.py | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1f60fad8..0118e537 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This application allows you to AFK mine timed Twitch drops, without having to wo ### How It Works: -Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. It then fetches the metadata of this stream - this is enough to advance the drops. Note that this completely bypasses the need to download any actual stream video and sound. To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection established that receives events about streams going up or down, or updates regarding the current amount of viewers. +Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. It then fetches the metadata of this data stream - this is enough to advance the drops. Note that this completely bypasses the need to download any actual stream video and sound. To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection established that receives events about streams going up or down, or updates regarding the current amount of viewers. ### Features: diff --git a/lang/Deutsch.json b/lang/Deutsch.json index 3b7fe09e..2cca9feb 100644 --- a/lang/Deutsch.json +++ b/lang/Deutsch.json @@ -153,7 +153,7 @@ "campaigns": "Alle Twitch-Kampagnen ansehen" }, "how_it_works": "So funktioniert's", - "how_it_works_text": "Alle ~60 Sekunden sendet die Anwendung ein \"Minute zugesehen\" Ereignis an den Kanal, dem gerade zugesehen wird.\nDies reicht aus, um den Drop voranzutreiben. Auf diese Weise ist es nicht nötig den Stream herunterzuladen und spart Bandbreite.\nUm den Online- oder Offline-Status der Kanäle aktuell zu halten, wird eine Websocket-Verbindung eingerichtet,\ndie die Kanäle auf ihren Status überprüft.", + "how_it_works_text": "Alle ~20 Sekunden fragt die Anwendung Twitch nach einer URL für die Rohdaten des Streams von dem Kanal, dem gerade zugesehen wird. Dann fordert sie die Metadaten dieses Datenstroms an. Dies reicht aus, um den Drop voranzutreiben. Auf diese Weise ist es nicht nötig den Stream herunterzuladen und spart Bandbreite.\nUm den Online- oder Offline-Status der Kanäle aktuell zu halten, wird eine Websocket-Verbindung eingerichtet,\ndie die Kanäle auf ihren Status überprüft.", "getting_started": "Erste Schritte", "getting_started_text": "• In der Anwendung anmelden.\n• Stelle sicher, dass das Twitch-Konto mit allen Kampagnen verknüpft ist, an denen Interesse besteht.\n• Sollen alle Drops bearbeitet werden, entferne den Haken bei \"Nur Priorität\" und drücke \"Neu laden\".\n• Sollen nur bestimmte Spiele in betracht gezogen werden, verwende die \"Priorität\" Liste um die Wahl nach Spielen einzugrenzen.\n• Die Liste priorisiert von oben nach unten.\n• Die Option \"Nur Priorität\" verhindert, dass Spiele, die nicht auf der Prioritätenliste stehen, bearbeitet werden.\n• Mit der Liste \"Ausschließen\", ist es möglich Spiele zu filtern, die niemals in betracht gezogen werden sollen.\n• Wenn Listen oder Optionen angepasst wurden, muss \"Neu laden\" gedrückt werden, damit die Änderungen übernommen werden." } diff --git "a/lang/\304\214e\305\241tina.json" "b/lang/\304\214e\305\241tina.json" index a07bb937..0f1df371 100644 --- "a/lang/\304\214e\305\241tina.json" +++ "b/lang/\304\214e\305\241tina.json" @@ -146,7 +146,7 @@ "campaigns": "Zobrazit všechny kampaňe a spravovat propojené účty" }, "how_it_works": "Jak to funguje", - "how_it_works_text": "Každých ~60 sekund aplikace odešle událost 'sledované minuty' na aktuálně sledovaný kanál - to stačí k posunu umístění. Všimněte si, že tímto způsobem zcela odpadá nutnost stahovat skutečné streamované video a zvuk. Aby byl stav kanálu (online nebo offline) stále aktuální, je navázáno spojení přes websocket, které přijímá události o spuštění nebo vypnutí streamů nebo aktualizace o aktuálním počtu diváků.", + "how_it_works_text": "Každých ~20 sekund aplikace požádá Twitch o adresu k čistým datám streamu od kanálu, který je v současnosti sledován. Poté stáhne dodatkové informace těchto dat streamu - to stačí k posunu umístění. Všimněte si, že tímto způsobem zcela odpadá nutnost stahovat skutečné streamované video a zvuk. Aby byl stav kanálu (online nebo offline) stále aktuální, je navázáno spojení přes websocket, které přijímá události o spuštění nebo vypnutí streamů nebo aktualizace o aktuálním počtu diváků.", "getting_started": "Jak začít", "getting_started_text": "1. Přihlaste se do aplikace. \n2. Ujistěte se, že je váš účet Twitch spojen se všemi reklamními sériemi, které chcete těžit. \n3. Pokud chcete klepnout pouze na veškerý obsah, zrušte zaškrtnutí políčka 'Pouze prioritní' a stiskněte tlačítko 'Obnovit'. \n4. Pokud se chcete nejprve věnovat konkrétním hrám, použijte seznam 'Prioritní' a nastavte si pořadí vybraných her. Nejprve se vyzkouší hry na začátku seznamu a poté hry na konci seznamu. \n5. Ponechte zaškrtnutou možnost 'Pouze prioritní', abyste se vyhnuli vyhledávání her, které nejsou na seznamu priorit. Nebo ne - záleží na vás. \n6. Pomocí seznamu 'vyloučit' můžete aplikaci sdělit, které hry by neměly být vytěženy. \n7. Změna obsahu obou seznamů nebo stavu možnosti Pouze prioritní vyžaduje stisknutí tlačítka Znovu načíst, aby se změna projevila." } diff --git a/translate.py b/translate.py index 227c0e8c..d7e7050b 100644 --- a/translate.py +++ b/translate.py @@ -379,8 +379,8 @@ class Translation(TypedDict): }, "how_it_works": "How It Works", "how_it_works_text": ( - "Every ~60 seconds, the application sends a \"minute watched\" event " - "to the channel that's currently being watched - this is enough " + "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. " + "It then fetches the metadata of this data stream - this is enough " "to advance the drops. Note that this completely bypasses the need to download " "any actual stream video and sound. " "To keep the status (ONLINE or OFFLINE) of the channels up-to-date, " From a86862e004e4aff5f6b8b4798efc4511ca89b5b2 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 16 May 2024 20:33:29 +0200 Subject: [PATCH 018/122] removed empty line for consistency --- channel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/channel.py b/channel.py index 7bd32531..7aa594bc 100644 --- a/channel.py +++ b/channel.py @@ -425,7 +425,6 @@ async def send_watch(self) -> bool: return response3.status == 200 except RequestException: return False - """ End of fix for 2024/5 API Change. Old code below. From 93b7cc8c711976f6bbd5571139d5011c2d3b3eb8 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 16 May 2024 22:07:12 +0200 Subject: [PATCH 019/122] added "Validators" to requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 827d2d96..f78481fc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,7 @@ aiohttp>=3.9,<4.0 Pillow pystray PyGObject<3.47; sys_platform == "linux" # required for better system tray support on Linux +validators # environment-dependent dependencies pywin32; sys_platform == "win32" From f233161209956d8fc1a2abba133338c9ffd48a1b Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 16:30:44 +0200 Subject: [PATCH 020/122] Create a workflow to ensure patch notes were added for in-dev (#18) --- .github/workflows/Check_patch_notes.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/Check_patch_notes.yml diff --git a/.github/workflows/Check_patch_notes.yml b/.github/workflows/Check_patch_notes.yml new file mode 100644 index 00000000..af6e0604 --- /dev/null +++ b/.github/workflows/Check_patch_notes.yml @@ -0,0 +1,23 @@ +name: Check patch notes + +on: + pull_request: + branches: + - main # Adjust to match your main branch name + +jobs: + check_documentation: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check for patch notes changes + run: | + if git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep -q '^patch_notes.txt$'; then + echo "Patch notes updated." + else + echo "Update patch notes!" + exit 1 + fi From 6629aac392e88776bd43396e527200c3e547f11c Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 16:31:00 +0200 Subject: [PATCH 021/122] Create release.yml for releasing stable version. Mostly copied from ci.yaml (#17) --- .github/workflows/release.yml | 246 ++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..ecc54011 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,246 @@ +name: Build release + +on: + pull_request: + types: [closed] + branches: + - 'master' + workflow_dispatch: + +env: + PYTHON_VERSION: '3.10' + +jobs: + windows: + name: Windows + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up variables + id: vars + run: | + Add-Content $env:GITHUB_OUTPUT "sha_short=$(git rev-parse --short HEAD)" + + - name: Append git revision to project version + run: | + (Get-Content version.py) ` + -Replace '^__version__\s*=\s*"[^"]+', "`$0.${{steps.vars.outputs.sha_short}}" |` + Out-File version.py + + # Ensure Python version + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{env.PYTHON_VERSION}} + + - name: Install project dependencies + run: | + python3 -m pip install wheel + python3 -m pip install -r requirements.txt + + - name: Install UPX + run: | + Invoke-WebRequest -Uri https://github.com/upx/upx/releases/download/v4.0.2/upx-4.0.2-win64.zip -OutFile (Join-Path $env:Temp upx.zip) + Expand-Archive -LiteralPath (Join-Path $env:Temp upx.zip) -DestinationPath $env:Temp + Move-Item -Path (Join-Path $env:Temp upx-*) -Destination (Join-Path $env:Temp upx) + Add-Content $env:GITHUB_PATH (Join-Path $env:Temp upx) + + - name: Install PyInstaller + run: | + python3 -m pip install pyinstaller + + - name: Create portable executable + run: | + pyinstaller build.spec + + - name: Create release folder + run: | + $FolderName = 'Twitch Drops Miner' + New-Item $FolderName -ItemType Directory + Copy-Item dist\*.exe $FolderName + Copy-Item manual.txt $FolderName + Compress-Archive -Path $FolderName -DestinationPath Twitch.Drops.Miner.Windows.zip + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: Twitch.Drops.Miner.Windows + path: Twitch.Drops.Miner.Windows.zip + + linux-pyinstaller: + name: Linux (PyInstaller) + runs-on: ubuntu-20.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up variables + id: vars + run: | + echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" + + - name: Append git revision to project version + run: | + sed -ri "s/^__version__\s*=\s*\"[^\"]+/\0.${{ steps.vars.outputs.sha_short }}/" version.py + + # NOTE: We're only use a custom version of Python here because truststore requires at least Python 3.10, but Ubuntu 20.04 has Python 3.8. + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{env.PYTHON_VERSION}} + + - name: Install system dependencies + run: | + sudo apt update + sudo apt install gir1.2-appindicator3-0.1 libgirepository1.0-dev python3-tk + + - name: Install project dependencies + run: | + python3 -m pip install wheel + python3 -m pip install -r requirements.txt + + - name: Install PyInstaller + run: | + python3 -m pip install pyinstaller + + # NOTE: Remove this step if/once libxft gets updated to 2.3.5 or newer on Ubuntu 20.04, which currently has 2.3.3. + - name: Build a recent version of libXft + run: | + mkdir -p /tmp/libXft + cd /tmp/libXft + curl -L https://xorg.freedesktop.org/releases/individual/lib/libXft-2.3.8.tar.xz -o libXft.tar.xz + tar xvf libXft.tar.xz + cd libXft-* + ./configure --prefix=/tmp/libXft --sysconfdir=/etc --disable-static + make + make install-strip + + - name: Create portable executable + run: | + LD_LIBRARY_PATH=/tmp/libXft/lib xvfb-run --auto-servernum pyinstaller build.spec + + - name: Show PyInstaller warnings + run: | + cat build/build/warn-build.txt || true + + - name: Create release folder + run: | + folder='Twitch Drops Miner' + mkdir "${folder}" + cp manual.txt dist/* "${folder}" + 7z a Twitch.Drops.Miner.Linux.PyInstaller.zip "${folder}" + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: Twitch.Drops.Miner.Linux.PyInstaller + path: Twitch.Drops.Miner.Linux.PyInstaller.zip + + linux-appimage: + name: Linux (AppImage) + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up variables + id: vars + run: | + echo "app_version=$(python3 -c 'from version import __version__ as v; print(v)')" >> "${GITHUB_OUTPUT}" + echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" + + - name: Append git revision to project version + run: | + sed -ri "s/^__version__\s*=\s*\"[^\"]+/\0.${{steps.vars.outputs.sha_short}}/" version.py + + - name: Install system dependencies + run: | + sudo apt update + sudo apt install libgirepository1.0-dev python3-testresources + + - name: Download AppImage Builder + run: | + curl -L https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage -o appimage-builder + chmod +x appimage-builder + + - name: Create AppImage + env: + APPIMAGE_EXTRACT_AND_RUN: 1 + APP_VERSION: ${{steps.vars.outputs.app_version}}.${{steps.vars.outputs.sha_short}} + PYTHON_VERSION: ${{env.PYTHON_VERSION}} + run: | + ./appimage-builder --recipe appimage/AppImageBuilder.yml + + - name: Create release folder + run: | + folder='Twitch Drops Miner' + mkdir "${folder}" + cp *.AppImage manual.txt "${folder}" + 7z a Twitch.Drops.Miner.Linux.AppImage.zip "${folder}" + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: Twitch.Drops.Miner.Linux.AppImage + path: Twitch.Drops.Miner.Linux.AppImage.zip + + update_releases_page: + name: Upload builds to Releases + if: github.event_name != 'pull_request' + needs: + - windows + - linux-pyinstaller + - linux-appimage + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Set up variables + id: vars + run: | + echo "date_now=$(date --rfc-3339=seconds)" >> "${GITHUB_OUTPUT}" + + - name: Download build artifacts from previous jobs + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Read patch notes from file + id: read_patch_notes + run: | + PATCH_NOTES=$(cat patch_notes.txt) + echo "patch_notes=$PATCH_NOTES" >> $GITHUB_ENV + + - name: Upload builds to Releases + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifactErrorsFailBuild: true + artifacts: artifacts/*/* + body: | + # ⚠️ Please help with translation as tracked in #2 ! + + *** + **This is an automatically generated updated version of the application, that includes the latest master branch changes.** + **This build should be stable, but if you encounter anything, please report any issues you find.** + + - Last build date: `${{ steps.vars.outputs.date_now }}` + - Reference commit: ${{ github.sha }} + + *** + ## Patch notes: + ${{ env.patch_notes }} + + name: Updated build + prerelease: false + removeArtifacts: true + tag: v15 From 26de4603d3903f093d7da07e85649413a81ec7fc Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 16:36:28 +0200 Subject: [PATCH 022/122] Updated ci workflow for the purposes of this fork (#19) --- .github/workflows/ci.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41ee6aaa..d4ca2fb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,12 @@ -name: Build +name: Build dev version on: push: branches: - - 'master' + - 'in-dev' pull_request: + branches: + - 'in-dev' workflow_dispatch: env: @@ -221,7 +223,10 @@ jobs: artifactErrorsFailBuild: true artifacts: artifacts/*/* body: | - **This is an automatically generated in-development pre-release version of the application, that includes the latest master branch changes.** + # ⚠️ Please help with translation as tracked in #2 ! + + *** + **This is an automatically generated in-development pre-release version of the application, that includes the latest in-dev branch changes.** **⚠️ This build is not stable and may end up terminating with a fatal error. ⚠️** **Use at your own risk.** From a42ea36560d5ed8b786d354f2af2048bfd01e205 Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 16:41:17 +0200 Subject: [PATCH 023/122] Added option to manually trigger patch notes workflow (#20) --- .github/workflows/Check_patch_notes.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/Check_patch_notes.yml b/.github/workflows/Check_patch_notes.yml index af6e0604..cb27d569 100644 --- a/.github/workflows/Check_patch_notes.yml +++ b/.github/workflows/Check_patch_notes.yml @@ -4,6 +4,7 @@ on: pull_request: branches: - main # Adjust to match your main branch name + workflow_dispatch: jobs: check_documentation: From 7a625046d586878b90c3c7d37cea9927d5663559 Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 17:27:06 +0200 Subject: [PATCH 024/122] Update Check_patch_notes.yml to resolve merge conflict (#22) --- .github/workflows/Check_patch_notes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Check_patch_notes.yml b/.github/workflows/Check_patch_notes.yml index cb27d569..c4f32ff6 100644 --- a/.github/workflows/Check_patch_notes.yml +++ b/.github/workflows/Check_patch_notes.yml @@ -3,7 +3,7 @@ name: Check patch notes on: pull_request: branches: - - main # Adjust to match your main branch name + - main workflow_dispatch: jobs: From 96319cb4abc570184023cbad1b21f002b8a827e8 Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 17:35:25 +0200 Subject: [PATCH 025/122] Update master (#21) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updated Italian translation.json * Update README.md to include credit for adjusted translations * Updated ci.yml (build-) workflow to better reflect usage in this fork * Added start timestamp to gui from pull request from original repo * removed unnecessary print * added patch notes to pre-release workflow * updated credits and workflows, created patch notes * Update spanish translation (#16) * Update Simplified Chinese Translation (#15) Simplified Chinese (简体中文) translation updated. * CHanged credits * updated check patch notes workflow --------- Co-authored-by: Kuddus73 <127908708+Kuddus73@users.noreply.github.com> Co-authored-by: Arne Weber Co-authored-by: VSeryi Co-authored-by: 残影 <9458793+BreakshadowCN@users.noreply.github.com> --- .github/workflows/Check_patch_notes.yml | 2 +- .github/workflows/Release.yml | 246 ++++++++++++++++++ README.md | 2 + "lang/Espa\303\261ol.json" | 10 +- lang/Italiano.json | 2 +- ...\344\275\223\344\270\255\346\226\207.json" | 2 +- patch_notes.txt | 3 + 7 files changed, 259 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/Release.yml create mode 100644 patch_notes.txt diff --git a/.github/workflows/Check_patch_notes.yml b/.github/workflows/Check_patch_notes.yml index c4f32ff6..f94ee248 100644 --- a/.github/workflows/Check_patch_notes.yml +++ b/.github/workflows/Check_patch_notes.yml @@ -21,4 +21,4 @@ jobs: else echo "Update patch notes!" exit 1 - fi + fi \ No newline at end of file diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml new file mode 100644 index 00000000..bf029b60 --- /dev/null +++ b/.github/workflows/Release.yml @@ -0,0 +1,246 @@ +name: Build release + +on: + pull_request: + types: [closed] + branches: + - 'master' + workflow_dispatch: + +env: + PYTHON_VERSION: '3.10' + +jobs: + windows: + name: Windows + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up variables + id: vars + run: | + Add-Content $env:GITHUB_OUTPUT "sha_short=$(git rev-parse --short HEAD)" + + - name: Append git revision to project version + run: | + (Get-Content version.py) ` + -Replace '^__version__\s*=\s*"[^"]+', "`$0.${{steps.vars.outputs.sha_short}}" |` + Out-File version.py + + # Ensure Python version + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{env.PYTHON_VERSION}} + + - name: Install project dependencies + run: | + python3 -m pip install wheel + python3 -m pip install -r requirements.txt + + - name: Install UPX + run: | + Invoke-WebRequest -Uri https://github.com/upx/upx/releases/download/v4.0.2/upx-4.0.2-win64.zip -OutFile (Join-Path $env:Temp upx.zip) + Expand-Archive -LiteralPath (Join-Path $env:Temp upx.zip) -DestinationPath $env:Temp + Move-Item -Path (Join-Path $env:Temp upx-*) -Destination (Join-Path $env:Temp upx) + Add-Content $env:GITHUB_PATH (Join-Path $env:Temp upx) + + - name: Install PyInstaller + run: | + python3 -m pip install pyinstaller + + - name: Create portable executable + run: | + pyinstaller build.spec + + - name: Create release folder + run: | + $FolderName = 'Twitch Drops Miner' + New-Item $FolderName -ItemType Directory + Copy-Item dist\*.exe $FolderName + Copy-Item manual.txt $FolderName + Compress-Archive -Path $FolderName -DestinationPath Twitch.Drops.Miner.Windows.zip + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: Twitch.Drops.Miner.Windows + path: Twitch.Drops.Miner.Windows.zip + + linux-pyinstaller: + name: Linux (PyInstaller) + runs-on: ubuntu-20.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up variables + id: vars + run: | + echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" + + - name: Append git revision to project version + run: | + sed -ri "s/^__version__\s*=\s*\"[^\"]+/\0.${{ steps.vars.outputs.sha_short }}/" version.py + + # NOTE: We're only use a custom version of Python here because truststore requires at least Python 3.10, but Ubuntu 20.04 has Python 3.8. + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{env.PYTHON_VERSION}} + + - name: Install system dependencies + run: | + sudo apt update + sudo apt install gir1.2-appindicator3-0.1 libgirepository1.0-dev python3-tk + + - name: Install project dependencies + run: | + python3 -m pip install wheel + python3 -m pip install -r requirements.txt + + - name: Install PyInstaller + run: | + python3 -m pip install pyinstaller + + # NOTE: Remove this step if/once libxft gets updated to 2.3.5 or newer on Ubuntu 20.04, which currently has 2.3.3. + - name: Build a recent version of libXft + run: | + mkdir -p /tmp/libXft + cd /tmp/libXft + curl -L https://xorg.freedesktop.org/releases/individual/lib/libXft-2.3.8.tar.xz -o libXft.tar.xz + tar xvf libXft.tar.xz + cd libXft-* + ./configure --prefix=/tmp/libXft --sysconfdir=/etc --disable-static + make + make install-strip + + - name: Create portable executable + run: | + LD_LIBRARY_PATH=/tmp/libXft/lib xvfb-run --auto-servernum pyinstaller build.spec + + - name: Show PyInstaller warnings + run: | + cat build/build/warn-build.txt || true + + - name: Create release folder + run: | + folder='Twitch Drops Miner' + mkdir "${folder}" + cp manual.txt dist/* "${folder}" + 7z a Twitch.Drops.Miner.Linux.PyInstaller.zip "${folder}" + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: Twitch.Drops.Miner.Linux.PyInstaller + path: Twitch.Drops.Miner.Linux.PyInstaller.zip + + linux-appimage: + name: Linux (AppImage) + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up variables + id: vars + run: | + echo "app_version=$(python3 -c 'from version import __version__ as v; print(v)')" >> "${GITHUB_OUTPUT}" + echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" + + - name: Append git revision to project version + run: | + sed -ri "s/^__version__\s*=\s*\"[^\"]+/\0.${{steps.vars.outputs.sha_short}}/" version.py + + - name: Install system dependencies + run: | + sudo apt update + sudo apt install libgirepository1.0-dev python3-testresources + + - name: Download AppImage Builder + run: | + curl -L https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage -o appimage-builder + chmod +x appimage-builder + + - name: Create AppImage + env: + APPIMAGE_EXTRACT_AND_RUN: 1 + APP_VERSION: ${{steps.vars.outputs.app_version}}.${{steps.vars.outputs.sha_short}} + PYTHON_VERSION: ${{env.PYTHON_VERSION}} + run: | + ./appimage-builder --recipe appimage/AppImageBuilder.yml + + - name: Create release folder + run: | + folder='Twitch Drops Miner' + mkdir "${folder}" + cp *.AppImage manual.txt "${folder}" + 7z a Twitch.Drops.Miner.Linux.AppImage.zip "${folder}" + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: Twitch.Drops.Miner.Linux.AppImage + path: Twitch.Drops.Miner.Linux.AppImage.zip + + update_releases_page: + name: Upload builds to Releases + if: github.event_name != 'pull_request' + needs: + - windows + - linux-pyinstaller + - linux-appimage + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Set up variables + id: vars + run: | + echo "date_now=$(date --rfc-3339=seconds)" >> "${GITHUB_OUTPUT}" + + - name: Download build artifacts from previous jobs + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Read patch notes from file + id: read_patch_notes + run: | + PATCH_NOTES=$(cat patch_notes.txt) + echo "patch_notes=$PATCH_NOTES" >> $GITHUB_ENV + + - name: Upload builds to Releases + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifactErrorsFailBuild: true + artifacts: artifacts/*/* + body: | + # ⚠️ Please help with translation as tracked in #2 ! + + *** + **This is an automatically generated updated version of the application, that includes the latest master branch changes.** + **This build should be stable, but if you encounter anything, please reoirt any issues you find.** + + - Last build date: `${{ steps.vars.outputs.date_now }}` + - Reference commit: ${{ github.sha }} + + *** + ## Patch notes: + ${{ env.patch_notes }} + + name: Updated build + prerelease: false + removeArtifacts: true + tag: v15 diff --git a/README.md b/README.md index 0118e537..5eb7bf37 100644 --- a/README.md +++ b/README.md @@ -129,3 +129,5 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @casungo - For the entirety of the Italian (Italiano) translation. @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. + +@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN - For updating Translations. diff --git "a/lang/Espa\303\261ol.json" "b/lang/Espa\303\261ol.json" index 2ed514cb..809aada3 100644 --- "a/lang/Espa\303\261ol.json" +++ "b/lang/Espa\303\261ol.json" @@ -2,13 +2,13 @@ "english_name": "Spanish", "status": { "terminated": "\nLa aplicación se ha detenido.\nPor favor, cierre la aplicación.", - "watching": "Mirando el canal: {channel}", + "watching": "Viendo el canal: {channel}", "goes_online": "El canal {channel} se ha conectado, cambiando...", "goes_offline": "El canal {channel} se ha desconectado, cambiando...", "claimed_drop": "Drop reclamado: {drop}", "claimed_points": "Recompensa de puntos reclamados: {points}", - "earned_points": "Puntos obtenidos por mirar el stream: {points} | Total: {balance}", - "no_channel": "No se ha encontrado un canal en vivo para mirar. \nEsperando un canal en vivo...", + "earned_points": "Puntos obtenidos por ver el stream: {points} | Total: {balance}", + "no_channel": "No se ha encontrado un canal en directo para ver. \nEsperando un canal en directo...", "no_campaign": "No se ha encontrado una campaña activa. \nEsperando una nueva campaña..." }, "login": { @@ -39,7 +39,7 @@ "exiting": "Saliendo...", "terminated": "Aplicación suspendida.", "cleanup": "Limpiando canales...", - "gathering": "Buscando canales en vivo...", + "gathering": "Buscando canales en directo...", "switching": "Cambiando de canal...", "fetching_inventory": "Obteniendo inventario...", "fetching_campaigns": "Obteniendo campañas...", @@ -154,7 +154,7 @@ "campaigns": "Ver todas las campañas y administrar cuentas vinculadas" }, "how_it_works": "Cómo funciona", - "how_it_works_text": "Cada aproximadamente 60 segundos, la aplicación envía un \"minuto visto\" al canal que se está mirando actualmente. \nDe esta forma, no es necesario descargar el video o sonido del stream. Ahorrando ancho de banda al usuario. \nCon el fin de mantener actualizados los estados (ONLINE o OFFLINE) de los canales, se establece una conexión websocket, \nque recibe información de los streams para poder actualizar el estado, o cantidad de espectadores actuales.", + "how_it_works_text": "Aproximadamente cada 20 segundos, la aplicación solicita a Twitch la URL de los datos del canal que estamos viendo. \nDe esta forma, obtenemos sus metadatos, lo que nos permite ahorrar en la descarga de video o audio del stream. \nPara mantener actualizados los estados (ONLINE o OFFLINE) de los canales, así como el número de espectadores, \nse establece una conexión WebSocket mediante de la cual recibimos la información actualizada de los streams.", "getting_started": "Primeros pasos", "getting_started_text": "1. Inicie sesión en la aplicación. \n2. Verifique que su cuenta de Twitch esté vinculada a todas las campañas deseadas a minar. \n3. Si desea minar todas las campañas, desmarque la opción \"Minar solo juegos preferidos\" y presione \"Recargar\". \n4. Si desea darle prioridad a una campaña específica, utilice la \"Lista de juegos preferidos\" para crear una lista de prioridad. \nLos juegos en la parte superior de la lista se intentarán minar antes de los que estén más abajo. \n5. Utilice la opción \"Minar solo juegos preferidos\" si desea evitar minar juegos que no estén en la lista de juegos preferidos. \n6. Utilice la \"Lista de juegos excluidos\" si desea evitar minar juegos que no estén en la lista de juegos excluidos. \n7. Al utilizar la opción \"Minar solo juegos preferidos\" o al cambiar el contenido de las listas, \nserá necesario presionar el botón \"Recargar\" para que los cambios sean aplicados." } diff --git a/lang/Italiano.json b/lang/Italiano.json index 9a5abd9e..320f09dc 100644 --- a/lang/Italiano.json +++ b/lang/Italiano.json @@ -154,7 +154,7 @@ "campaigns": "Vedi tutte le campagne e gestisci i collegamenti dell'account" }, "how_it_works": "Come funziona", - "how_it_works_text": "Ogni ~60 secondi, l'applicazione invia un evento \"minuto guardato\" al canale che stai guardando - questo è sufficiente per far avanzare il progresso dei drop. Da notare che questo bypassa completamente la necessità di scaricare qualsiasi video o audio della diretta. Per mantenere lo stato (ONLINE o OFFLINE) dei canali aggiornato, c'è una connessione websocket stabilita che riceve eventi sui canali che vanno online o offline, o aggiornamenti riguardanti il numero attuale di spettatori.", + "how_it_works_text": "Circa ogni 20 secondi, l'applicazione chiede a Twitch un URL per il flusso di dati grezzi del canale attualmente guardato. Successivamente, recupera i metadati di questo flusso e ciò è sufficiente per far avanzare il progresso dei drop. Da notare che questo bypassa completamente la necessità di scaricare qualsiasi video o audio della diretta. Per mantenere aggiornato lo stato (ONLINE o OFFLINE) dei canali, viene stabilita una connessione websocket che riceve eventi sui canali che vanno online o offline, oppure aggiornamenti relativi al numero attuale di spettatori.", "getting_started": "Per iniziare", "getting_started_text": "1. Effettua il login nell'applicazione.\n2. Assicurati che il tuo account Twitch sia collegato a tutte le campagne per cui sei interessato a ottenere i drop.\n3. Se sei interessato a ottenere tutto, deseleziona \"Solo priorità\" e premi su \"Ricarica\".\n4. Se vuoi ottenere prima giochi specifici, usa la lista \"Priorità\" per impostare una lista ordinata di giochi a tua scelta. I giochi in cima alla lista verranno ottenuti prima.\n5. Mantieni l'opzione \"Solo priorità\" selezionata, per evitare di ottenere giochi che non sono nella lista delle priorità. Oppure non farlo - dipende da te.\n6. Usa la lista \"Escludi\" per dire all'applicazione quali giochi non devono mai essere ottenuti.\n7. Cambiare il contenuto di una delle liste, o cambiare lo stato dell'opzione \"Solo priorità\", richiede di premere su \"Ricarica\" perché le modifiche abbiano effetto." } diff --git "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" index f98d36a2..755adc33 100644 --- "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" +++ "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" @@ -154,7 +154,7 @@ "campaigns": "查看所有掉宝活动并管理连接账号" }, "how_it_works": "工作原理", - "how_it_works_text": "每隔约 60 秒,应用程序会向当前正在观看的频道发送一个“观看了一分钟”事件 - 这足以推进掉宝进度。这完全不需要下载任何实际视频流和声音。为了使频道的状态(在线或离线)保持最新,建立了websocket连接,用于接收有关直播开播下播事件,或当前观众数量的更新。", + "how_it_works_text": "每隔约 20 秒,程序就会向 Twitch 询问当前正在观看的频道的原始数据流 URL。然后,它会获取这个数据流的元数据。 - 这足以推进掉宝进度。这完全不需要下载任何实际的视频流和音频流。为了使频道的状态(在线或离线)保持最新,程序会建立 Websocket 连接,用于接收有关频道开播和下播的事件,并更新当前的观众数量。", "getting_started": "入门设置", "getting_started_text": "1. 登录应用程序。\n2.确保所有感兴趣挖掘的游戏的账号已连接到您的Twitch账号。\n3.如果您想挖掘所有掉宝,请不要勾选“仅参与优先掉宝游戏”,然后按“刷新”。\n4.如果您想优先挖掘特定游戏,请使用“优先掉宝游戏”列表设置您想挖掘的游戏的优先顺序。程序将尝试先挖掘列表顶部的游戏,然后再挖掘后边的游戏。\n5.勾选“仅参与优先掉宝游戏”时,不会挖掘不在优先列表中的游戏。勾不勾选取决于你。\n6。使用“不参与掉宝游戏”列表设置永不挖掘的游戏。\n7.更改任一列表的内容,或更改“仅参与优先掉宝游戏”勾选状态,需要手动按“刷新”才能使更改生效。" } diff --git a/patch_notes.txt b/patch_notes.txt new file mode 100644 index 00000000..5a3ef286 --- /dev/null +++ b/patch_notes.txt @@ -0,0 +1,3 @@ +### 17.5.2024 +- Updated Italian, Simplified Chineese and Spanish translation as well as corresponding credits +- Various changes to github workflows \ No newline at end of file From 02381423f124a1fbd31c5a88ca5ac824e4887665 Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 18:38:18 +0200 Subject: [PATCH 026/122] Delete .github/workflows/Release.yml (#24) --- .github/workflows/Release.yml | 246 ---------------------------------- 1 file changed, 246 deletions(-) delete mode 100644 .github/workflows/Release.yml diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml deleted file mode 100644 index bf029b60..00000000 --- a/.github/workflows/Release.yml +++ /dev/null @@ -1,246 +0,0 @@ -name: Build release - -on: - pull_request: - types: [closed] - branches: - - 'master' - workflow_dispatch: - -env: - PYTHON_VERSION: '3.10' - -jobs: - windows: - name: Windows - runs-on: windows-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up variables - id: vars - run: | - Add-Content $env:GITHUB_OUTPUT "sha_short=$(git rev-parse --short HEAD)" - - - name: Append git revision to project version - run: | - (Get-Content version.py) ` - -Replace '^__version__\s*=\s*"[^"]+', "`$0.${{steps.vars.outputs.sha_short}}" |` - Out-File version.py - - # Ensure Python version - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: ${{env.PYTHON_VERSION}} - - - name: Install project dependencies - run: | - python3 -m pip install wheel - python3 -m pip install -r requirements.txt - - - name: Install UPX - run: | - Invoke-WebRequest -Uri https://github.com/upx/upx/releases/download/v4.0.2/upx-4.0.2-win64.zip -OutFile (Join-Path $env:Temp upx.zip) - Expand-Archive -LiteralPath (Join-Path $env:Temp upx.zip) -DestinationPath $env:Temp - Move-Item -Path (Join-Path $env:Temp upx-*) -Destination (Join-Path $env:Temp upx) - Add-Content $env:GITHUB_PATH (Join-Path $env:Temp upx) - - - name: Install PyInstaller - run: | - python3 -m pip install pyinstaller - - - name: Create portable executable - run: | - pyinstaller build.spec - - - name: Create release folder - run: | - $FolderName = 'Twitch Drops Miner' - New-Item $FolderName -ItemType Directory - Copy-Item dist\*.exe $FolderName - Copy-Item manual.txt $FolderName - Compress-Archive -Path $FolderName -DestinationPath Twitch.Drops.Miner.Windows.zip - - - name: Upload build artifact - uses: actions/upload-artifact@v4 - with: - if-no-files-found: error - name: Twitch.Drops.Miner.Windows - path: Twitch.Drops.Miner.Windows.zip - - linux-pyinstaller: - name: Linux (PyInstaller) - runs-on: ubuntu-20.04 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up variables - id: vars - run: | - echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" - - - name: Append git revision to project version - run: | - sed -ri "s/^__version__\s*=\s*\"[^\"]+/\0.${{ steps.vars.outputs.sha_short }}/" version.py - - # NOTE: We're only use a custom version of Python here because truststore requires at least Python 3.10, but Ubuntu 20.04 has Python 3.8. - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: ${{env.PYTHON_VERSION}} - - - name: Install system dependencies - run: | - sudo apt update - sudo apt install gir1.2-appindicator3-0.1 libgirepository1.0-dev python3-tk - - - name: Install project dependencies - run: | - python3 -m pip install wheel - python3 -m pip install -r requirements.txt - - - name: Install PyInstaller - run: | - python3 -m pip install pyinstaller - - # NOTE: Remove this step if/once libxft gets updated to 2.3.5 or newer on Ubuntu 20.04, which currently has 2.3.3. - - name: Build a recent version of libXft - run: | - mkdir -p /tmp/libXft - cd /tmp/libXft - curl -L https://xorg.freedesktop.org/releases/individual/lib/libXft-2.3.8.tar.xz -o libXft.tar.xz - tar xvf libXft.tar.xz - cd libXft-* - ./configure --prefix=/tmp/libXft --sysconfdir=/etc --disable-static - make - make install-strip - - - name: Create portable executable - run: | - LD_LIBRARY_PATH=/tmp/libXft/lib xvfb-run --auto-servernum pyinstaller build.spec - - - name: Show PyInstaller warnings - run: | - cat build/build/warn-build.txt || true - - - name: Create release folder - run: | - folder='Twitch Drops Miner' - mkdir "${folder}" - cp manual.txt dist/* "${folder}" - 7z a Twitch.Drops.Miner.Linux.PyInstaller.zip "${folder}" - - - name: Upload build artifact - uses: actions/upload-artifact@v4 - with: - if-no-files-found: error - name: Twitch.Drops.Miner.Linux.PyInstaller - path: Twitch.Drops.Miner.Linux.PyInstaller.zip - - linux-appimage: - name: Linux (AppImage) - runs-on: ubuntu-22.04 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up variables - id: vars - run: | - echo "app_version=$(python3 -c 'from version import __version__ as v; print(v)')" >> "${GITHUB_OUTPUT}" - echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" - - - name: Append git revision to project version - run: | - sed -ri "s/^__version__\s*=\s*\"[^\"]+/\0.${{steps.vars.outputs.sha_short}}/" version.py - - - name: Install system dependencies - run: | - sudo apt update - sudo apt install libgirepository1.0-dev python3-testresources - - - name: Download AppImage Builder - run: | - curl -L https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage -o appimage-builder - chmod +x appimage-builder - - - name: Create AppImage - env: - APPIMAGE_EXTRACT_AND_RUN: 1 - APP_VERSION: ${{steps.vars.outputs.app_version}}.${{steps.vars.outputs.sha_short}} - PYTHON_VERSION: ${{env.PYTHON_VERSION}} - run: | - ./appimage-builder --recipe appimage/AppImageBuilder.yml - - - name: Create release folder - run: | - folder='Twitch Drops Miner' - mkdir "${folder}" - cp *.AppImage manual.txt "${folder}" - 7z a Twitch.Drops.Miner.Linux.AppImage.zip "${folder}" - - - name: Upload build artifact - uses: actions/upload-artifact@v4 - with: - if-no-files-found: error - name: Twitch.Drops.Miner.Linux.AppImage - path: Twitch.Drops.Miner.Linux.AppImage.zip - - update_releases_page: - name: Upload builds to Releases - if: github.event_name != 'pull_request' - needs: - - windows - - linux-pyinstaller - - linux-appimage - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - name: Set up variables - id: vars - run: | - echo "date_now=$(date --rfc-3339=seconds)" >> "${GITHUB_OUTPUT}" - - - name: Download build artifacts from previous jobs - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Read patch notes from file - id: read_patch_notes - run: | - PATCH_NOTES=$(cat patch_notes.txt) - echo "patch_notes=$PATCH_NOTES" >> $GITHUB_ENV - - - name: Upload builds to Releases - uses: ncipollo/release-action@v1 - with: - allowUpdates: true - artifactErrorsFailBuild: true - artifacts: artifacts/*/* - body: | - # ⚠️ Please help with translation as tracked in #2 ! - - *** - **This is an automatically generated updated version of the application, that includes the latest master branch changes.** - **This build should be stable, but if you encounter anything, please reoirt any issues you find.** - - - Last build date: `${{ steps.vars.outputs.date_now }}` - - Reference commit: ${{ github.sha }} - - *** - ## Patch notes: - ${{ env.patch_notes }} - - name: Updated build - prerelease: false - removeArtifacts: true - tag: v15 From dd35e8b301011bc778533192f3ffd634be1f0653 Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Fri, 17 May 2024 20:46:26 +0200 Subject: [PATCH 027/122] Update Master (#27) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updated Italian translation.json * Update README.md to include credit for adjusted translations * Updated ci.yml (build-) workflow to better reflect usage in this fork * Added start timestamp to gui from pull request from original repo * removed unnecessary print * added patch notes to pre-release workflow * updated credits and workflows, created patch notes * Update spanish translation (#16) * Update Simplified Chinese Translation (#15) Simplified Chinese (简体中文) translation updated. * CHanged credits * updated check patch notes workflow * Update Release.yml * Delete .github/workflows/Release.yml * fixed patch notes workflow branch * updated workflows * updatech check patch notes workflow * updated ci.yml * updated ci workflow --------- Co-authored-by: Kuddus73 <127908708+Kuddus73@users.noreply.github.com> Co-authored-by: Arne Weber Co-authored-by: VSeryi Co-authored-by: 残影 <9458793+BreakshadowCN@users.noreply.github.com> --- .github/workflows/Check_patch_notes.yml | 37 +++++++++++++++++-------- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/.github/workflows/Check_patch_notes.yml b/.github/workflows/Check_patch_notes.yml index f94ee248..334de991 100644 --- a/.github/workflows/Check_patch_notes.yml +++ b/.github/workflows/Check_patch_notes.yml @@ -3,22 +3,35 @@ name: Check patch notes on: pull_request: branches: - - main + - in-dev workflow_dispatch: jobs: - check_documentation: - runs-on: ubuntu-latest + check_patch_notes: + runs-on: 'ubuntu-20.04' steps: - name: Checkout code - uses: actions/checkout@v4 - - - name: Check for patch notes changes + uses: actions/checkout@v2 + with: + # Checkout as many commits as needed for the diff + fetch-depth: 2 + - shell: pwsh + # Give an id to the step, so we can reference it later + id: check_file_changed run: | - if git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep -q '^patch_notes.txt$'; then - echo "Patch notes updated." - else - echo "Update patch notes!" - exit 1 - fi \ No newline at end of file + # Diff HEAD with the previous commit + $diff = git diff --name-only HEAD^ HEAD + + # Check if a file under docs/ or with the .md extension has changed (added, modified, deleted) + $SourceDiff = $diff | Where-Object { $_ -match 'patch_notes.txt' } + $HasDiff = $SourceDiff.Length -gt 0 + + # Set the output named "docs_changed" + Write-Host "::set-output name=docs_changed::$HasDiff" + + # Run the step only with "docs_changed" equals "False" + - shell: pwsh + # steps..outputs. + if: steps.check_file_changed.outputs.docs_changed == 'False' + run: exit 1 \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4ca2fb7..9d4274cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -195,8 +195,8 @@ jobs: path: Twitch.Drops.Miner.Linux.AppImage.zip update_releases_page: + if: github.event.pull_request.merged == true || github.event_name == 'push' name: Upload builds to Releases - if: github.event_name != 'pull_request' needs: - windows - linux-pyinstaller diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ecc54011..8e31736f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -194,7 +194,7 @@ jobs: update_releases_page: name: Upload builds to Releases - if: github.event_name != 'pull_request' + if: github.event.pull_request.merged == true needs: - windows - linux-pyinstaller From 6e8f88401610f2f70794e451ff9cce6eed073045 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 17 May 2024 21:15:13 +0200 Subject: [PATCH 028/122] updated workflows --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d4274cf..1d96baf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -195,7 +195,7 @@ jobs: path: Twitch.Drops.Miner.Linux.AppImage.zip update_releases_page: - if: github.event.pull_request.merged == true || github.event_name == 'push' + #NOTEif: github.event.pull_request.merged == true || github.event_name == 'push' name: Upload builds to Releases needs: - windows diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8e31736f..a26e64bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -194,7 +194,7 @@ jobs: update_releases_page: name: Upload builds to Releases - if: github.event.pull_request.merged == true + #NOTEif: github.event.pull_request.merged == true needs: - windows - linux-pyinstaller From ae11bd49a37bcb25d98067b84fff5b2c5f9ccf48 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 17 May 2024 21:15:13 +0200 Subject: [PATCH 029/122] updated workflows --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d4274cf..1d96baf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -195,7 +195,7 @@ jobs: path: Twitch.Drops.Miner.Linux.AppImage.zip update_releases_page: - if: github.event.pull_request.merged == true || github.event_name == 'push' + #NOTEif: github.event.pull_request.merged == true || github.event_name == 'push' name: Upload builds to Releases needs: - windows diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8e31736f..a26e64bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -194,7 +194,7 @@ jobs: update_releases_page: name: Upload builds to Releases - if: github.event.pull_request.merged == true + #NOTEif: github.event.pull_request.merged == true needs: - windows - linux-pyinstaller From 74beaa4bfc5b787e7858c297660efb8366fefd66 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 17 May 2024 21:34:13 +0200 Subject: [PATCH 030/122] Updated release workflow --- .github/workflows/release.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a26e64bc..08b5c679 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -213,12 +213,11 @@ jobs: uses: actions/download-artifact@v4 with: path: artifacts - + - name: Read patch notes from file - id: read_patch_notes - run: | - PATCH_NOTES=$(cat patch_notes.txt) - echo "patch_notes=$PATCH_NOTES" >> $GITHUB_ENV + uses: juliangruber/read-file-action@v1.1.7 + with: + path: ./patch_notes.txt - name: Upload builds to Releases uses: ncipollo/release-action@v1 @@ -238,7 +237,7 @@ jobs: *** ## Patch notes: - ${{ env.patch_notes }} + ${{ steps.package.outputs.content }} name: Updated build prerelease: false From 45fcded5c2f9224b02b56edc53babc0f3b38c357 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 17 May 2024 21:34:13 +0200 Subject: [PATCH 031/122] Updated release workflow --- .github/workflows/release.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a26e64bc..08b5c679 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -213,12 +213,11 @@ jobs: uses: actions/download-artifact@v4 with: path: artifacts - + - name: Read patch notes from file - id: read_patch_notes - run: | - PATCH_NOTES=$(cat patch_notes.txt) - echo "patch_notes=$PATCH_NOTES" >> $GITHUB_ENV + uses: juliangruber/read-file-action@v1.1.7 + with: + path: ./patch_notes.txt - name: Upload builds to Releases uses: ncipollo/release-action@v1 @@ -238,7 +237,7 @@ jobs: *** ## Patch notes: - ${{ env.patch_notes }} + ${{ steps.package.outputs.content }} name: Updated build prerelease: false From 0a3b70c6b0bda7e71ced48b758ec14bef852af38 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 17 May 2024 22:01:45 +0200 Subject: [PATCH 032/122] Updated release workflow --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 08b5c679..f7312326 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -214,6 +214,9 @@ jobs: with: path: artifacts + - name: Checkout repository + uses: actions/checkout@v3 + - name: Read patch notes from file uses: juliangruber/read-file-action@v1.1.7 with: From 0048e4d053c8e72a3d0927cba7af3755adfdc2e2 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 01:06:14 +0200 Subject: [PATCH 033/122] I think this should actually fix this workflow --- .github/workflows/release.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 49aa4587..934b36a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -214,10 +214,8 @@ jobs: with: path: artifacts - - name: Checkout repository - uses: actions/checkout@v3 - - name: Read patch notes from file + id: patch_notes uses: juliangruber/read-file-action@v1.1.7 with: path: ./patch_notes.txt @@ -240,7 +238,7 @@ jobs: *** ## Patch notes: - ${{ steps.package.outputs.content }} + ${{ steps.patch_notes.outputs.content }} name: Updated build prerelease: false From 1b169c06db6056b2ca8295e9af5f63ffb40143db Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 01:06:14 +0200 Subject: [PATCH 034/122] I think this should actually fix this workflow --- .github/workflows/release.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 49aa4587..934b36a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -214,10 +214,8 @@ jobs: with: path: artifacts - - name: Checkout repository - uses: actions/checkout@v3 - - name: Read patch notes from file + id: patch_notes uses: juliangruber/read-file-action@v1.1.7 with: path: ./patch_notes.txt @@ -240,7 +238,7 @@ jobs: *** ## Patch notes: - ${{ steps.package.outputs.content }} + ${{ steps.patch_notes.outputs.content }} name: Updated build prerelease: false From a0091dbd74777d7de781375fa5d6b21ba6a73066 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 01:26:10 +0200 Subject: [PATCH 035/122] maybe the release workflow will work this time... --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 934b36a8..431dd611 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -204,6 +204,9 @@ jobs: contents: write steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Set up variables id: vars run: | From c9cd4adadaf0357567f4d10885cd05421560ecad Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 01:26:10 +0200 Subject: [PATCH 036/122] maybe the release workflow will work this time... --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 934b36a8..431dd611 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -204,6 +204,9 @@ jobs: contents: write steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Set up variables id: vars run: | From f894aa5a367a8dddccfae2a34ec1c30870c0ca9e Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 02:11:15 +0200 Subject: [PATCH 037/122] Hopefully, release workflow should do versioning --- .github/workflows/release.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 431dd611..6636c2eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -206,7 +206,14 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v3 - + + - name: Get next version + uses: reecetech/version-increment@2024.4.3 + id: version + with: + scheme: semver + increment: minor + - name: Set up variables id: vars run: | @@ -246,4 +253,4 @@ jobs: name: Updated build prerelease: false removeArtifacts: true - tag: v15 + tag: ${{ steps.version.outputs.v-version }} From c93a8f2b99866e12867f32f416035eaee5a644d8 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 02:11:15 +0200 Subject: [PATCH 038/122] Hopefully, release workflow should do versioning --- .github/workflows/release.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 431dd611..6636c2eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -206,7 +206,14 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v3 - + + - name: Get next version + uses: reecetech/version-increment@2024.4.3 + id: version + with: + scheme: semver + increment: minor + - name: Set up variables id: vars run: | @@ -246,4 +253,4 @@ jobs: name: Updated build prerelease: false removeArtifacts: true - tag: v15 + tag: ${{ steps.version.outputs.v-version }} From ed098b8f5c9f290fff597bc3fcd2921073360a96 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 02:31:24 +0200 Subject: [PATCH 039/122] finalized updates to release workflow --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6636c2eb..e4dc099a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -250,7 +250,7 @@ jobs: ## Patch notes: ${{ steps.patch_notes.outputs.content }} - name: Updated build + name: Updated tested build - ${{ steps.version.outputs.v-version }} prerelease: false removeArtifacts: true tag: ${{ steps.version.outputs.v-version }} From 7df2d42a9620f55d213df7a7af5ac5e4360dfaea Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 17 May 2024 20:16:51 +0300 Subject: [PATCH 040/122] Update Russian Translation --- ...\240\321\203\321\201\321\201\320\272\320\270\320\271.json" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" "b/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" index 96350941..e281d6d7 100644 --- "a/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" +++ "b/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" @@ -154,9 +154,9 @@ "campaigns": "Все кампании Twitch" }, "how_it_works": "Как это работает?", - "how_it_works_text": "Каждые ~60 секунд приложение отправляет событие \"минутный просмотр\" на просматриваемый канал. \nЭтого достаточно, чтобы получить Drop. Таким образом, нет необходимости скачивать поток, что экономит трафик. \nДля поддержания актуального состояния каналов в режиме онлайн или офлайн устанавливается соединение websocket, которое проверяет состояние каналов.", + "how_it_works_text": "Каждые ~20 секунд приложение запрашивает у Twitch URL-адрес необработанных данных потока канала, который просматривается в данный момент. Затем он извлекает метаданные этого потока данных. \nЭтого достаточно, чтобы получить Drop. Таким образом, нет необходимости скачивать поток, что экономит трафик. \nДля поддержания актуального состояния каналов в режиме онлайн или офлайн устанавливается соединение websocket, которое проверяет состояние каналов.", "getting_started": "Первые шаги", - "getting_started_text": "• Войдите в приложение.\n• Убедитесь, что аккаунт Twitch связан со всеми кампаниями, к которым есть интерес.\n• Если вы хотите редактировать все Drops, снимите флажок \"Только приоритет\" и нажмите \"Перезагрузить\".\n• Если необходимо смотреть только определенные игры, используйте список \"Приоритет\", чтобы сузить выбор игр.\n• В списке приоритеты расставлены сверху вниз.\n• Опция \"Только приоритет\" предотвращает просмотр игр, не входящих в список приоритетов.\n• С помощью списка \"Исключения\" можно отфильтровать игры, которые не должны рассматриваться.\n• Если списки или опции были изменены, нажмите \"Перезагрузить\", чтобы изменения были применены." + "getting_started_text": "1. Войдите в приложение.\n2. Убедитесь, что аккаунт Twitch связан со всеми кампаниями, к которым есть интерес.\n3. Если вы хотите редактировать все Drops, снимите флажок \"Только приоритет\" и нажмите \"Перезагрузить\".\n4. Если необходимо смотреть только определенные игры, используйте список \"Приоритет\", чтобы сузить выбор игр.\n5. В списке приоритеты расставлены сверху вниз.\n6. Опция \"Только приоритет\" предотвращает просмотр игр, не входящих в список приоритетов.\n7. С помощью списка \"Исключения\" можно отфильтровать игры, которые не должны рассматриваться.\n8. Если списки или опции были изменены, нажмите \"Перезагрузить\", чтобы изменения были применены." } } } From dbdc97573e109ddb5d05671d6f7042523c6330bb Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 17 May 2024 20:23:41 +0300 Subject: [PATCH 041/122] Update Ukrainian Translation --- ...20\260\321\227\320\275\321\201\321\214\320\272\320\260.json" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" index c9b324c4..40586677 100644 --- "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" +++ "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" @@ -154,7 +154,7 @@ "campaigns": "Переглянути усі кампанії та керувати пов'язаними обліковими записами" }, "how_it_works": "Як це працює?", - "how_it_works_text": "Приблизно кожні 60 секунд програма надсилає подію \"переглянуто хвилину\" на канал, який зараз переглядається - цього достатньо, щоб здобувати дропи. Зауважте, що це повністю обходить необхідність завантажувати будь-які потокові відео та звук. Щоб підтримувати актуальний стан каналів (ОНЛАЙН або ОФЛАЙН), встановлюється з'єднання з веб-сокетом, який отримує події про збільшення або зменшення кількості трансляцій, або оновлення поточної кількості глядачів.", + "how_it_works_text": "Кожні ~20 секунд програма запитує у Twitch URL-адресу необроблених даних потоку каналу, який зараз переглядається. Потім він отримує метадані цього потоку даних. Цього достатньо, щоб здобувати дропи. Зауважте, що це повністю обходить необхідність завантажувати будь-які потокові відео та звук. Щоб підтримувати актуальний стан каналів (ОНЛАЙН або ОФЛАЙН), встановлюється з'єднання з веб-сокетом, який отримує події про збільшення або зменшення кількості трансляцій, або оновлення поточної кількості глядачів.", "getting_started": "Інструкція", "getting_started_text": "1. Увійдіть в додаток.\n2. Переконайтеся, що ваш обліковий запис Twitch пов'язаний з усіма обліковими записами ігор, з яких ви хочете здобувати дропи.\n3. Якщо ви зацікавлені у здобуванні всього, зніміть прапорець \"Тільки пріоритет\" і натисніть \"Перезавантажити\".\n4. Якщо ви хочете здобувати з певних ігор, скористайтеся списком \"Пріоритет\", щоб створити впорядкований список ігор за вашим вибором. Ігри будуть здобуватися в порядку розташування в списку.\n5. Не знімайте прапорець \"Тільки пріоритет\", щоб уникнути здобування з ігор, які не входять до пріоритетного списку. Або ні - вирішувати вам.\n6. Використовуйте список \"Виключено\", щоб вказати застосунку, з яких ігор ніколи не слід здобувати.\n7. Зміна вмісту будь-якого зі списків або зміна стану опції \"Тільки пріоритет\" вимагає натискання кнопки \"Перезавантажити\" для набуття змінами чинності.\n\nПереклад виконав Дмитро Зозуля" } From b4cec670a45f91ae6cfb005f211fd13365738a55 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 17 May 2024 20:24:51 +0300 Subject: [PATCH 042/122] Update patch_notes.txt --- patch_notes.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patch_notes.txt b/patch_notes.txt index 5a3ef286..d15479c1 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,3 +1,3 @@ ### 17.5.2024 -- Updated Italian, Simplified Chineese and Spanish translation as well as corresponding credits -- Various changes to github workflows \ No newline at end of file +- Updated Italian, Simplified Chineese, Spanish, Russian and Ukrainian translation as well as corresponding credits +- Various changes to github workflows From 4e3767d03d1d8b19eeb371614ccd063204bb304e Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Fri, 17 May 2024 20:25:53 +0300 Subject: [PATCH 043/122] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5eb7bf37..e5b45c77 100644 --- a/README.md +++ b/README.md @@ -130,4 +130,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN - For updating Translations. +@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98 - For updating Translations. From 0fcb9675b64070ce4cb1316572415b56c13e68f2 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 15:26:14 +0200 Subject: [PATCH 044/122] another attempt at auto-checking patch notes --- .github/workflows/Check_patch_notes.yml | 35 ++++++++----------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/.github/workflows/Check_patch_notes.yml b/.github/workflows/Check_patch_notes.yml index 334de991..45084979 100644 --- a/.github/workflows/Check_patch_notes.yml +++ b/.github/workflows/Check_patch_notes.yml @@ -8,30 +8,17 @@ on: jobs: check_patch_notes: - runs-on: 'ubuntu-20.04' - + runs-on: ubuntu-latest # windows-latest | macos-latest + name: Test changed-files steps: - - name: Checkout code - uses: actions/checkout@v2 + - uses: actions/checkout@v2 with: - # Checkout as many commits as needed for the diff - fetch-depth: 2 - - shell: pwsh - # Give an id to the step, so we can reference it later - id: check_file_changed - run: | - # Diff HEAD with the previous commit - $diff = git diff --name-only HEAD^ HEAD - - # Check if a file under docs/ or with the .md extension has changed (added, modified, deleted) - $SourceDiff = $diff | Where-Object { $_ -match 'patch_notes.txt' } - $HasDiff = $SourceDiff.Length -gt 0 - - # Set the output named "docs_changed" - Write-Host "::set-output name=docs_changed::$HasDiff" - - # Run the step only with "docs_changed" equals "False" - - shell: pwsh - # steps..outputs. - if: steps.check_file_changed.outputs.docs_changed == 'False' + fetch-depth: 2 # "0" OR "2" -> To retrieve the preceding commit. + + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v9.2 + + - name: Run when patch noted don't change + if: ${{ !contains(steps.changed-files.outputs.modified_files, 'patch_notes.txt') }} run: exit 1 \ No newline at end of file From 24d189ebf72725909bc1341860af0d25962e3c03 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 15:30:13 +0200 Subject: [PATCH 045/122] updated patch notes with accurate date --- patch_notes.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/patch_notes.txt b/patch_notes.txt index d15479c1..0780cf14 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,3 +1,7 @@ -### 17.5.2024 -- Updated Italian, Simplified Chineese, Spanish, Russian and Ukrainian translation as well as corresponding credits +### 18.5.2024 +- Updated Russian and Ukrainian translation as well as corresponding credits - Various changes to github workflows + +### 17.5.2024 +- Updated Italian, Simplified Chineese and Spanish translation as well as corresponding credits +- Various changes to github workflows \ No newline at end of file From 643925ac9e1533dabd0f5ef1d6a69c48cf8aea5a Mon Sep 17 00:00:00 2001 From: zelda0079 Date: Sat, 18 May 2024 19:31:30 +0800 Subject: [PATCH 046/122] =?UTF-8?q?Update=20=E7=B9=81=E9=AB=94=E4=B8=AD?= =?UTF-8?q?=E6=96=87.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\351\253\224\344\270\255\346\226\207.json" | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git "a/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" "b/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" index fd3bcf3a..ef226783 100644 --- "a/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" +++ "b/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" @@ -1,46 +1,46 @@ { "english_name": "Traditional Chinese", "status": { - "terminated": "\n應用程式已結束運行,請關閉窗口已退出應用程式。", + "terminated": "\n應用程序已終止,請關閉窗口以退出應用程序。", "watching": "正在觀看: {channel}", - "goes_online": "{channel} 該頻道已開始實況, 正在跳轉...", - "goes_offline": "{channel} 該頻道已結束實況, 正在跳轉...", + "goes_online": "{channel} 該頻道已上線, 正在切換...", + "goes_offline": "{channel} 該頻道已離線, 正在切換...", "claimed_drop": "領取的掉寶: {drop}", "claimed_points": "領取的積分獎勵: {points}", - "earned_points": "觀看實況獲得積分: {points}, 總積分: {balance}", - "no_channel": "沒有可觀看的實況,等待一個可領取掉寶的實況開始實況...", + "earned_points": "觀看直播獲得積分: {points}, 總積分: {balance}", + "no_channel": "沒有可觀看的頻道,等待一個在線直播頻道...", "no_campaign": "沒有可用於掉寶的活動,等待一個有效的掉寶活動..." }, "login": { "chrome": { - "startup": "正在開啟Chrome瀏覽器...", - "login_to_complete": "請再次點擊登錄已完成登錄.", + "startup": "正在打開Chrome瀏覽器...", + "login_to_complete": "請再次點擊登錄按鈕來完成登陸.", "no_token": "無法獲取授權令牌.", - "closed_window": "在登錄完成之前,Chrome瀏覽器已被關閉." + "closed_window": "在登錄完成之前關閉了Chrome瀏覽器." }, - "error_code": "登錄出現錯誤: {error_code}", - "unexpected_content": "返回的內容類型有誤,通常是由於被重新定向,您需要設置VPN或者確認登錄頁面才能連上網路嗎?", - "incorrect_login_pass": "帳號或密碼錯誤.", - "incorrect_email_code": "電子郵件驗證碼錯誤.", + "error_code": "登錄出錯: {error_code}", + "unexpected_content": "返回的內容類型有誤通常是由於被重定向.您需要設置VPN或者確認登錄頁面才能聯網嗎?", + "incorrect_login_pass": "用戶名或密碼錯誤.", + "incorrect_email_code": "電子郵箱驗證碼錯誤.", "incorrect_twofa_code": "雙重驗證2FA令牌錯誤.", - "email_code_required": "需要電子信箱驗證碼,請查看你的信箱.", + "email_code_required": "需要電子郵件驗證碼 查看你的郵件.", "twofa_code_required": "需要雙重驗證2FA令牌." }, "error": { - "captcha": "您的登錄存在異常,Twitch官方已進行限制,請在12小時後重試.", - "site_down": "Twitch無法連接,{seconds} 秒後重試...", - "no_connection": "無法連接到Twitch,請確認已經開啟VPN並添加了代理,{seconds} 秒後重試..." + "captcha": "您的登錄存在異常,Twitch官方已進行限制,請在12小時后重試.", + "site_down": "Twitch無法連接,{seconds} 秒后重試...", + "no_connection": "無法連接到Twitch,請確保已經開啟VPN並添加了代理,{seconds} 秒后重試..." }, "gui": { - "output": "輸出日誌", + "output": "輸出日志", "status": { "name": "狀態", "idle": "已完成獲取", "exiting": "正在退出...", - "terminated": "應用程式已終止", + "terminated": "應用已終止運行", "cleanup": "清除頻道中...", - "gathering": "搜索實況頻道...", - "switching": "切換實況頻道...", + "gathering": "搜索直播頻道...", + "switching": "切換直播頻道中...", "fetching_inventory": "獲取庫存中...", "fetching_campaigns": "獲取掉寶活動...", "adding_campaigns": "將掉寶活動列表添加至庫存... {counter}" @@ -53,38 +53,38 @@ }, "tray": { "notification_title": "開始掉寶活動", - "minimize": "視窗最小化,縮至右下角", + "minimize": "窗口最小化", "show": "掉寶活動", "quit": "退出" }, "login": { - "name": "登錄Twtich帳號", + "name": "登錄Twitch賬號", "labels": "狀態:\n用戶ID:", "logged_in": "已登錄", "logged_out": "未登錄", "logging_in": "正在登錄中...", "required": "請先登錄", "request": "請先登錄以訪問更多內容.", - "username": "帳號", + "username": "用戶名", "password": "密碼", - "twofa_code": "信箱2FA令牌", + "twofa_code": "郵箱2FA令牌", "button": "登錄" }, "websocket": { - "name": "網路協議連接狀態", + "name": "網絡協議連接狀態", "websocket": "Websocket #{id}:", "initializing": "初始化...", "connected": "已連接", "disconnected": "斷開連接", "connecting": "連接中...", - "disconnecting": "斷開連接...", + "disconnecting": "斷開連接中...", "reconnecting": "重新連接中..." }, "progress": { "name": "掉寶活動進度", "drop": "掉寶獎勵:", "game": "遊戲:", - "remaining": "剩餘 {time}", + "remaining": "剩余 {time}", "campaign": "掉寶活動名稱:", "drop_progress": "掉寶進度:", "campaign_progress": "活動進度:" @@ -92,15 +92,15 @@ "channels": { "name": "活動頻道", "switch": "切換", - "load_points": "讀取積分", + "load_points": "加載積分", "online": "ONLINE \u2714", "pending": "OFFLINE \u23f3", "offline": "OFFLINE \u274c", "headings": { - "channel": "實況頻道", + "channel": "直播頻道", "game": "遊戲", "points": "積分", - "status": "在現狀態", + "status": "在線狀態", "viewers": "觀眾" } }, @@ -108,18 +108,18 @@ "filter": { "name": "篩選", "show": "掉寶活動:", - "not_linked": "未連結", + "not_linked": "未關聯賬戶的遊戲掉寶", "expired": "已結束", "excluded": "未添加的掉寶活動", - "upcoming": "即將開啟", + "upcoming": "即將上線", "finished": "已完成", "refresh": "刷新" }, "status": { - "linked": "已連結 \u2714", - "not_linked": "未連結帳戶 \u274c", + "linked": "已關聯 \u2714", + "not_linked": "未關聯賬戶 \u274c", "active": "已上線 \u2714", - "upcoming": "即將開啟 \u23f3", + "upcoming": "即將上線 \u23f3", "expired": "已結束 \u274c", "claimed": "已領取 \u2714", "ready_to_claim": "可以領取 \u23f3" @@ -134,9 +134,10 @@ }, "settings": { "general": { - "name": "功能設定", - "autostart": "開機自動啟動: ", - "tray": "開機自動啟動並最小化: ", + "name": "功能設置", + "autostart": "開機自啟動: ", + "tray": "開機自啟動並最小化: ", + "tray_notifications": "啟用托盤通知: ", "priority_only": "僅參與優先掉寶遊戲: ", "proxy": "代理:" }, @@ -144,18 +145,18 @@ "priority": "優先掉寶遊戲", "exclude": "不參與掉寶遊戲", "reload": "刷新", - "reload_text": "大多數設定更改後,需要重新啟動軟件或刷新才能生效: " + "reload_text": "大多數設置更改后需要重新啟動軟件或刷新才能生效: " }, "help": { "links": { "name": "幫助", "inventory": "查看Twitch庫存", - "campaigns": "查看所有掉寶活動並管理連結帳號" + "campaigns": "查看所有掉寶活動並管理連接賬號" }, "how_it_works": "工作原理", - "how_it_works_text": "每隔約60秒,應用程式會向當前正在觀看的實況頻道發送一個“觀看了一分鐘”的事件 - 這足以推進掉寶進度。這完全不需要下載任何實際影片串流和聲音。為了使頻道的狀態(在線或離線)保持最新狀態,建立了websocket連接,用於接受有關實況開始及結束事件,或當前觀眾數量的更新。", - "getting_started": "開始設定", - "getting_started_text": "1.登錄應用程式。\n2.確保所有感興趣挖掘的遊戲的帳號已連結到您的Twitch帳號。\n3.如果您想挖掘所有掉寶,請不要勾選“僅參與優先掉寶遊戲”,然後按“刷新”。\n4.如果您想優先挖掘特定遊戲,請使用“優先掉寶遊戲”列表設置您想挖掘的遊戲的優先順序。應用程式將嘗試先挖掘列表頂部的遊戲,然後再挖掘後面的遊戲。\n5.勾選“僅參與優先掉寶遊戲”時不會挖掘不在優先列表中的遊戲。勾不勾選取決於你。\n6.使用“不參與掉寶遊戲”列表設置永不挖掘的遊戲。\n7.更改任一列表的內容,或更改“僅參與優先掉寶遊戲”勾選狀態,需要手動按“刷新”才能使更改生效。" - } + "how_it_works_text": "每隔約 20 秒,程序就會向 Twitch 詢問當前正在觀看的頻道的原始數據流 URL。然后,它會獲取這個數據流的元數據。 - 這足以推進掉寶進度。這完全不需要下載任何實際的視頻流和音頻流。為了使頻道的狀態(在線或離線)保持最新,程序會建立 Websocket 連接,用於接收有關頻道開播和下播的事件,並更新當前的觀眾數量。", + "getting_started": "入門設置", + "getting_started_text": "1. 登錄應用程序。\n2.確保所有感興趣挖掘的遊戲的賬號已連接到您的Twitch賬號。\n3.如果您想挖掘所有掉寶,請不要勾選“僅參與優先掉寶遊戲”,然后按“刷新”。\n4.如果您想優先挖掘特定遊戲,請使用“優先掉寶遊戲”列表設置您想挖掘的遊戲的優先順序。程序將嘗試先挖掘列表頂部的遊戲,然后再挖掘后邊的遊戲。\n5.勾選“僅參與優先掉寶遊戲”時,不會挖掘不在優先列表中的遊戲。勾不勾選取決於你。\n6。使用“不參與掉寶遊戲”列表設置永不挖掘的遊戲。\n7.更改任一列表的內容,或更改“僅參與優先掉寶遊戲”勾選狀態,需要手動按“刷新”才能使更改生效。" + } } } From 72f0744e0238912d5bb65677c0977a82f492e2ed Mon Sep 17 00:00:00 2001 From: zelda0079 Date: Sat, 18 May 2024 21:28:13 +0800 Subject: [PATCH 047/122] Update patch_notes.txt --- patch_notes.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/patch_notes.txt b/patch_notes.txt index 0780cf14..e8110752 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -3,5 +3,8 @@ - Various changes to github workflows ### 17.5.2024 -- Updated Italian, Simplified Chineese and Spanish translation as well as corresponding credits -- Various changes to github workflows \ No newline at end of file +- Updated Italian, Simplified Chinese and Spanish translation as well as corresponding credits +- Various changes to github workflows + +### 18.5.2024 +- Updated Traditional Chinese From 4d270fa1c256664209254bb0b26d98ff5c6c3e19 Mon Sep 17 00:00:00 2001 From: zelda0079 Date: Sat, 18 May 2024 21:28:43 +0800 Subject: [PATCH 048/122] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e5b45c77..257df7bd 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @alikdb - For the entirety of the Turkish (Türkçe) translation. @roobini-gamer - For the entirety of the French (Français) translation. @Sergo1217 - For the entirety of the Russian (Русский) translation. -@Ricky103403 - For the entirety of the Traditional Chinese (繁體中文) translation. +@Ricky103403 @zelda0079- For the entirety of the Traditional Chinese (繁體中文) translation. @Patriot99 - For the Polish (Polski) translation (co-authored with @DevilXD). @Nollasko - For the entirety of the Ukrainian (Українська) translation. @casungo - For the entirety of the Italian (Italiano) translation. From cb517a06e1aa41c50dc0a9f261a6e11d27a70834 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 18 May 2024 15:46:14 +0200 Subject: [PATCH 049/122] readme and patch notes update --- README.md | 4 ++-- patch_notes.txt | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 257df7bd..3939679e 100644 --- a/README.md +++ b/README.md @@ -123,11 +123,11 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @alikdb - For the entirety of the Turkish (Türkçe) translation. @roobini-gamer - For the entirety of the French (Français) translation. @Sergo1217 - For the entirety of the Russian (Русский) translation. -@Ricky103403 @zelda0079- For the entirety of the Traditional Chinese (繁體中文) translation. +@Ricky103403 - For the entirety of the Traditional Chinese (繁體中文) translation. @Patriot99 - For the Polish (Polski) translation (co-authored with @DevilXD). @Nollasko - For the entirety of the Ukrainian (Українська) translation. @casungo - For the entirety of the Italian (Italiano) translation. @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98 - For updating Translations. +@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079 - For updating Translations. diff --git a/patch_notes.txt b/patch_notes.txt index e8110752..85cb9cc0 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,10 +1,7 @@ ### 18.5.2024 -- Updated Russian and Ukrainian translation as well as corresponding credits +- Updated Russian, Ukrainian and Traditional Chinese translation as well as corresponding credits - Various changes to github workflows ### 17.5.2024 - Updated Italian, Simplified Chinese and Spanish translation as well as corresponding credits -- Various changes to github workflows - -### 18.5.2024 -- Updated Traditional Chinese +- Various changes to github workflows \ No newline at end of file From 9b41a32e493d9dd70d3dc1101bb0f11e4a5a05d0 Mon Sep 17 00:00:00 2001 From: Calvineries Date: Sat, 18 May 2024 16:43:56 +0200 Subject: [PATCH 050/122] =?UTF-8?q?Update=20Fran=C3=A7ais.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "lang/Fran\303\247ais.json" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/lang/Fran\303\247ais.json" "b/lang/Fran\303\247ais.json" index 5f532e3a..238d9550 100644 --- "a/lang/Fran\303\247ais.json" +++ "b/lang/Fran\303\247ais.json" @@ -154,7 +154,7 @@ "campaigns": "Afficher toutes les campagnes et gérer les comptes associés" }, "how_it_works": "Comment ça fonctionne", - "how_it_works_text": "Environ toutes les ~60 secondes, l'application envoie un événement \"minute regardée\" à la chaîne qui est actuellement en cours de visionnage - ce qui suffit pour faire avancer les drops. Notez que cela contourne complètement le besoin de télécharger la vidéo et le son du flux réel. Pour maintenir à jour le statut (EN LIGNE ou HORS LIGNE) des chaînes, une connexion websocket est établie pour recevoir des événements sur les flux qui montent ou descendent, ou des mises à jour concernant le nombre actuel de spectateurs.", + "how_it_works_text": "Toutes les ~20 secondes, l'application demande à Twitch une URL vers les données brutes du flux de la chaîne actuellement regardée. Elle récupère ensuite les métadonnées de ce flux de données - ce qui suffit pour faire avancer les drops. Notez que cela contourne complètement le besoin de télécharger la vidéo et le son du flux réel. Pour maintenir à jour le statut (EN LIGNE ou HORS LIGNE) des chaînes, une connexion websocket est établie pour recevoir des événements sur les flux qui montent ou descendent, ou des mises à jour concernant le nombre actuel de spectateurs.", "getting_started": "Premiers pas", "getting_started_text": "1. Connectez-vous à l'application.\n2. Assurez-vous que votre compte Twitch est lié à toutes les campagnes qui vous intéressent.\n3. Si vous voulez simplement miner tout, décochez \"Priorité uniquement\" et appuyez sur \"Recharger\".\n4. Si vous souhaitez miner d'abord certains jeux, utilisez la liste \"Priorité\" pour définir une liste ordonnée des jeux de votre choix. Les jeux en haut de la liste seront tentés d'être minés en premier, avant ceux plus bas dans la liste.\n5. Laissez l'option \"Priorité uniquement\" cochée pour éviter de miner des jeux qui ne sont pas dans la liste de priorité. Ou pas - c'est à vous de décider.\n6. Utilisez la liste \"Exclure\" pour indiquer à l'application les jeux qui ne doivent jamais être minés.\n7. Modifier le contenu de l'une des listes ou changer l'état de l'option \"Priorité uniquement\" nécessite d'appuyer sur \"Recharger\" pour que les changements prennent effet." } From 13545cc3df52e355fc7cef40b71aa1071ba14890 Mon Sep 17 00:00:00 2001 From: Calvineries Date: Sun, 19 May 2024 10:41:30 +0200 Subject: [PATCH 051/122] Update patch_notes.txt --- patch_notes.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/patch_notes.txt b/patch_notes.txt index 85cb9cc0..9517966e 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,7 +1,10 @@ +### 19.5.2024 +- Updated French translation as well as corresponding credits + ### 18.5.2024 - Updated Russian, Ukrainian and Traditional Chinese translation as well as corresponding credits - Various changes to github workflows ### 17.5.2024 - Updated Italian, Simplified Chinese and Spanish translation as well as corresponding credits -- Various changes to github workflows \ No newline at end of file +- Various changes to github workflows From de2b66bfa391a290d58defd080d5f40853486856 Mon Sep 17 00:00:00 2001 From: Calvineries Date: Sun, 19 May 2024 10:42:12 +0200 Subject: [PATCH 052/122] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3939679e..974bd023 100644 --- a/README.md +++ b/README.md @@ -130,4 +130,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079 - For updating Translations. +@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries - For updating Translations. From 3af6997b7c8ffe13fdcac4881e82dfbadd6c508a Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sun, 19 May 2024 19:04:02 +0200 Subject: [PATCH 053/122] added commit hash to release --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e4dc099a..901f63df 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -218,6 +218,7 @@ jobs: id: vars run: | echo "date_now=$(date --rfc-3339=seconds)" >> "${GITHUB_OUTPUT}" + Add-Content $env:GITHUB_OUTPUT "sha_short=$(git rev-parse --short HEAD)" - name: Download build artifacts from previous jobs uses: actions/download-artifact@v4 @@ -250,7 +251,7 @@ jobs: ## Patch notes: ${{ steps.patch_notes.outputs.content }} - name: Updated tested build - ${{ steps.version.outputs.v-version }} + name: Updated tested build - ${{ steps.version.outputs.v-version }} (${{ steps.vars.outputs.sha_short }}) prerelease: false removeArtifacts: true tag: ${{ steps.version.outputs.v-version }} From 75404ecdb10911917f7950b862a8dbf754a0c62f Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sun, 19 May 2024 19:07:07 +0200 Subject: [PATCH 054/122] added translation credits --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 974bd023..8b4a77e1 100644 --- a/README.md +++ b/README.md @@ -130,4 +130,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries - For updating Translations. +@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi - For updating Translations. From 70b84cde346116591d57cd4ff8a5bd10bddb4f87 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sun, 19 May 2024 19:16:30 +0200 Subject: [PATCH 055/122] fixed release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 901f63df..3ec76383 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -218,7 +218,7 @@ jobs: id: vars run: | echo "date_now=$(date --rfc-3339=seconds)" >> "${GITHUB_OUTPUT}" - Add-Content $env:GITHUB_OUTPUT "sha_short=$(git rev-parse --short HEAD)" + echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" - name: Download build artifacts from previous jobs uses: actions/download-artifact@v4 From 8d5f03c68510d09b4bbae428e31391af54d83f60 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sun, 19 May 2024 23:03:29 +0200 Subject: [PATCH 056/122] tweaked patch notes format --- patch_notes.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/patch_notes.txt b/patch_notes.txt index 9517966e..8f536722 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,3 +1,8 @@ +## v15.3.0 +### DATE +- notes here + +## v15.2.0 ### 19.5.2024 - Updated French translation as well as corresponding credits @@ -5,6 +10,7 @@ - Updated Russian, Ukrainian and Traditional Chinese translation as well as corresponding credits - Various changes to github workflows +## v15.1.0 ### 17.5.2024 - Updated Italian, Simplified Chinese and Spanish translation as well as corresponding credits -- Various changes to github workflows +- Various changes to github workflows \ No newline at end of file From 15722919fe74a2715a6b64351650f95ef822644a Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Mon, 20 May 2024 00:07:58 +0200 Subject: [PATCH 057/122] updated readme translation credits to look nicer --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b4a77e1..af01aa45 100644 --- a/README.md +++ b/README.md @@ -130,4 +130,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -@Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi - For updating Translations. +For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi \ No newline at end of file From 27c5c3712ffe718b69e17cff3f51850dca35d6df Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Mon, 20 May 2024 17:09:50 +0200 Subject: [PATCH 058/122] Updated README and release notes --- .github/workflows/release.yml | 2 +- README.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3ec76383..98e7be4f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -238,7 +238,7 @@ jobs: artifactErrorsFailBuild: true artifacts: artifacts/*/* body: | - # ⚠️ Please help with translation as tracked in #2 ! + # ⚠️ Please help with translation as tracked in #2 and channel points as tracked in #23 ! *** **This is an automatically generated updated version of the application, that includes the latest master branch changes.** diff --git a/README.md b/README.md index af01aa45..a5191a1e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Twitch Drops Miner +Thanks to @DevilXD and other contributors from the [original repo](https://github.com/DevilXD/TwitchDropsMiner) for the vast majority of the code. + This application allows you to AFK mine timed Twitch drops, without having to worry about switching channels when the one you were watching goes offline, claiming the drops, or even receiving the stream data itself. This helps both you and Twitch save on bandwidth and hassle. Everyone wins! ### How It Works: From 5138444a4be55e918a1bd08db3cca8da38d1417a Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Mon, 20 May 2024 23:32:54 +0200 Subject: [PATCH 059/122] incomplete dark mode added --- gui.py | 42 +++++++++++++++++++++++++++++++++++++----- settings.py | 3 +++ translate.py | 1 + 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/gui.py b/gui.py index 24695a78..b6505bdd 100644 --- a/gui.py +++ b/gui.py @@ -1456,6 +1456,7 @@ def proxy_validate(entry: PlaceholderEntry, settings: Settings) -> bool: class _SettingsVars(TypedDict): tray: IntVar proxy: StringVar + dark_theme: IntVar autostart: IntVar priority_only: IntVar tray_notifications: IntVar @@ -1465,12 +1466,14 @@ class SettingsPanel: AUTOSTART_NAME: str = "TwitchDropsMiner" AUTOSTART_KEY: str = "HKCU/Software/Microsoft/Windows/CurrentVersion/Run" - def __init__(self, manager: GUIManager, master: ttk.Widget): + def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): + self._root = root self._twitch = manager._twitch self._settings: Settings = manager._twitch.settings self._vars: _SettingsVars = { "proxy": StringVar(master, str(self._settings.proxy)), "tray": IntVar(master, self._settings.autostart_tray), + "dark_theme": IntVar(master, self._settings.dark_theme), "autostart": IntVar(master, self._settings.autostart), "priority_only": IntVar(master, self._settings.priority_only), "tray_notifications": IntVar(master, self._settings.tray_notifications), @@ -1505,8 +1508,14 @@ def __init__(self, manager: GUIManager, master: ttk.Widget): checkboxes_frame = ttk.Frame(center_frame2) checkboxes_frame.grid(column=0, row=1) ttk.Label( - checkboxes_frame, text=_("gui", "settings", "general", "autostart") + checkboxes_frame, text=_("gui", "settings", "general", "dark_theme") ).grid(column=0, row=(irow := 0), sticky="e") + ttk.Checkbutton( + checkboxes_frame, variable=self._vars["dark_theme"], command=self.change_theme + ).grid(column=1, row=irow, sticky="w") + ttk.Label( + checkboxes_frame, text=_("gui", "settings", "general", "autostart") + ).grid(column=0, row=(irow := irow + 1), sticky="e") ttk.Checkbutton( checkboxes_frame, variable=self._vars["autostart"], command=self.update_autostart ).grid(column=1, row=irow, sticky="w") @@ -1639,6 +1648,13 @@ def _get_autostart_path(self, tray: bool) -> str: self_path += " --tray" return self_path + def change_theme(self): + self._settings.dark_theme = bool(self._vars["dark_theme"].get()) + if self._settings.dark_theme: + set_theme(self._root, "dark") + else: + set_theme(self._root, "light") + def update_autostart(self) -> None: enabled = bool(self._vars["autostart"].get()) tray = bool(self._vars["tray"].get()) @@ -1880,14 +1896,14 @@ def __init__(self, twitch: Twitch): # Image cache for displaying images self._cache = ImageCache(self) - # style adjustements + # style adjustments self._style = style = ttk.Style(root) default_font = nametofont("TkDefaultFont") # theme theme = '' # theme = style.theme_names()[6] # style.theme_use(theme) - # fix treeview's background color from tags not working (also see '_fixed_map') + # Fix treeview's background color from tags not working (also see '_fixed_map') style.map( "Treeview", foreground=self._fixed_map("foreground"), @@ -1927,6 +1943,11 @@ def __init__(self, twitch: Twitch): style.configure("Link.TLabel", font=link_font, foreground="blue") # end of style changes + if self._twitch.settings.dark_theme: + set_theme(root, "dark") + else: + set_theme(root, "light") + root_frame = ttk.Frame(root, padding=8) root_frame.grid(column=0, row=0, sticky="nsew") root.rowconfigure(0, weight=1) @@ -1950,7 +1971,7 @@ def __init__(self, twitch: Twitch): self.tabs.add_tab(inv_frame, name=_("gui", "tabs", "inventory")) # Settings tab settings_frame = ttk.Frame(root_frame, padding=8) - self.settings = SettingsPanel(self, settings_frame) + self.settings = SettingsPanel(self, settings_frame, root) self.tabs.add_tab(settings_frame, name=_("gui", "tabs", "settings")) # Help tab help_frame = ttk.Frame(root_frame, padding=8) @@ -2135,6 +2156,15 @@ def print(self, message: str): self.output.print(message) +def set_theme(root, name): + style = ttk.Style(root) + # Style options + match name: + case "dark": + style.configure('.', background='#2b2b2b', foreground='#ffffff') + case "light" | "default" | _ : + style.configure('.', background='#ffffff', foreground='#000000') + ################### # GUI MANAGER END # ################### @@ -2256,11 +2286,13 @@ async def main(exit_event: asyncio.Event): tray=False, priority=[], proxy=URL(), + dark_theme=False, autostart=False, language="English", priority_only=False, autostart_tray=False, exclude={"Lit Game"}, + tray_notifications=True ) ) mock.change_state = lambda state: mock.gui.print(f"State change: {state.value}") diff --git a/settings.py b/settings.py index 1e0ee1a7..07200d34 100644 --- a/settings.py +++ b/settings.py @@ -14,6 +14,7 @@ class SettingsFile(TypedDict): proxy: URL language: str + dark_theme: bool autostart: bool exclude: set[str] priority: list[str] @@ -27,6 +28,7 @@ class SettingsFile(TypedDict): "proxy": URL(), "priority": [], "exclude": set(), + "dark_theme": False, "autostart": False, "priority_only": True, "autostart_tray": False, @@ -48,6 +50,7 @@ class Settings: # from settings file proxy: URL language: str + dark_theme: bool autostart: bool exclude: set[str] priority: list[str] diff --git a/translate.py b/translate.py index d7e7050b..68ecfe9f 100644 --- a/translate.py +++ b/translate.py @@ -359,6 +359,7 @@ class Translation(TypedDict): "settings": { "general": { "name": "General", + "dark_theme": "Dark theme: ", "autostart": "Autostart: ", "tray": "Autostart into tray: ", "tray_notifications": "Tray notifications: ", From dbada5730882016cc2b552d9fc8a518487253780 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Mon, 20 May 2024 23:34:13 +0200 Subject: [PATCH 060/122] updated patch notes --- patch_notes.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patch_notes.txt b/patch_notes.txt index 8f536722..f18656af 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,6 +1,6 @@ ## v15.3.0 -### DATE -- notes here +### 20.5.2024 +- Added incomplete dark mode ## v15.2.0 ### 19.5.2024 From 3ca39b30f7cc10212cc7aac537b6752892ac5987 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 21 May 2024 02:20:26 +0200 Subject: [PATCH 061/122] more work on dark mode --- gui.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/gui.py b/gui.py index b6505bdd..675aaddb 100644 --- a/gui.py +++ b/gui.py @@ -1467,6 +1467,7 @@ class SettingsPanel: AUTOSTART_KEY: str = "HKCU/Software/Microsoft/Windows/CurrentVersion/Run" def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): + self._manager = manager self._root = root self._twitch = manager._twitch self._settings: Settings = manager._twitch.settings @@ -1651,9 +1652,9 @@ def _get_autostart_path(self, tray: bool) -> str: def change_theme(self): self._settings.dark_theme = bool(self._vars["dark_theme"].get()) if self._settings.dark_theme: - set_theme(self._root, "dark") + set_theme(self._root, self._manager, "dark") else: - set_theme(self._root, "light") + set_theme(self._root, self._manager, "light") def update_autostart(self) -> None: enabled = bool(self._vars["autostart"].get()) @@ -1943,11 +1944,6 @@ def __init__(self, twitch: Twitch): style.configure("Link.TLabel", font=link_font, foreground="blue") # end of style changes - if self._twitch.settings.dark_theme: - set_theme(root, "dark") - else: - set_theme(root, "light") - root_frame = ttk.Frame(root, padding=8) root_frame.grid(column=0, row=0, sticky="nsew") root.rowconfigure(0, weight=1) @@ -2018,6 +2014,11 @@ def __init__(self, twitch: Twitch): else: self._root.after_idle(self._root.deiconify) + if self._twitch.settings.dark_theme: + set_theme(root, self, "dark") + else: + set_theme(root, self, "light") + # https://stackoverflow.com/questions/56329342/tkinter-treeview-background-tag-not-working def _fixed_map(self, option): # Fix for setting text colour for Tkinter 8.6.9 @@ -2156,14 +2157,48 @@ def print(self, message: str): self.output.print(message) -def set_theme(root, name): +def set_theme(root, manager, name): style = ttk.Style(root) # Style options match name: case "dark": - style.configure('.', background='#2b2b2b', foreground='#ffffff') - case "light" | "default" | _ : - style.configure('.', background='#ffffff', foreground='#000000') + style.theme_use('alt') + style.configure('.', background="#181818", foreground="#ffffff") + style.configure("TButton", background="#181818") + style.map("TButton", + background=[("active", "#2b2b2b")], + foreground=[("pressed", "black")]) + style.configure("TNotebook.Tab", background="#181818") + style.map("TNotebook.Tab", + background=[("selected", "#2b2b2b")]) + style.configure("TCheckbutton", foreground="black") + style.map("TCheckbutton", + background=[('active', '#2b2b2b')]) + style.configure("TLabelFrame", background="#181818") + manager.output._text.configure(bg="#181818") + manager.settings._exclude_list.configure(bg="#181818", fg="#ffffff") + manager.settings._priority_list.configure(bg="#181818", fg="#ffffff") + + + + case "light" | "default" | _ : # TEMP RETURN VALUES + style.theme_use('vista') + style.configure('.', background="#ffffff", foreground="#000000") + style.configure("TButton", background="#ffffff") + style.map("TButton", + background=[("active", "#e0e0e0")], + foreground=[("pressed", "black")]) + style.configure("TNotebook.Tab", background="#ffffff") + style.map("TNotebook.Tab", + background=[("selected", "#e0e0e0")]) + style.configure("TCheckbutton", foreground="black") + style.map("TCheckbutton", + background=[('active', '#e0e0e0')]) + style.configure("TLabelFrame", background="#ffffff") + manager.output._text.configure(bg="#ffffff") + manager.settings._exclude_list.configure(bg="#ffffff", fg="#000000") + manager.settings._priority_list.configure(bg="#ffffff", fg="#000000") + ################### # GUI MANAGER END # From fa7535870a46c62a82428ccce06644ea5faadfe3 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 21 May 2024 22:27:28 +0200 Subject: [PATCH 062/122] added dark mode --- gui.py | 126 +++++++++++++++++++++++++++++++++++------------- patch_notes.txt | 3 ++ 2 files changed, 96 insertions(+), 33 deletions(-) diff --git a/gui.py b/gui.py index 675aaddb..133f929c 100644 --- a/gui.py +++ b/gui.py @@ -353,12 +353,11 @@ def __init__( command: abc.Callable[[_T], Any] | None = None, default: str | None = None, relief: tk._Relief = "solid", - background: str = "white", **kwargs: Any, ): width = max((len(k) for k in options.keys()), default=20) super().__init__( - master, *args, background=background, relief=relief, width=width, **kwargs + master, *args, relief=relief, width=width, **kwargs ) self._menu_options: dict[str, _T] = options self._command = command @@ -1499,12 +1498,13 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): language_frame = ttk.Frame(center_frame2) language_frame.grid(column=0, row=0) ttk.Label(language_frame, text="Language 🌐 (requires restart): ").grid(column=0, row=0) - SelectMenu( + self._select_menu = SelectMenu( language_frame, default=_.current, options={k: k for k in _.languages}, command=lambda lang: setattr(self._settings, "language", lang), - ).grid(column=1, row=0) + ) + self._select_menu.grid(column=1, row=0) # checkboxes frame checkboxes_frame = ttk.Frame(center_frame2) checkboxes_frame.grid(column=0, row=1) @@ -2159,45 +2159,105 @@ def print(self, message: str): def set_theme(root, manager, name): style = ttk.Style(root) - # Style options + default_font = nametofont("TkDefaultFont") + large_font = default_font.copy() + large_font.config(size=12) + link_font = default_font.copy() + link_font.config(underline=True) + + def configure_combobox_list(combobox, flag, value): + combobox.update_idletasks() + popdown_window = combobox.tk.call("ttk::combobox::PopdownWindow", combobox) + listbox = f"{popdown_window}.f.l" + combobox.tk.call(listbox, "configure", flag, value) + + # Style options, !!!"background" and "bg" is not interchangable for some reason!!! match name: case "dark": - style.theme_use('alt') - style.configure('.', background="#181818", foreground="#ffffff") - style.configure("TButton", background="#181818") + bg_grey = "#181818" + active_grey = "#2b2b2b" + # General + style.theme_use('alt') # We have to switch the theme, because OS-defaults ("vista") don't support certain customisations, like Treeview-fieldbackground etc. + style.configure('.', background=bg_grey, foreground="white") + style.configure("Link.TLabel", font=link_font, foreground="#00aaff") + # Buttons style.map("TButton", - background=[("active", "#2b2b2b")], - foreground=[("pressed", "black")]) - style.configure("TNotebook.Tab", background="#181818") + background=[("active", active_grey)]) + # Tabs + style.configure("TNotebook.Tab", background=bg_grey) style.map("TNotebook.Tab", - background=[("selected", "#2b2b2b")]) - style.configure("TCheckbutton", foreground="black") + background=[("selected", active_grey)]) + # Checkboxes + style.configure("TCheckbutton", foreground="black") # The checkbox has to be white since it's an image, so the tick has to be black style.map("TCheckbutton", - background=[('active', '#2b2b2b')]) - style.configure("TLabelFrame", background="#181818") - manager.output._text.configure(bg="#181818") - manager.settings._exclude_list.configure(bg="#181818", fg="#ffffff") - manager.settings._priority_list.configure(bg="#181818", fg="#ffffff") - - - - case "light" | "default" | _ : # TEMP RETURN VALUES + background=[('active', active_grey)]) + # Output field + manager.output._text.configure(bg=bg_grey, fg="white", selectbackground=active_grey) + # Include/Exclude lists + manager.settings._exclude_list.configure(bg=bg_grey, fg="white") + manager.settings._priority_list.configure(bg=bg_grey, fg="white") + # Channel list + style.configure('Treeview', background=bg_grey, fieldbackground=bg_grey) + manager.channels._table + # Inventory + manager.inv._canvas.configure(bg=bg_grey) + # Scroll bars + style.configure("TScrollbar", foreground="white", troughcolor=bg_grey, bordercolor=bg_grey, arrowcolor="white") + style.map("TScrollbar", + background=[("active", bg_grey), ("!active", bg_grey)]) + # Language selection box _select_menu + manager.settings._select_menu.configure(bg=bg_grey, fg="white", activebackground=active_grey, activeforeground="white") # Couldn't figure out how to change the border, so it stays black + for index in range(manager.settings._select_menu.menu.index("end")+1): + manager.settings._select_menu.menu.entryconfig(index, background=bg_grey, activebackground=active_grey, foreground="white") + # Proxy field + style.configure("TEntry", foreground="white", selectbackground=active_grey, fieldbackground=bg_grey) + # Include/Exclude box + style.configure("TCombobox", foreground="white", selectbackground=active_grey, fieldbackground=bg_grey, arrowcolor="white") + style.map("TCombobox", background=[("active", active_grey), ("disabled", bg_grey)]) + # Include list + configure_combobox_list(manager.settings._priority_entry, "-background", bg_grey) + configure_combobox_list(manager.settings._priority_entry, "-foreground", "white") + configure_combobox_list(manager.settings._priority_entry, "-selectbackground", active_grey) + # Exclude list + configure_combobox_list(manager.settings._exclude_entry, "-background", bg_grey) + configure_combobox_list(manager.settings._exclude_entry, "-foreground", "white") + configure_combobox_list(manager.settings._exclude_entry, "-selectbackground", active_grey) + + case "light" | "default" | _ : # When creating a new theme, additional values might need to be set, so the default theme remains consistent + # General style.theme_use('vista') - style.configure('.', background="#ffffff", foreground="#000000") - style.configure("TButton", background="#ffffff") + style.configure('.', background="#f0f0f0", foreground="#000000") + # Buttons style.map("TButton", - background=[("active", "#e0e0e0")], - foreground=[("pressed", "black")]) - style.configure("TNotebook.Tab", background="#ffffff") + background=[("active", "#ffffff")]) + # Tabs + style.configure("TNotebook.Tab", background="#f0f0f0") style.map("TNotebook.Tab", - background=[("selected", "#e0e0e0")]) - style.configure("TCheckbutton", foreground="black") - style.map("TCheckbutton", - background=[('active', '#e0e0e0')]) - style.configure("TLabelFrame", background="#ffffff") - manager.output._text.configure(bg="#ffffff") + background=[("selected", "#ffffff")]) + # Checkboxes don't need to be reverted + # Output field + manager.output._text.configure(bg="#ffffff", fg="#000000") + # Include/Exclude lists manager.settings._exclude_list.configure(bg="#ffffff", fg="#000000") manager.settings._priority_list.configure(bg="#ffffff", fg="#000000") + # Channel list doesn't need to be reverted + # Inventory + manager.inv._canvas.configure(bg="#f0f0f0") + # Scroll bars don't need to be reverted + # Language selection box _select_menu + manager.settings._select_menu.configure(bg="#ffffff", fg="black", activebackground="#f0f0f0", activeforeground="black") # Couldn't figure out how to change the border, so it stays black + for index in range(manager.settings._select_menu.menu.index("end")+1): + manager.settings._select_menu.menu.entryconfig(index, background="#f0f0f0", activebackground="#0078d7", foreground="black") + # Proxy field doesn't need to be reverted + # Include/Exclude dropdown - Only the lists have to be reverted + # Include list + configure_combobox_list(manager.settings._priority_entry, "-background", "white") + configure_combobox_list(manager.settings._priority_entry, "-foreground", "black") + configure_combobox_list(manager.settings._priority_entry, "-selectbackground", "#0078d7") + # Exclude list + configure_combobox_list(manager.settings._exclude_entry, "-background", "white") + configure_combobox_list(manager.settings._exclude_entry, "-foreground", "black") + configure_combobox_list(manager.settings._exclude_entry, "-selectbackground", "#0078d7") ################### diff --git a/patch_notes.txt b/patch_notes.txt index f18656af..6b18e01d 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,4 +1,7 @@ ## v15.3.0 +### 22.5.2024 +- Completed dark mode 🎉 + ### 20.5.2024 - Added incomplete dark mode From 7a715148cd0ad5af08ff11c78e20d49081a68193 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Wed, 22 May 2024 01:57:18 +0200 Subject: [PATCH 063/122] removed English.json from gitignore --- .gitignore | 2 +- lang/English.json | 163 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 lang/English.json diff --git a/.gitignore b/.gitignore index a71ef047..3abda3d9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ __pycache__ log.txt /lock.file settings.json -/lang/English.json +#/lang/English.json # AppImage /AppDir /appimage-builder diff --git a/lang/English.json b/lang/English.json new file mode 100644 index 00000000..5d0ba679 --- /dev/null +++ b/lang/English.json @@ -0,0 +1,163 @@ +{ + "english_name": "English", + "status": { + "terminated": "\nApplication Terminated.\nClose the window to exit the application.", + "watching": "Watching: {channel}", + "goes_online": "{channel} goes ONLINE, switching...", + "goes_offline": "{channel} goes OFFLINE, switching...", + "claimed_drop": "Claimed drop: {drop}", + "claimed_points": "Claimed bonus points: {points}", + "earned_points": "Earned points for watching: {points}, total: {balance}", + "no_channel": "No available channels to watch. Waiting for an ONLINE channel...", + "no_campaign": "No active campaigns to mine drops for. Waiting for an active campaign..." + }, + "login": { + "unexpected_content": "Unexpected content type returned, usually due to being redirected. Do you need to login for internet access?", + "chrome": { + "startup": "Opening Chrome...", + "login_to_complete": "Complete the login procedure manually by pressing the Login button again.", + "no_token": "No authorization token could be found.", + "closed_window": "Chrome window was closed before the login procedure could complete." + }, + "error_code": "Login error code: {error_code}", + "incorrect_login_pass": "Incorrect username or password.", + "incorrect_email_code": "Incorrect email code.", + "incorrect_twofa_code": "Incorrect 2FA code.", + "email_code_required": "Email code required. Check your email.", + "twofa_code_required": "2FA token required." + }, + "error": { + "captcha": "Your login attempt was denied by CAPTCHA.\nPlease try again in 12+ hours.", + "site_down": "Twitch is down, retrying in {seconds} seconds...", + "no_connection": "Cannot connect to Twitch, retrying in {seconds} seconds..." + }, + "gui": { + "output": "Output", + "status": { + "name": "Status", + "idle": "Idle", + "exiting": "Exiting...", + "terminated": "Terminated", + "cleanup": "Cleaning up channels...", + "gathering": "Gathering channels...", + "switching": "Switching the channel...", + "fetching_inventory": "Fetching inventory...", + "fetching_campaigns": "Fetching campaigns...", + "adding_campaigns": "Adding campaigns to inventory... {counter}" + }, + "tabs": { + "main": "Main", + "inventory": "Inventory", + "settings": "Settings", + "help": "Help" + }, + "tray": { + "notification_title": "Mined Drop", + "minimize": "Minimize to Tray", + "show": "Show", + "quit": "Quit" + }, + "login": { + "name": "Login Form", + "labels": "Status:\nUser ID:", + "logged_in": "Logged in", + "logged_out": "Logged out", + "logging_in": "Logging in...", + "required": "Login required", + "request": "Please log in to continue.", + "username": "Username", + "password": "Password", + "twofa_code": "2FA code (optional)", + "button": "Login" + }, + "websocket": { + "name": "Websocket Status", + "websocket": "Websocket #{id}:", + "initializing": "Initializing...", + "connected": "Connected", + "disconnected": "Disconnected", + "connecting": "Connecting...", + "disconnecting": "Disconnecting...", + "reconnecting": "Reconnecting..." + }, + "progress": { + "name": "Campaign Progress", + "drop": "Drop:", + "game": "Game:", + "campaign": "Campaign:", + "remaining": "{time} remaining", + "drop_progress": "Progress:", + "campaign_progress": "Progress:" + }, + "channels": { + "name": "Channels", + "switch": "Switch", + "load_points": "Load Points", + "online": "ONLINE \u2714", + "pending": "OFFLINE \u23f3", + "offline": "OFFLINE \u274c", + "headings": { + "channel": "Channel", + "status": "Status", + "game": "Game", + "viewers": "Viewers", + "points": "Points" + } + }, + "inventory": { + "filter": { + "name": "Filter", + "show": "Show:", + "not_linked": "Not linked", + "upcoming": "Upcoming", + "expired": "Expired", + "excluded": "Excluded", + "finished": "Finished", + "refresh": "Refresh" + }, + "status": { + "linked": "Linked \u2714", + "not_linked": "Not Linked \u274c", + "active": "Active \u2714", + "upcoming": "Upcoming \u23f3", + "expired": "Expired \u274c", + "claimed": "Claimed \u2714", + "ready_to_claim": "Ready to claim \u23f3" + }, + "starts": "Starts: {time}", + "ends": "Ends: {time}", + "allowed_channels": "Allowed Channels:", + "all_channels": "All", + "and_more": "and {amount} more...", + "percent_progress": "{percent} of {minutes} minutes", + "minutes_progress": "{minutes} minutes" + }, + "settings": { + "general": { + "name": "General", + "dark_theme": "Dark theme: ", + "autostart": "Autostart: ", + "tray": "Autostart into tray: ", + "tray_notifications": "Tray notifications: ", + "priority_only": "Priority Only: ", + "proxy": "Proxy (requires restart):" + }, + "game_name": "Game name", + "priority": "Priority", + "exclude": "Exclude", + "reload": "Reload", + "reload_text": "Most changes require a reload to take an immediate effect: " + }, + "help": { + "links": { + "name": "Useful Links", + "inventory": "See Twitch inventory", + "campaigns": "See all campaigns and manage account links" + }, + "how_it_works": "How It Works", + "how_it_works_text": "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. It then fetches the metadata of this data stream - this is enough to advance the drops. Note that this completely bypasses the need to download any actual stream video and sound. To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection estabilished that receives events about streams going up or down, or updates regarding the current amount of viewers.", + "getting_started": "Getting Started", + "getting_started_text": "1. Login into the application.\n2. Ensure your Twitch account is linked to all campaigns you're interested in mining.\n3. If you're interested in just mining everything, uncheck \"Priority only\" and press on \"Reload\".\n4. If you want to mine specific games first, use the \"Priority\" list to setup an ordered list of games of your choice. Games from the top of the list will be attempted to be mined first, before the ones lower down the list.\n5. Keep the \"Priority only\" option checked, to avoid mining games that are not on the priority list. Or not - it's up to you.\n6. Use the \"Exclude\" list to tell the application which games should never be mined.\n7. Changing the contents of either of the lists, or changing the state of the \"Priority only\" option, requires you to press on \"Reload\" for the changes to take an effect." + } + } +} \ No newline at end of file From 72fb6010523d466f38839ef0fcad109d2ed22b7f Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Wed, 22 May 2024 02:32:02 +0200 Subject: [PATCH 064/122] added end-priority to translations --- lang/English.json | 1 + translate.py | 1 + 2 files changed, 2 insertions(+) diff --git a/lang/English.json b/lang/English.json index 5d0ba679..b3add9cc 100644 --- a/lang/English.json +++ b/lang/English.json @@ -140,6 +140,7 @@ "tray": "Autostart into tray: ", "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", + "prioritze_end": "Prioritize campaigns by end date: ", "proxy": "Proxy (requires restart):" }, "game_name": "Game name", diff --git a/translate.py b/translate.py index 68ecfe9f..da6b8535 100644 --- a/translate.py +++ b/translate.py @@ -364,6 +364,7 @@ class Translation(TypedDict): "tray": "Autostart into tray: ", "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", + "prioritze_end": "Prioritize campaigns by end date: ", "proxy": "Proxy (requires restart):", }, "game_name": "Game name", From 6fea3a3011b663d7cacb9509e0c78cb526a6c5c8 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 23 May 2024 23:02:10 +0200 Subject: [PATCH 065/122] Should fix Theme-related crash on linux --- gui.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gui.py b/gui.py index 133f929c..e51bf75c 100644 --- a/gui.py +++ b/gui.py @@ -2159,6 +2159,9 @@ def print(self, message: str): def set_theme(root, manager, name): style = ttk.Style(root) + if not hasattr(set_theme, "default_style"): + set_theme.default_style = style.theme_use() # "Themes" is more fitting for the recolour and "Style" for the button style. + default_font = nametofont("TkDefaultFont") large_font = default_font.copy() large_font.config(size=12) @@ -2225,7 +2228,7 @@ def configure_combobox_list(combobox, flag, value): case "light" | "default" | _ : # When creating a new theme, additional values might need to be set, so the default theme remains consistent # General - style.theme_use('vista') + style.theme_use(set_theme.default_style) style.configure('.', background="#f0f0f0", foreground="#000000") # Buttons style.map("TButton", From e9412bd20b0606f4607a2a7999948d03a67eab58 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 23 May 2024 23:12:46 +0200 Subject: [PATCH 066/122] updated patch notes and README --- README.md | 2 +- patch_notes.txt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a5191a1e..f189545a 100644 --- a/README.md +++ b/README.md @@ -132,4 +132,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi \ No newline at end of file +For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns \ No newline at end of file diff --git a/patch_notes.txt b/patch_notes.txt index 6b18e01d..bb2ba5fb 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,4 +1,9 @@ ## v15.3.0 + +### 23.5.2024 +- Fixed crash on Linux +- Updated English, German, Czech, Spanish and Russian translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date. + ### 22.5.2024 - Completed dark mode 🎉 From b90e7b52c69024f6a6f9bbee5b6cb3b389c0dcb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elvis=20Gr=C4=81ps?= Date: Thu, 23 May 2024 21:06:11 +0000 Subject: [PATCH 067/122] =?UTF-8?q?Translate=20=D0=A0=D1=83=D1=81=D1=81?= =?UTF-8?q?=D0=BA=D0=B8=D0=B9.json=20via=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\201\321\201\320\272\320\270\320\271.json" | 326 +++++++++--------- 1 file changed, 164 insertions(+), 162 deletions(-) diff --git "a/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" "b/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" index e281d6d7..b3082bec 100644 --- "a/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" +++ "b/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" @@ -1,162 +1,164 @@ -{ - "english_name": "Russian", - "status": { - "terminated": "\nПриложение остановлено.\nЗакройте окно, чтобы выйти из приложения.", - "watching": "Просмотр канала: {channel}", - "goes_online": "Изменение: {channel} онлайн", - "goes_offline": "Изменение: {channel} онлайн", - "claimed_drop": "Drop получено: {drop}", - "claimed_points": "Получены очки канала: {points}", - "earned_points": "За просмотр начисляются очки канала: {points} | Сумма: {balance}", - "no_channel": "Нет участвующих каналов онлайн. Ожидание каналов...", - "no_campaign": "Нет участвующих кампаний онлайн. Ожидание кампаний..." - }, - "login": { - "chrome": { - "startup": "Запуск Браузера...", - "login_to_complete": "Нажмите Log In еще раз, чтобы завершить процесс входа в систему вручную..", - "no_token": "Не найден токен авторизации.", - "closed_window": "Окно Браузера было закрыто до завершения процесса входа в систему." - }, - "error_code": "Код ошибки входа в систему: {error_code}", - "unexpected_content": "Возвращен неожиданный тип содержимого, обычно из-за перенаправления. Требуется ли логин для доступа в Интернет?", - "incorrect_login_pass": "Неправильное имя пользователя или пароль.", - "incorrect_email_code": "Неправильный код электронной почты.", - "incorrect_twofa_code": "Неправильный код 2FA.", - "email_code_required": "Требуется код электронной почты. Пожалуйста, проверьте электронную почту.", - "twofa_code_required": "Требуется код 2FA." - }, - "error": { - "captcha": "Попытка входа в систему была отклонена CAPTCHA.\nПожалуйста, повторите попытку не менее чем через 12 часов.", - "site_down": "Twitch недоступен. Повторите попытку через {seconds} секунд...", - "no_connection": "Невозможно подключиться к Twitch. Повторите попытку через {seconds} секунд..." - }, - "gui": { - "output": "Протокол", - "status": { - "name": "Статус", - "idle": "Вхолостую", - "exiting": "Выход...", - "terminated": "Прекращено", - "cleanup": "Очистка каналов...", - "gathering": "Поиск каналов...", - "switching": "Переключение канала...", - "fetching_inventory": "Получение инвентаря...", - "fetching_campaigns": "Получение кампаний...", - "adding_campaigns": "Добавление кампаний в инвентарь... {counter}" - }, - "tabs": { - "main": "Главная", - "inventory": "Инвентарь", - "settings": "Настройки", - "help": "Помощь" - }, - "tray": { - "notification_title": "Drop получено", - "minimize": "Свернуть в трей", - "show": "Показать", - "quit": "Закрыть" - }, - "login": { - "name": "Авторизация", - "labels": "Статус:\nID пользователя:", - "logged_in": "Авторизован", - "logged_out": "не авторизован", - "logging_in": "Авторизация...", - "required": "Требуется авторизация", - "request": "Пожалуйста, авторизуйтесь, чтобы продолжить.", - "username": "Имя пользователя", - "password": "Пароль", - "twofa_code": "2FA код (опционально)", - "button": "Войти" - }, - "websocket": { - "name": "WebSocket статус", - "websocket": "WebSocket #{id}:", - "initializing": "Инициализация...", - "connected": "Подключено", - "disconnected": "Отключено", - "connecting": "Подключение...", - "disconnecting": "Отключение...", - "reconnecting": "Переподключение..." - }, - "progress": { - "name": "Ход кампании", - "drop": "Drop:", - "game": "Игра:", - "campaign": "Кампания:", - "remaining": "{time} осталось", - "drop_progress": "Прогресс:", - "campaign_progress": "Прогресс:" - }, - "channels": { - "name": "Каналы", - "switch": "Изменить", - "load_points": "Загрузить баллы", - "online": "ОНЛАЙН ✔", - "pending": "ОЖИДАНИЕ ⏳", - "offline": "ОФЛАЙН ❌", - "headings": { - "channel": "Канал", - "status": "Статус", - "game": "Игра", - "viewers": "Зрители", - "points": "Баллы" - } - }, - "inventory": { - "filter": { - "name": "Фильтр", - "show": "Показать:", - "not_linked": "Не связано", - "upcoming": "Будущие", - "expired": "Прошедшие", - "excluded": "Исключенные", - "finished": "Оконченные", - "refresh": "Обновить" - }, - "status": { - "linked": "Связанное ✔", - "not_linked": "Не связанное ❌", - "active": "Активное ✔", - "upcoming": "Будущее ⏳", - "expired": "Прошедшее ❌", - "claimed": "Получено ✔", - "ready_to_claim": "Готово к получению⏳" - }, - "starts": "Начало: {time}", - "ends": "Окончание: {time}", - "allowed_channels": "Участвующие каналы:", - "all_channels": "Все", - "and_more": "и еще {amount}...", - "percent_progress": "{percent} от {minutes} минут", - "minutes_progress": "{minutes} минут" - }, - "settings": { - "general": { - "name": "Общие", - "autostart": "Автозапуск", - "tray": "Автозапуск свёрнутым", - "tray_notifications": "Всплывающие уведомления", - "priority_only": "Только приоритет", - "proxy": "Прокси (Требуется перезапуск):" - }, - "game_name": "Игра", - "priority": "Приоритет", - "exclude": "Исключения", - "reload": "Перезагрузить", - "reload_text": "Большинство изменений требуют перезагрузки, чтобы вступить в силу немедленно: " - }, - "help": { - "links": { - "name": "Полезные ссылки", - "inventory": "Инвентарь Twitch", - "campaigns": "Все кампании Twitch" - }, - "how_it_works": "Как это работает?", - "how_it_works_text": "Каждые ~20 секунд приложение запрашивает у Twitch URL-адрес необработанных данных потока канала, который просматривается в данный момент. Затем он извлекает метаданные этого потока данных. \nЭтого достаточно, чтобы получить Drop. Таким образом, нет необходимости скачивать поток, что экономит трафик. \nДля поддержания актуального состояния каналов в режиме онлайн или офлайн устанавливается соединение websocket, которое проверяет состояние каналов.", - "getting_started": "Первые шаги", - "getting_started_text": "1. Войдите в приложение.\n2. Убедитесь, что аккаунт Twitch связан со всеми кампаниями, к которым есть интерес.\n3. Если вы хотите редактировать все Drops, снимите флажок \"Только приоритет\" и нажмите \"Перезагрузить\".\n4. Если необходимо смотреть только определенные игры, используйте список \"Приоритет\", чтобы сузить выбор игр.\n5. В списке приоритеты расставлены сверху вниз.\n6. Опция \"Только приоритет\" предотвращает просмотр игр, не входящих в список приоритетов.\n7. С помощью списка \"Исключения\" можно отфильтровать игры, которые не должны рассматриваться.\n8. Если списки или опции были изменены, нажмите \"Перезагрузить\", чтобы изменения были применены." - } - } -} +{ + "english_name": "Russian", + "status": { + "terminated": "\nПриложение остановлено.\nЗакройте окно, чтобы выйти из приложения.", + "watching": "Просмотр канала: {channel}", + "goes_online": "Изменение: {channel} онлайн", + "goes_offline": "Изменение: {channel} онлайн", + "claimed_drop": "Drop получено: {drop}", + "claimed_points": "Получены очки канала: {points}", + "earned_points": "За просмотр начисляются очки канала: {points} | Сумма: {balance}", + "no_channel": "Нет участвующих каналов онлайн. Ожидание каналов...", + "no_campaign": "Нет участвующих кампаний онлайн. Ожидание кампаний..." + }, + "login": { + "unexpected_content": "Возвращен неожиданный тип содержимого, обычно из-за перенаправления. Требуется ли логин для доступа в Интернет?", + "chrome": { + "startup": "Запуск Браузера...", + "login_to_complete": "Нажмите Log In еще раз, чтобы завершить процесс входа в систему вручную..", + "no_token": "Не найден токен авторизации.", + "closed_window": "Окно Браузера было закрыто до завершения процесса входа в систему." + }, + "error_code": "Код ошибки входа в систему: {error_code}", + "incorrect_login_pass": "Неправильное имя пользователя или пароль.", + "incorrect_email_code": "Неправильный код электронной почты.", + "incorrect_twofa_code": "Неправильный код 2FA.", + "email_code_required": "Требуется код электронной почты. Пожалуйста, проверьте электронную почту.", + "twofa_code_required": "Требуется код 2FA." + }, + "error": { + "captcha": "Попытка входа в систему была отклонена CAPTCHA.\nПожалуйста, повторите попытку не менее чем через 12 часов.", + "site_down": "Twitch недоступен. Повторите попытку через {seconds} секунд...", + "no_connection": "Невозможно подключиться к Twitch. Повторите попытку через {seconds} секунд..." + }, + "gui": { + "output": "Протокол", + "status": { + "name": "Статус", + "idle": "Вхолостую", + "exiting": "Выход...", + "terminated": "Прекращено", + "cleanup": "Очистка каналов...", + "gathering": "Поиск каналов...", + "switching": "Переключение канала...", + "fetching_inventory": "Получение инвентаря...", + "fetching_campaigns": "Получение кампаний...", + "adding_campaigns": "Добавление кампаний в инвентарь... {counter}" + }, + "tabs": { + "main": "Главная", + "inventory": "Инвентарь", + "settings": "Настройки", + "help": "Помощь" + }, + "tray": { + "notification_title": "Drop получено", + "minimize": "Свернуть в трей", + "show": "Показать", + "quit": "Закрыть" + }, + "login": { + "name": "Авторизация", + "labels": "Статус:\nID пользователя:", + "logged_in": "Авторизован", + "logged_out": "не авторизован", + "logging_in": "Авторизация...", + "required": "Требуется авторизация", + "request": "Пожалуйста, авторизуйтесь, чтобы продолжить.", + "username": "Имя пользователя", + "password": "Пароль", + "twofa_code": "2FA код (опционально)", + "button": "Войти" + }, + "websocket": { + "name": "WebSocket статус", + "websocket": "WebSocket #{id}:", + "initializing": "Инициализация...", + "connected": "Подключено", + "disconnected": "Отключено", + "connecting": "Подключение...", + "disconnecting": "Отключение...", + "reconnecting": "Переподключение..." + }, + "progress": { + "name": "Ход кампании", + "drop": "Drop:", + "game": "Игра:", + "campaign": "Кампания:", + "remaining": "{time} осталось", + "drop_progress": "Прогресс:", + "campaign_progress": "Прогресс:" + }, + "channels": { + "name": "Каналы", + "switch": "Изменить", + "load_points": "Загрузить баллы", + "online": "ОНЛАЙН ✔", + "pending": "ОЖИДАНИЕ ⏳", + "offline": "ОФЛАЙН ❌", + "headings": { + "channel": "Канал", + "status": "Статус", + "game": "Игра", + "viewers": "Зрители", + "points": "Баллы" + } + }, + "inventory": { + "filter": { + "name": "Фильтр", + "show": "Показать:", + "not_linked": "Не связано", + "upcoming": "Будущие", + "expired": "Прошедшие", + "excluded": "Исключенные", + "finished": "Оконченные", + "refresh": "Обновить" + }, + "status": { + "linked": "Связанное ✔", + "not_linked": "Не связанное ❌", + "active": "Активное ✔", + "upcoming": "Будущее ⏳", + "expired": "Прошедшее ❌", + "claimed": "Получено ✔", + "ready_to_claim": "Готово к получению⏳" + }, + "starts": "Начало: {time}", + "ends": "Окончание: {time}", + "allowed_channels": "Участвующие каналы:", + "all_channels": "Все", + "and_more": "и еще {amount}...", + "percent_progress": "{percent} от {minutes} минут", + "minutes_progress": "{minutes} минут" + }, + "settings": { + "general": { + "name": "Общие", + "dark_theme": "Тёмная тема: ", + "autostart": "Автозапуск", + "tray": "Автозапуск свёрнутым", + "tray_notifications": "Всплывающие уведомления", + "priority_only": "Только приоритет", + "prioritze_end": "Приоритизация кампаний по дате окончания:", + "proxy": "Прокси (Требуется перезапуск):" + }, + "game_name": "Игра", + "priority": "Приоритет", + "exclude": "Исключения", + "reload": "Перезагрузить", + "reload_text": "Большинство изменений требуют перезагрузки, чтобы вступить в силу немедленно: " + }, + "help": { + "links": { + "name": "Полезные ссылки", + "inventory": "Инвентарь Twitch", + "campaigns": "Все кампании Twitch" + }, + "how_it_works": "Как это работает?", + "how_it_works_text": "Каждые ~20 секунд приложение запрашивает у Twitch URL-адрес необработанных данных потока канала, который просматривается в данный момент. Затем он извлекает метаданные этого потока данных. \nЭтого достаточно, чтобы получить Drop. Таким образом, нет необходимости скачивать поток, что экономит трафик. \nДля поддержания актуального состояния каналов в режиме онлайн или офлайн устанавливается соединение websocket, которое проверяет состояние каналов.", + "getting_started": "Первые шаги", + "getting_started_text": "1. Войдите в приложение.\n2. Убедитесь, что аккаунт Twitch связан со всеми кампаниями, к которым есть интерес.\n3. Если вы хотите редактировать все Drops, снимите флажок \"Только приоритет\" и нажмите \"Перезагрузить\".\n4. Если необходимо смотреть только определенные игры, используйте список \"Приоритет\", чтобы сузить выбор игр.\n5. В списке приоритеты расставлены сверху вниз.\n6. Опция \"Только приоритет\" предотвращает просмотр игр, не входящих в список приоритетов.\n7. С помощью списка \"Исключения\" можно отфильтровать игры, которые не должны рассматриваться.\n8. Если списки или опции были изменены, нажмите \"Перезагрузить\", чтобы изменения были применены." + } + } +} From 346023ecb0c0915ae168936298d5916f1755214c Mon Sep 17 00:00:00 2001 From: notNSANE Date: Thu, 23 May 2024 21:05:13 +0000 Subject: [PATCH 068/122] =?UTF-8?q?Translate=20Espa=C3=B1ol.json=20via=20G?= =?UTF-8?q?itLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "lang/Espa\303\261ol.json" | 310 +++++++++++++++++++------------------ 1 file changed, 156 insertions(+), 154 deletions(-) diff --git "a/lang/Espa\303\261ol.json" "b/lang/Espa\303\261ol.json" index 809aada3..e7bae604 100644 --- "a/lang/Espa\303\261ol.json" +++ "b/lang/Espa\303\261ol.json" @@ -1,162 +1,164 @@ { - "english_name": "Spanish", + "english_name": "Spanish", + "status": { + "terminated": "\nLa aplicación se ha detenido.\nPor favor, cierre la aplicación.", + "watching": "Viendo el canal: {channel}", + "goes_online": "El canal {channel} se ha conectado, cambiando...", + "goes_offline": "El canal {channel} se ha desconectado, cambiando...", + "claimed_drop": "Drop reclamado: {drop}", + "claimed_points": "Recompensa de puntos reclamados: {points}", + "earned_points": "Puntos obtenidos por ver el stream: {points} | Total: {balance}", + "no_channel": "No se ha encontrado un canal en directo para ver. \nEsperando un canal en directo...", + "no_campaign": "No se ha encontrado una campaña activa. \nEsperando una nueva campaña..." + }, + "login": { + "unexpected_content": "Se produjo un error inesperado, \ngeneralmente debido a una redirección.\n¿Necesitas un VPN o iniciar sesión para acceder a internet?", + "chrome": { + "startup": "Iniciando Chrome...", + "login_to_complete": "Por favor, presione Iniciar sesión nuevamente para \ncompletar el inicio de sesión.", + "no_token": "No se pudo obtener un token de autorización.", + "closed_window": "La ventana de Chrome se cerró antes de que \nse completara el inicio de sesión." + }, + "error_code": "Error de inicio de sesión: {error_code}", + "incorrect_login_pass": "El usuario o contraseña ingresada es incorrecto.", + "incorrect_email_code": "El código de verificación de email es incorrecto.", + "incorrect_twofa_code": "El código 2FA es incorrecto.", + "email_code_required": "Código de verificación de email requerido. \nPor favor, revise su email.", + "twofa_code_required": "Token 2FA requerido." + }, + "error": { + "captcha": "El inicio de sesión fue rechazado por CAPTCHA.\nPor favor, intente nuevamente en aprox. 12 horas.", + "site_down": "Twitch no está disponible. \nIntente de nuevo en {seconds} segundos...", + "no_connection": "No se ha podido conectar a Twitch. \nIntente de nuevo en {seconds} segundos..." + }, + "gui": { + "output": "Registros", "status": { - "terminated": "\nLa aplicación se ha detenido.\nPor favor, cierre la aplicación.", - "watching": "Viendo el canal: {channel}", - "goes_online": "El canal {channel} se ha conectado, cambiando...", - "goes_offline": "El canal {channel} se ha desconectado, cambiando...", - "claimed_drop": "Drop reclamado: {drop}", - "claimed_points": "Recompensa de puntos reclamados: {points}", - "earned_points": "Puntos obtenidos por ver el stream: {points} | Total: {balance}", - "no_channel": "No se ha encontrado un canal en directo para ver. \nEsperando un canal en directo...", - "no_campaign": "No se ha encontrado una campaña activa. \nEsperando una nueva campaña..." + "name": "Estado", + "idle": "En espera...", + "exiting": "Saliendo...", + "terminated": "Aplicación suspendida.", + "cleanup": "Limpiando canales...", + "gathering": "Buscando canales en directo...", + "switching": "Cambiando de canal...", + "fetching_inventory": "Obteniendo inventario...", + "fetching_campaigns": "Obteniendo campañas...", + "adding_campaigns": "Agregando lista de campañas al inventario... {counter}" + }, + "tabs": { + "main": "General", + "inventory": "Inventario", + "settings": "Configuración", + "help": "Ayuda" + }, + "tray": { + "notification_title": "Drop minado", + "minimize": "Minimizar a la bandeja", + "show": "Mostrar", + "quit": "Salir" }, "login": { - "chrome": { - "startup": "Iniciando Chrome...", - "login_to_complete": "Por favor, presione Iniciar sesión nuevamente para \ncompletar el inicio de sesión.", - "no_token": "No se pudo obtener un token de autorización.", - "closed_window": "La ventana de Chrome se cerró antes de que \nse completara el inicio de sesión." - }, - "error_code": "Error de inicio de sesión: {error_code}", - "unexpected_content": "Se produjo un error inesperado, \ngeneralmente debido a una redirección.\n¿Necesitas un VPN o iniciar sesión para acceder a internet?", - "incorrect_login_pass": "El usuario o contraseña ingresada es incorrecto.", - "incorrect_email_code": "El código de verificación de email es incorrecto.", - "incorrect_twofa_code": "El código 2FA es incorrecto.", - "email_code_required": "Código de verificación de email requerido. \nPor favor, revise su email.", - "twofa_code_required": "Token 2FA requerido." + "name": "Inicio de sesión", + "labels": "Estado:\nUsuario:", + "logged_in": "Conectado", + "logged_out": "Desconectado", + "logging_in": "Iniciando sesión...", + "required": "Se requiere inicio de sesión", + "request": "Por favor, inicie sesión para continuar.", + "username": "Usuario", + "password": "Contraseña", + "twofa_code": "Token 2FA (opcional)", + "button": "Iniciar sesión" + }, + "websocket": { + "name": "Estado del Websocket", + "websocket": "Websocket #{id}:", + "initializing": "Iniciando...", + "connected": "Conectado", + "disconnected": "Desconectado", + "connecting": "Conectando...", + "disconnecting": "Desconectando...", + "reconnecting": "Reconectando..." + }, + "progress": { + "name": "Progreso de la Campaña", + "drop": "Drop:", + "game": "Juego:", + "campaign": "Campaña:", + "remaining": "{time} restante", + "drop_progress": "Progreso:", + "campaign_progress": "Progreso:" + }, + "channels": { + "name": "Canales", + "switch": "Cambiar", + "load_points": "Cargar Puntos", + "online": "ONLINE ✔", + "pending": "OFFLINE ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "Canal", + "status": "Estado", + "game": "Juego", + "viewers": "Espectadores", + "points": "Puntos" + } + }, + "inventory": { + "filter": { + "name": "Filtro de campañas", + "show": "Mostrar:", + "not_linked": "No enlazado", + "upcoming": "Próximas", + "expired": "Expiradas", + "excluded": "Excluidas", + "finished": "Completadas", + "refresh": "Actualizar" + }, + "status": { + "linked": "Vinculado ✔", + "not_linked": "Sin vincular ❌", + "active": "Activo ✔", + "upcoming": "Próximamente ⏳", + "expired": "Expirado ❌", + "claimed": "Reclamado ✔", + "ready_to_claim": "Listo para reclamar ⏳" + }, + "starts": "Comienza: {time}", + "ends": "Termina: {time}", + "allowed_channels": "Canales permitidos:", + "all_channels": "Todos", + "and_more": "y {amount} más...", + "percent_progress": "{percent} de {minutes} minutos", + "minutes_progress": "{minutes} minutos" }, - "error": { - "captcha": "El inicio de sesión fue rechazado por CAPTCHA.\nPor favor, intente nuevamente en aprox. 12 horas.", - "site_down": "Twitch no está disponible. \nIntente de nuevo en {seconds} segundos...", - "no_connection": "No se ha podido conectar a Twitch. \nIntente de nuevo en {seconds} segundos..." + "settings": { + "general": { + "name": "Ajustes generales", + "dark_theme": "Tema oscuro: ", + "autostart": "Ejecutar al iniciar el sistema: ", + "tray": "Ejecutar en la bandeja del sistema: ", + "tray_notifications": "Mostrar notificaciones: ", + "priority_only": "Minar solo juegos preferidos: ", + "prioritze_end": "Priorizar campañas por fecha de finalización: ", + "proxy": "Proxy (requiere reinicio):" + }, + "game_name": "Nombre del juego", + "priority": "Lista de juegos preferidos", + "exclude": "Lista de juegos excluidos", + "reload": "Recargar", + "reload_text": "La mayoría de los cambios requieren recargar o reiniciar la aplicación para que sean aplicados: " }, - "gui": { - "output": "Registros", - "status": { - "name": "Estado", - "idle": "En espera...", - "exiting": "Saliendo...", - "terminated": "Aplicación suspendida.", - "cleanup": "Limpiando canales...", - "gathering": "Buscando canales en directo...", - "switching": "Cambiando de canal...", - "fetching_inventory": "Obteniendo inventario...", - "fetching_campaigns": "Obteniendo campañas...", - "adding_campaigns": "Agregando lista de campañas al inventario... {counter}" - }, - "tabs": { - "main": "General", - "inventory": "Inventario", - "settings": "Configuración", - "help": "Ayuda" - }, - "tray": { - "notification_title": "Drop minado", - "minimize": "Minimizar a la bandeja", - "show": "Mostrar", - "quit": "Salir" - }, - "login": { - "name": "Inicio de sesión", - "labels": "Estado:\nUsuario:", - "logged_in": "Conectado", - "logged_out": "Desconectado", - "logging_in": "Iniciando sesión...", - "required": "Se requiere inicio de sesión", - "request": "Por favor, inicie sesión para continuar.", - "username": "Usuario", - "password": "Contraseña", - "twofa_code": "Token 2FA (opcional)", - "button": "Iniciar sesión" - }, - "websocket": { - "name": "Estado del Websocket", - "websocket": "Websocket #{id}:", - "initializing": "Iniciando...", - "connected": "Conectado", - "disconnected": "Desconectado", - "connecting": "Conectando...", - "disconnecting": "Desconectando...", - "reconnecting": "Reconectando..." - }, - "progress": { - "name": "Progreso de la Campaña", - "drop": "Drop:", - "game": "Juego:", - "campaign": "Campaña:", - "remaining": "{time} restante", - "drop_progress": "Progreso:", - "campaign_progress": "Progreso:" - }, - "channels": { - "name": "Canales", - "switch": "Cambiar", - "load_points": "Cargar Puntos", - "online": "ONLINE ✔", - "pending": "OFFLINE ⏳", - "offline": "OFFLINE ❌", - "headings": { - "channel": "Canal", - "status": "Estado", - "game": "Juego", - "viewers": "Espectadores", - "points": "Puntos" - } - }, - "inventory": { - "filter": { - "name": "Filtro de campañas", - "show": "Mostrar:", - "not_linked": "No enlazado", - "upcoming": "Próximas", - "expired": "Expiradas", - "excluded": "Excluidas", - "finished": "Completadas", - "refresh": "Actualizar" - }, - "status": { - "linked": "Vinculado ✔", - "not_linked": "Sin vincular ❌", - "active": "Activo ✔", - "upcoming": "Próximamente ⏳", - "expired": "Expirado ❌", - "claimed": "Reclamado ✔", - "ready_to_claim": "Listo para reclamar ⏳" - }, - "starts": "Comienza: {time}", - "ends": "Termina: {time}", - "allowed_channels": "Canales permitidos:", - "all_channels": "Todos", - "and_more": "y {amount} más...", - "percent_progress": "{percent} de {minutes} minutos", - "minutes_progress": "{minutes} minutos" - }, - "settings": { - "general": { - "name": "Ajustes generales", - "autostart": "Ejecutar al iniciar el sistema: ", - "tray": "Ejecutar en la bandeja del sistema: ", - "tray_notifications": "Mostrar notificaciones: ", - "priority_only": "Minar solo juegos preferidos: ", - "proxy": "Proxy (requiere reinicio):" - }, - "game_name": "Nombre del juego", - "priority": "Lista de juegos preferidos", - "exclude": "Lista de juegos excluidos", - "reload": "Recargar", - "reload_text": "La mayoría de los cambios requieren recargar o reiniciar la aplicación para que sean aplicados: " - }, - "help": { - "links": { - "name": "Enlaces útiles", - "inventory": "Ver inventario de Twitch", - "campaigns": "Ver todas las campañas y administrar cuentas vinculadas" - }, - "how_it_works": "Cómo funciona", - "how_it_works_text": "Aproximadamente cada 20 segundos, la aplicación solicita a Twitch la URL de los datos del canal que estamos viendo. \nDe esta forma, obtenemos sus metadatos, lo que nos permite ahorrar en la descarga de video o audio del stream. \nPara mantener actualizados los estados (ONLINE o OFFLINE) de los canales, así como el número de espectadores, \nse establece una conexión WebSocket mediante de la cual recibimos la información actualizada de los streams.", - "getting_started": "Primeros pasos", - "getting_started_text": "1. Inicie sesión en la aplicación. \n2. Verifique que su cuenta de Twitch esté vinculada a todas las campañas deseadas a minar. \n3. Si desea minar todas las campañas, desmarque la opción \"Minar solo juegos preferidos\" y presione \"Recargar\". \n4. Si desea darle prioridad a una campaña específica, utilice la \"Lista de juegos preferidos\" para crear una lista de prioridad. \nLos juegos en la parte superior de la lista se intentarán minar antes de los que estén más abajo. \n5. Utilice la opción \"Minar solo juegos preferidos\" si desea evitar minar juegos que no estén en la lista de juegos preferidos. \n6. Utilice la \"Lista de juegos excluidos\" si desea evitar minar juegos que no estén en la lista de juegos excluidos. \n7. Al utilizar la opción \"Minar solo juegos preferidos\" o al cambiar el contenido de las listas, \nserá necesario presionar el botón \"Recargar\" para que los cambios sean aplicados." - } + "help": { + "links": { + "name": "Enlaces útiles", + "inventory": "Ver inventario de Twitch", + "campaigns": "Ver todas las campañas y administrar cuentas vinculadas" + }, + "how_it_works": "Cómo funciona", + "how_it_works_text": "Aproximadamente cada 20 segundos, la aplicación solicita a Twitch la URL de los datos del canal que estamos viendo. \nDe esta forma, obtenemos sus metadatos, lo que nos permite ahorrar en la descarga de video o audio del stream. \nPara mantener actualizados los estados (ONLINE o OFFLINE) de los canales, así como el número de espectadores, \nse establece una conexión WebSocket mediante de la cual recibimos la información actualizada de los streams.", + "getting_started": "Primeros pasos", + "getting_started_text": "1. Inicie sesión en la aplicación. \n2. Verifique que su cuenta de Twitch esté vinculada a todas las campañas deseadas a minar. \n3. Si desea minar todas las campañas, desmarque la opción \"Minar solo juegos preferidos\" y presione \"Recargar\". \n4. Si desea darle prioridad a una campaña específica, utilice la \"Lista de juegos preferidos\" para crear una lista de prioridad. \nLos juegos en la parte superior de la lista se intentarán minar antes de los que estén más abajo. \n5. Utilice la opción \"Minar solo juegos preferidos\" si desea evitar minar juegos que no estén en la lista de juegos preferidos. \n6. Utilice la \"Lista de juegos excluidos\" si desea evitar minar juegos que no estén en la lista de juegos excluidos. \n7. Al utilizar la opción \"Minar solo juegos preferidos\" o al cambiar el contenido de las listas, \nserá necesario presionar el botón \"Recargar\" para que los cambios sean aplicados." } + } } From f7abd339924efb2bb0882d1c27261d9b50a887bb Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 23 May 2024 21:04:09 +0000 Subject: [PATCH 069/122] Translate Deutsch.json via GitLocalize --- lang/Deutsch.json | 325 +++++++++++++++++++++++----------------------- 1 file changed, 164 insertions(+), 161 deletions(-) diff --git a/lang/Deutsch.json b/lang/Deutsch.json index 2cca9feb..f47ca00f 100644 --- a/lang/Deutsch.json +++ b/lang/Deutsch.json @@ -1,161 +1,164 @@ -{ - "english_name": "German", - "status": { - "terminated": "\nAnwendung gestoppt.\nFenster schließen, um die Anwendung zu beenden", - "watching": "{channel} wird zugesehen", - "goes_online": "{channel} ist ONLINE gegangen, wechseln...", - "goes_offline": "{channel} ist OFFLINE gegangen, wechseln...", - "claimed_drop": "Drop abgeholt: {drop}", - "claimed_points": "Kanal-Punkte verdient: {points}", - "earned_points": "Verdiente Kanal-Punkte fürs zuschauen: {points} | Summe: {balance}", - "no_channel": "Keine teilnehmenden Kanäle online. Warten auf Kanäle...", - "no_campaign": "Keine aktiven Kampagnen verfügbar. Warten auf neue Kampagne..." - }, - "login": { - "chrome": { - "startup": "Starte Chrome...", - "login_to_complete": "Erneut auf Anmelden drücken, um den Anmeldevorgang manuell abzuschließen.", - "no_token": "Es wurde kein Autorisierungs-Token gefunden.", - "closed_window": "Das Chrome-Fenster wurde geschlossen, bevor der Anmeldevorgang abgeschlossen werden konnte." - }, - "error_code": "Login-Fehlercode: {error_code}", - "unexpected_content": "Unerwarteter Inhaltstyp zurückgegeben, normalerweise aufgrund einer Weiterleitung.\nIst ein Login für den Internetzugang erforderlich?", - "incorrect_login_pass": "Falscher Benutzername oder Passwort.", - "incorrect_email_code": "Falscher E-Mail Code.", - "incorrect_twofa_code": "Falscher 2FA Code.", - "email_code_required": "E-Mail Code erforderlich. Bitte E-Mail prüfen.", - "twofa_code_required": "2FA Token erforderlich." - }, - "error": { - "captcha": "Der Anmeldeversuch wurde durch CAPTCHA verweigert.\nBitte versuche es in mindestens 12 Stunden erneut.", - "site_down": "Twitch ist nicht erreichbar. Erneuter Versuch in {seconds} Sekunden...", - "no_connection": "Keine Verbindung zu Twitch möglich. Erneuter Versuch in {seconds} Sekunden..." - }, - "gui": { - "output": "Protokoll", - "status": { - "name": "Status", - "idle": "Im Leerlauf", - "exiting": "Beenden...", - "terminated": "Abgebrochen", - "cleanup": "Kanäle aufräumen..", - "gathering": "Kanäle sammeln...", - "switching": "Wechsel des Kanals...", - "fetching_inventory": "Lade Inventar...", - "fetching_campaigns": "Lade Kampagnen...", - "adding_campaigns": "Kampagnen dem Inventar hinzufügen... {counter}" - }, - "tabs": { - "main": "Hauptseite", - "inventory": "Inventar", - "settings": "Einstellungen", - "help": "Hilfe" - }, - "tray": { - "notification_title": "Drop abgeholt", - "minimize": "Minimiere ins System Tray", - "show": "Anzeigen", - "quit": "Beenden" - }, - "login": { - "name": "Login", - "labels": "Status:\nBenutzer ID:", - "logged_in": "Angemeldet", - "logged_out": "Abgemeldet", - "logging_in": "Anmelden...", - "required": "Anmeldung erforderlich", - "request": "Bitte einloggen um fortzufahren.", - "username": "Benutzername", - "password": "Passwort", - "twofa_code": "2FA Code (optional)", - "button": "Anmelden" - }, - "websocket": { - "name": "WebSocket Status", - "websocket": "WebSocket #{id}:", - "initializing": "Initialisieren...", - "connected": "Verbunden", - "disconnected": "Verbindung verloren", - "connecting": "Verbinden...", - "disconnecting": "Verbindung trennen...", - "reconnecting": "Neu verbinden..." - }, - "progress": { - "name": "Kampagnen-Fortschritt", - "drop": "Drop:", - "game": "Spiel:", - "campaign": "Kampagne:", - "remaining": "{time} verbleibend", - "drop_progress": "Fortschritt:", - "campaign_progress": "Fortschritt:" - }, - "channels": { - "name": "Kanäle", - "switch": "Wechseln", - "load_points": "Lade Punkte", - "online": "ONLINE ✔", - "pending": "OFFLINE ⏳", - "offline": "OFFLINE ❌", - "headings": { - "channel": "Kanal", - "status": "Status", - "game": "Spiel", - "viewers": "Zuschauer", - "points": "Punkte" - } - }, - "inventory": { - "filter": { - "name": "Filter", - "show": "Anzeigen:", - "not_linked": "Nicht verbunden", - "upcoming": "Zukünftig", - "expired": "Abgelaufen", - "excluded": "Ausgeschlossen", - "finished": "Abgeholt", - "refresh": "Aktualisieren" - }, - "status": { - "linked": "Verknüpft ✔", - "not_linked": "Nicht verknüpft ❌", - "active": "Aktiv ✔", - "upcoming": "Zukünftig ⏳", - "expired": "Abgelaufen ❌", - "claimed": "Abgeholt ✔", - "ready_to_claim": "Bereit zum abholen ⏳" - }, - "starts": "Beginnt: {time}", - "ends": "Endet: {time}", - "allowed_channels": "Teilnehmende Kanäle:", - "all_channels": "Alle", - "and_more": "und {amount} weitere...", - "percent_progress": "{percent} von {minutes} Minuten", - "minutes_progress": "{minutes} Minuten" - }, - "settings": { - "general": { - "name": "Allgemein", - "autostart": "Autostart: ", - "tray": "Autostart ins System Tray: ", - "priority_only": "Nur Priorität: ", - "proxy": "Proxy (Erfordert Neustart):" - }, - "game_name": "Spiel", - "priority": "Priorität", - "exclude": "Ausschließen", - "reload": "Neu laden", - "reload_text": "Die meisten Änderungen erfordern ein neu laden, um sofort wirksam zu werden: " - }, - "help": { - "links": { - "name": "Hilfreiche Links", - "inventory": "Twitch Inventar ansehen", - "campaigns": "Alle Twitch-Kampagnen ansehen" - }, - "how_it_works": "So funktioniert's", - "how_it_works_text": "Alle ~20 Sekunden fragt die Anwendung Twitch nach einer URL für die Rohdaten des Streams von dem Kanal, dem gerade zugesehen wird. Dann fordert sie die Metadaten dieses Datenstroms an. Dies reicht aus, um den Drop voranzutreiben. Auf diese Weise ist es nicht nötig den Stream herunterzuladen und spart Bandbreite.\nUm den Online- oder Offline-Status der Kanäle aktuell zu halten, wird eine Websocket-Verbindung eingerichtet,\ndie die Kanäle auf ihren Status überprüft.", - "getting_started": "Erste Schritte", - "getting_started_text": "• In der Anwendung anmelden.\n• Stelle sicher, dass das Twitch-Konto mit allen Kampagnen verknüpft ist, an denen Interesse besteht.\n• Sollen alle Drops bearbeitet werden, entferne den Haken bei \"Nur Priorität\" und drücke \"Neu laden\".\n• Sollen nur bestimmte Spiele in betracht gezogen werden, verwende die \"Priorität\" Liste um die Wahl nach Spielen einzugrenzen.\n• Die Liste priorisiert von oben nach unten.\n• Die Option \"Nur Priorität\" verhindert, dass Spiele, die nicht auf der Prioritätenliste stehen, bearbeitet werden.\n• Mit der Liste \"Ausschließen\", ist es möglich Spiele zu filtern, die niemals in betracht gezogen werden sollen.\n• Wenn Listen oder Optionen angepasst wurden, muss \"Neu laden\" gedrückt werden, damit die Änderungen übernommen werden." - } - } -} +{ + "english_name": "German", + "status": { + "terminated": "\nAnwendung gestoppt.\nFenster schließen, um die Anwendung zu beenden", + "watching": "{channel} wird zugesehen", + "goes_online": "{channel} ist ONLINE gegangen, wechseln...", + "goes_offline": "{channel} ist OFFLINE gegangen, wechseln...", + "claimed_drop": "Drop abgeholt: {drop}", + "claimed_points": "Kanal-Punkte verdient: {points}", + "earned_points": "Verdiente Kanal-Punkte fürs zuschauen: {points} | Summe: {balance}", + "no_channel": "Keine teilnehmenden Kanäle online. Warten auf Kanäle...", + "no_campaign": "Keine aktiven Kampagnen verfügbar. Warten auf neue Kampagne..." + }, + "login": { + "unexpected_content": "Unerwarteter Inhaltstyp zurückgegeben, normalerweise aufgrund einer Weiterleitung.\nIst ein Login für den Internetzugang erforderlich?", + "chrome": { + "startup": "Starte Chrome...", + "login_to_complete": "Erneut auf Anmelden drücken, um den Anmeldevorgang manuell abzuschließen.", + "no_token": "Es wurde kein Autorisierungs-Token gefunden.", + "closed_window": "Das Chrome-Fenster wurde geschlossen, bevor der Anmeldevorgang abgeschlossen werden konnte." + }, + "error_code": "Login-Fehlercode: {error_code}", + "incorrect_login_pass": "Falscher Benutzername oder Passwort.", + "incorrect_email_code": "Falscher E-Mail Code.", + "incorrect_twofa_code": "Falscher 2FA Code.", + "email_code_required": "E-Mail Code erforderlich. Bitte E-Mail prüfen.", + "twofa_code_required": "2FA Token erforderlich." + }, + "error": { + "captcha": "Der Anmeldeversuch wurde durch CAPTCHA verweigert.\nBitte versuche es in mindestens 12 Stunden erneut.", + "site_down": "Twitch ist nicht erreichbar. Erneuter Versuch in {seconds} Sekunden...", + "no_connection": "Keine Verbindung zu Twitch möglich. Erneuter Versuch in {seconds} Sekunden..." + }, + "gui": { + "output": "Protokoll", + "status": { + "name": "Status", + "idle": "Im Leerlauf", + "exiting": "Beenden...", + "terminated": "Abgebrochen", + "cleanup": "Kanäle aufräumen..", + "gathering": "Kanäle sammeln...", + "switching": "Wechsel des Kanals...", + "fetching_inventory": "Lade Inventar...", + "fetching_campaigns": "Lade Kampagnen...", + "adding_campaigns": "Kampagnen dem Inventar hinzufügen... {counter}" + }, + "tabs": { + "main": "Hauptseite", + "inventory": "Inventar", + "settings": "Einstellungen", + "help": "Hilfe" + }, + "tray": { + "notification_title": "Drop abgeholt", + "minimize": "Minimiere ins System Tray", + "show": "Anzeigen", + "quit": "Beenden" + }, + "login": { + "name": "Login", + "labels": "Status:\nBenutzer ID:", + "logged_in": "Angemeldet", + "logged_out": "Abgemeldet", + "logging_in": "Anmelden...", + "required": "Anmeldung erforderlich", + "request": "Bitte einloggen um fortzufahren.", + "username": "Benutzername", + "password": "Passwort", + "twofa_code": "2FA Code (optional)", + "button": "Anmelden" + }, + "websocket": { + "name": "WebSocket Status", + "websocket": "WebSocket #{id}:", + "initializing": "Initialisieren...", + "connected": "Verbunden", + "disconnected": "Verbindung verloren", + "connecting": "Verbinden...", + "disconnecting": "Verbindung trennen...", + "reconnecting": "Neu verbinden..." + }, + "progress": { + "name": "Kampagnen-Fortschritt", + "drop": "Drop:", + "game": "Spiel:", + "campaign": "Kampagne:", + "remaining": "{time} verbleibend", + "drop_progress": "Fortschritt:", + "campaign_progress": "Fortschritt:" + }, + "channels": { + "name": "Kanäle", + "switch": "Wechseln", + "load_points": "Lade Punkte", + "online": "ONLINE ✔", + "pending": "OFFLINE ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "Kanal", + "status": "Status", + "game": "Spiel", + "viewers": "Zuschauer", + "points": "Punkte" + } + }, + "inventory": { + "filter": { + "name": "Filter", + "show": "Anzeigen:", + "not_linked": "Nicht verbunden", + "upcoming": "Zukünftig", + "expired": "Abgelaufen", + "excluded": "Ausgeschlossen", + "finished": "Abgeholt", + "refresh": "Aktualisieren" + }, + "status": { + "linked": "Verknüpft ✔", + "not_linked": "Nicht verknüpft ❌", + "active": "Aktiv ✔", + "upcoming": "Zukünftig ⏳", + "expired": "Abgelaufen ❌", + "claimed": "Abgeholt ✔", + "ready_to_claim": "Bereit zum abholen ⏳" + }, + "starts": "Beginnt: {time}", + "ends": "Endet: {time}", + "allowed_channels": "Teilnehmende Kanäle:", + "all_channels": "Alle", + "and_more": "und {amount} weitere...", + "percent_progress": "{percent} von {minutes} Minuten", + "minutes_progress": "{minutes} Minuten" + }, + "settings": { + "general": { + "name": "Allgemein", + "dark_theme": "Dunkler Design: ", + "autostart": "Autostart: ", + "tray": "Autostart ins System Tray: ", + "tray_notifications": "System Tray Benachrichtigungen:", + "priority_only": "Nur Priorität: ", + "prioritze_end": "Kampagnen nach Ende priorisieren: ", + "proxy": "Proxy (Erfordert Neustart):" + }, + "game_name": "Spiel", + "priority": "Priorität", + "exclude": "Ausschließen", + "reload": "Neu laden", + "reload_text": "Die meisten Änderungen erfordern ein neu laden, um sofort wirksam zu werden: " + }, + "help": { + "links": { + "name": "Hilfreiche Links", + "inventory": "Twitch Inventar ansehen", + "campaigns": "Alle Twitch-Kampagnen ansehen" + }, + "how_it_works": "So funktioniert's", + "how_it_works_text": "Alle ~20 Sekunden fragt die Anwendung Twitch nach einer URL für die Rohdaten des Streams von dem Kanal, dem gerade zugesehen wird. Dann fordert sie die Metadaten dieses Datenstroms an. Dies reicht aus, um den Drop voranzutreiben. Auf diese Weise ist es nicht nötig den Stream herunterzuladen und spart Bandbreite.\nUm den Online- oder Offline-Status der Kanäle aktuell zu halten, wird eine Websocket-Verbindung eingerichtet,\ndie die Kanäle auf ihren Status überprüft.", + "getting_started": "Erste Schritte", + "getting_started_text": "• In der Anwendung anmelden.\n• Stelle sicher, dass das Twitch-Konto mit allen Kampagnen verknüpft ist, an denen Interesse besteht.\n• Sollen alle Drops bearbeitet werden, entferne den Haken bei \"Nur Priorität\" und drücke \"Neu laden\".\n• Sollen nur bestimmte Spiele in betracht gezogen werden, verwende die \"Priorität\" Liste um die Wahl nach Spielen einzugrenzen.\n• Die Liste priorisiert von oben nach unten.\n• Die Option \"Nur Priorität\" verhindert, dass Spiele, die nicht auf der Prioritätenliste stehen, bearbeitet werden.\n• Mit der Liste \"Ausschließen\", ist es möglich Spiele zu filtern, die niemals in betracht gezogen werden sollen.\n• Wenn Listen oder Optionen angepasst wurden, muss \"Neu laden\" gedrückt werden, damit die Änderungen übernommen werden." + } + } +} From 8dab6ebbaba90b104888e6bfe34de70e1ec20f0a Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 23 May 2024 21:03:39 +0000 Subject: [PATCH 070/122] =?UTF-8?q?Translate=20=C4=8Ce=C5=A1tina.json=20vi?= =?UTF-8?q?a=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "lang/\304\214e\305\241tina.json" | 302 +++++++++++++++--------------- 1 file changed, 156 insertions(+), 146 deletions(-) diff --git "a/lang/\304\214e\305\241tina.json" "b/lang/\304\214e\305\241tina.json" index 0f1df371..60e9d303 100644 --- "a/lang/\304\214e\305\241tina.json" +++ "b/lang/\304\214e\305\241tina.json" @@ -1,154 +1,164 @@ { - "english_name": "Czech", + "english_name": "Czech", + "status": { + "terminated": "\nAplikace byla ukončena.", + "watching": "Sledování kanálu: {channel}", + "goes_online": "Kanál {channel} je online, přepínám...", + "goes_offline": "Kanál {channel} je offline, přepínám na další...", + "claimed_drop": "Drop vyzvednut: {drop}", + "claimed_points": "Vyzvednuto {points} bodů", + "earned_points": "Získáno {points} bodů za sledování. Celkem: {balance}", + "no_channel": "Žádný kanál není dostupný, čekání na další...", + "no_campaign": "Žádné dropy k dispozici, čekání na další dostupné dropy..." + }, + "login": { + "unexpected_content": "Chyba při přesměrování. Nepoužíváte VPN?", + "chrome": { + "startup": "Otevírá se Chrome...", + "login_to_complete": "Automaticky dokončete proces přihlášení opětovným kliknutím na tlačítko přihlásit.", + "no_token": "Nebyl nalezen žádný autorizační token.", + "closed_window": "Okno Chrome bylo zavřeno před dokončním procesu přihlášení." + }, + "error_code": "Chyba přihlášení: {error_code}", + "incorrect_login_pass": "Nesprávné uživatelské jméno nebo heslo.", + "incorrect_email_code": "Nesprávný E-Mail kód.", + "incorrect_twofa_code": "Nesprávný dvoufaktorový token", + "email_code_required": "K přihlášení je vyžadován kód který byl zaslán na váš E-Mail.", + "twofa_code_required": "K přihlášení je vyžadován dvoufaktorový kód." + }, + "error": { + "captcha": "Vaše připojení bylo zamítnuto systémem přihlásit.CAPTCHA, zkuste to znovu za 12 hodin.", + "site_down": "Služba Twitch je nedostupná,zkuste to znovu za {seconds} sekund...", + "no_connection": "Nelze se připojit k službe Twitch, zkuste to znovu za {seconds}..." + }, + "gui": { + "output": "Výstup", "status": { - "terminated": "\nAplikace byla ukončena.", - "watching": "Sledování kanálu: {channel}", - "goes_online": "Kanál {channel} je online, přepínám...", - "goes_offline": "Kanál {channel} je offline, přepínám na další...", - "claimed_drop": "Drop vyzvednut: {drop}", - "claimed_points": "Vyzvednuto {points} bodů", - "earned_points": "Získáno {points} bodů za sledování. Celkem: {balance}", - "no_channel": "Žádný kanál není dostupný, čekání na další...", - "no_campaign": "Žádné dropy k dispozici, čekání na další dostupné dropy..." + "name": "Status", + "idle": "Dokončeno načítání", + "exiting": "Ukončování...", + "terminated": "Aplikace ukončena", + "cleanup": "Čištění...", + "gathering": "Vyhledávání dostupného živého kanálu...", + "switching": "Přepínám mezi kanály...", + "fetching_inventory": "Načítání inventáře...", + "fetching_campaigns": "Načítání dropů...", + "adding_campaigns": "Přidávám dropy... {counter}" + }, + "tabs": { + "main": "Hlavní Panel", + "inventory": "Inventář", + "settings": "Nastavení", + "help": "Nápověda" + }, + "tray": { + "notification_title": "Začít sbírat dropy", + "minimize": "Minimalizovat", + "show": "Zobrazit", + "quit": "Ukončit" }, "login": { - "unexpected_content": "Chyba při přesměrování. Nepoužíváte VPN?", - "incorrect_login_pass": "Nesprávné přihlašení.", - "incorrect_email_code": "Nesprávný E-Mail kód.", - "incorrect_twofa_code": "Nesprávný dvoufaktorový token", - "email_code_required": "K přihlášení je vyžadován kód který byl zaslán na váš E-Mail.", - "twofa_code_required": "K přihlášení je vyžadován dvoufaktorový kód." + "name": "Přihlášení k službě Twitch", + "labels": "Uživatelské ID:", + "logged_in": "Přihlášeno", + "logged_out": "Odhlášeno", + "logging_in": "Přihlašování...", + "required": "Potřebujete se nejdříve přihlásit", + "request": "Pro přístup je potřeba přihlášení", + "username": "Uživatelské Jméno", + "password": "Heslo", + "twofa_code": "2FA Kód", + "button": "Přihlásit se" + }, + "websocket": { + "name": "Status Připojení Síťového Protokolu", + "websocket": "Websocket #{id}:", + "initializing": "Načítání", + "connected": "Připojeno", + "disconnected": "Odpojeno", + "connecting": "Připojování...", + "disconnecting": "Odpojování...", + "reconnecting": "Přepojování..." + }, + "progress": { + "name": "Průběh Dropu", + "drop": "Drop Odměny:", + "game": "Hra:", + "campaign": "Kampaň:", + "remaining": "Zbývá {time}", + "drop_progress": "Průběh dropu:", + "campaign_progress": "Průběh kampaňe:" + }, + "channels": { + "name": "Název", + "switch": "Přepnout", + "load_points": "Načíst body", + "online": "ONLINE ✔", + "pending": "PRŮBĚH ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "Kanál", + "status": "Status", + "game": "Hra", + "viewers": "Diváci", + "points": "Body" + } + }, + "inventory": { + "filter": { + "name": "Filtr", + "show": "Drop:", + "not_linked": "Nepropojeno", + "upcoming": "Nadcházející", + "expired": "Ukončeno", + "excluded": "Vynecháno", + "finished": "Dokončeno", + "refresh": "Obnovit" + }, + "status": { + "linked": "ŽIVĚ ✔", + "not_linked": "Zatím nejsou dostupné žádné kanály ❌", + "active": "ŽIVĚ ✔", + "upcoming": "Nadcházející ⏳", + "expired": "Ukončeno ❌", + "claimed": "Vyzvednuto ✔", + "ready_to_claim": "Připraveno k vyzvednutí ⏳" + }, + "starts": "Začíná: {time}", + "ends": "Začíná: {time}", + "allowed_channels": "Povolené kanály:", + "all_channels": "Všechny kanály", + "and_more": "Je tu {amount} ...", + "percent_progress": "{minutes} minut {percent}", + "minutes_progress": "{minutes} minut" }, - "error": { - "captcha": "Vaše připojení bylo zamítnuto službou Twitch, zkuste to znovu za 12 hodin.", - "site_down": "Služba Twitch je nedostupná,zkuste to znovu za {seconds} sekund...", - "no_connection": "Nelze se připojit k službe Twitch, zkuste to znovu za {seconds}..." + "settings": { + "general": { + "name": "Nastavení", + "dark_theme": "Tmavý vzhled: ", + "autostart": "Automatické spuštění: ", + "tray": "Automaticky spusti minimalizovaně: ", + "tray_notifications": "Oznámení v systémové liště:", + "priority_only": "Pouze prioritní: ", + "prioritze_end": "Upřednostnit kampaně podle data ukončení:", + "proxy": "Proxy:" + }, + "game_name": "Název Hry", + "priority": "Priorita", + "exclude": "Vynechat", + "reload": "Obnovit", + "reload_text": "Většina změn vyžaduje restart aplikace nebo obnovení: " }, - "gui": { - "output": "Výstup", - "status": { - "name": "Status", - "idle": "Dokončeno načítání", - "exiting": "Ukončování...", - "terminated": "Aplikace ukončena", - "cleanup": "Čištění...", - "gathering": "Vyhledávání dostupného živého kanálu...", - "switching": "Přepínám mezi kanály...", - "fetching_inventory": "Načítání inventáře...", - "fetching_campaigns": "Načítání dropů...", - "adding_campaigns": "Přidávám dropy... {counter}" - }, - "tabs": { - "main": "Hlavní Panel", - "inventory": "Inventář", - "settings": "Nastavení", - "help": "Nápověda" - }, - "tray": { - "notification_title": "Začít sbírat dropy", - "minimize": "Minimalizovat", - "show": "Zobrazit", - "quit": "Ukončit" - }, - "login": { - "name": "Přihlášení k službě Twitch", - "labels": "Uživatelské ID:", - "logged_in": "Přihlášeno", - "logged_out": "Odhlášeno", - "logging_in": "Přihlašování...", - "required": "Potřebujete se nejdříve přihlásit", - "request": "Pro přístup je potřeba přihlášení", - "username": "Uživatelské Jméno", - "password": "Heslo", - "twofa_code": "2FA Kód", - "button": "Přihlásit se" - }, - "websocket": { - "name": "Status Připojení Síťového Protokolu", - "websocket": "Websocket #{id}:", - "initializing": "Načítání", - "connected": "Připojeno", - "disconnected": "Odpojeno", - "connecting": "Připojování...", - "disconnecting": "Odpojování...", - "reconnecting": "Přepojování..." - }, - "progress": { - "name": "Průběh Dropu", - "drop": "Drop Odměny:", - "game": "Hra:", - "campaign": "Kampaň:", - "remaining": "Zbývá {time}", - "drop_progress": "Průběh dropu:", - "campaign_progress": "Průběh kampaňe:" - }, - "channels": { - "name": "Název", - "switch": "Přepnout", - "load_points": "Načíst body", - "online": "ONLINE \u2714", - "pending": "PRŮBĚH \u23f3", - "offline": "OFFLINE \u274c", - "headings": { - "channel": "Kanál", - "game": "Hra", - "points": "Body", - "status": "Status", - "viewers": "Diváci" - } - }, - "inventory": { - "filter": { - "name": "Filtr", - "show": "Drop:", - "not_linked": "Nepropojeno", - "expired": "Ukončeno", - "excluded": "Vynecháno", - "upcoming": "Nadcházející", - "finished": "Dokončeno", - "refresh": "Obnovit" - }, - "status": { - "linked": "ŽIVĚ \u2714", - "not_linked": "Zatím nejsou dostupné žádné kanály \u274c", - "active": "ŽIVĚ \u2714", - "upcoming": "Nadcházející \u23f3", - "expired": "Ukončeno \u274c", - "claimed": "Vyzvednuto \u2714", - "ready_to_claim": "Připraveno k vyzvednutí \u23f3" - }, - "starts": "Začíná: {time}", - "ends": "Začíná: {time}", - "allowed_channels": "Povolené kanály:", - "all_channels": "Všechny kanály", - "and_more": "Je tu {amount} ...", - "percent_progress": "{minutes} minut {percent}", - "minutes_progress": "{minutes} minut" - }, - "settings": { - "general": { - "name": "Nastavení", - "autostart": "Automatické spuštění: ", - "tray": "Automaticky spusti minimalizovaně: ", - "priority_only": "Pouze prioritní: ", - "proxy": "Proxy:" - }, - "game_name": "Název Hry", - "priority": "Priorita", - "exclude": "Vynechat", - "reload": "Obnovit", - "reload_text": "Většina změn vyžaduje restart aplikace nebo obnovení: " - }, - "help": { - "links": { - "name": "Nápověda", - "inventory": "Zobrazit Twitch Inventář", - "campaigns": "Zobrazit všechny kampaňe a spravovat propojené účty" - }, - "how_it_works": "Jak to funguje", - "how_it_works_text": "Každých ~20 sekund aplikace požádá Twitch o adresu k čistým datám streamu od kanálu, který je v současnosti sledován. Poté stáhne dodatkové informace těchto dat streamu - to stačí k posunu umístění. Všimněte si, že tímto způsobem zcela odpadá nutnost stahovat skutečné streamované video a zvuk. Aby byl stav kanálu (online nebo offline) stále aktuální, je navázáno spojení přes websocket, které přijímá události o spuštění nebo vypnutí streamů nebo aktualizace o aktuálním počtu diváků.", - "getting_started": "Jak začít", - "getting_started_text": "1. Přihlaste se do aplikace. \n2. Ujistěte se, že je váš účet Twitch spojen se všemi reklamními sériemi, které chcete těžit. \n3. Pokud chcete klepnout pouze na veškerý obsah, zrušte zaškrtnutí políčka 'Pouze prioritní' a stiskněte tlačítko 'Obnovit'. \n4. Pokud se chcete nejprve věnovat konkrétním hrám, použijte seznam 'Prioritní' a nastavte si pořadí vybraných her. Nejprve se vyzkouší hry na začátku seznamu a poté hry na konci seznamu. \n5. Ponechte zaškrtnutou možnost 'Pouze prioritní', abyste se vyhnuli vyhledávání her, které nejsou na seznamu priorit. Nebo ne - záleží na vás. \n6. Pomocí seznamu 'vyloučit' můžete aplikaci sdělit, které hry by neměly být vytěženy. \n7. Změna obsahu obou seznamů nebo stavu možnosti Pouze prioritní vyžaduje stisknutí tlačítka Znovu načíst, aby se změna projevila." - } + "help": { + "links": { + "name": "Nápověda", + "inventory": "Zobrazit Twitch Inventář", + "campaigns": "Zobrazit všechny kampaňe a spravovat propojené účty" + }, + "how_it_works": "Jak to funguje", + "how_it_works_text": "Každých ~20 sekund aplikace požádá Twitch o adresu k čistým datám streamu od kanálu, který je v současnosti sledován. Poté stáhne dodatkové informace těchto dat streamu - to stačí k posunu umístění. Všimněte si, že tímto způsobem zcela odpadá nutnost stahovat skutečné streamované video a zvuk. Aby byl stav kanálu (online nebo offline) stále aktuální, je navázáno spojení přes websocket, které přijímá události o spuštění nebo vypnutí streamů nebo aktualizace o aktuálním počtu diváků.", + "getting_started": "Jak začít", + "getting_started_text": "1. Přihlaste se do aplikace. \n2. Ujistěte se, že je váš účet Twitch spojen se všemi reklamními sériemi, které chcete těžit. \n3. Pokud chcete klepnout pouze na veškerý obsah, zrušte zaškrtnutí políčka 'Pouze prioritní' a stiskněte tlačítko 'Obnovit'. \n4. Pokud se chcete nejprve věnovat konkrétním hrám, použijte seznam 'Prioritní' a nastavte si pořadí vybraných her. Nejprve se vyzkouší hry na začátku seznamu a poté hry na konci seznamu. \n5. Ponechte zaškrtnutou možnost 'Pouze prioritní', abyste se vyhnuli vyhledávání her, které nejsou na seznamu priorit. Nebo ne - záleží na vás. \n6. Pomocí seznamu 'vyloučit' můžete aplikaci sdělit, které hry by neměly být vytěženy. \n7. Změna obsahu obou seznamů nebo stavu možnosti Pouze prioritní vyžaduje stisknutí tlačítka Znovu načíst, aby se změna projevila." } + } } From 23bc198f3a8c673a5e4e86511c4a061680c33fbd Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 23 May 2024 23:27:50 +0200 Subject: [PATCH 071/122] updated patch notes --- patch_notes.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/patch_notes.txt b/patch_notes.txt index bb2ba5fb..67eac595 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,8 +1,12 @@ -## v15.3.0 +## v15.4.0 ### 23.5.2024 - Fixed crash on Linux -- Updated English, German, Czech, Spanish and Russian translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date. +- Updated English, German, Czech, Spanish and Russian translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date + + + +## v15.3.0 ### 22.5.2024 - Completed dark mode 🎉 @@ -10,7 +14,10 @@ ### 20.5.2024 - Added incomplete dark mode + + ## v15.2.0 + ### 19.5.2024 - Updated French translation as well as corresponding credits @@ -18,7 +25,10 @@ - Updated Russian, Ukrainian and Traditional Chinese translation as well as corresponding credits - Various changes to github workflows + + ## v15.1.0 + ### 17.5.2024 - Updated Italian, Simplified Chinese and Spanish translation as well as corresponding credits - Various changes to github workflows \ No newline at end of file From 1e8c2a33bd1b0037811217ea5f49668106facbae Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 23 May 2024 23:45:52 +0200 Subject: [PATCH 072/122] more detailed patch notes --- patch_notes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch_notes.txt b/patch_notes.txt index 67eac595..23a26ca9 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,7 +1,7 @@ ## v15.4.0 ### 23.5.2024 -- Fixed crash on Linux +- Fixed crash on Linux caused by trying to apply a Windows-exclusive Tkinter theme - Updated English, German, Czech, Spanish and Russian translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date From c130fa8f9aa6636615df27b79e47be9175d47d4a Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 18:36:46 +0200 Subject: [PATCH 073/122] Add sorting by end_at setting by @jaredkotoff --- gui.py | 18 ++++++++++--- inventory.py | 4 +++ lang/English.json | 2 +- settings.py | 5 +++- translate.py | 5 ++-- twitch.py | 64 +++++++++++++++++++++++++++++------------------ 6 files changed, 67 insertions(+), 31 deletions(-) diff --git a/gui.py b/gui.py index e51bf75c..7f72d5cb 100644 --- a/gui.py +++ b/gui.py @@ -1458,6 +1458,7 @@ class _SettingsVars(TypedDict): dark_theme: IntVar autostart: IntVar priority_only: IntVar + prioritze_end: IntVar tray_notifications: IntVar @@ -1476,6 +1477,7 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): "dark_theme": IntVar(master, self._settings.dark_theme), "autostart": IntVar(master, self._settings.autostart), "priority_only": IntVar(master, self._settings.priority_only), + "prioritze_end": IntVar(master, self._settings.prioritze_end), "tray_notifications": IntVar(master, self._settings.tray_notifications), } master.rowconfigure(0, weight=1) @@ -1540,6 +1542,12 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): ttk.Checkbutton( checkboxes_frame, variable=self._vars["priority_only"], command=self.priority_only ).grid(column=1, row=irow, sticky="w") + ttk.Label( + checkboxes_frame, text=_("gui", "settings", "general", "prioritze_end") + ).grid(column=0, row=(irow := irow + 1), sticky="e") + ttk.Checkbutton( + checkboxes_frame, variable=self._vars["prioritze_end"], command=self.prioritze_end + ).grid(column=1, row=irow, sticky="w") # proxy frame proxy_frame = ttk.Frame(center_frame2) proxy_frame.grid(column=0, row=2) @@ -1759,6 +1767,9 @@ def priority_delete(self) -> None: def priority_only(self) -> None: self._settings.priority_only = bool(self._vars["priority_only"].get()) + def prioritze_end(self) -> None: + self._settings.prioritze_end = bool(self._vars["prioritze_end"].get()) + def exclude_add(self) -> None: game_name: str = self._exclude_entry.get() if not game_name: @@ -2173,7 +2184,7 @@ def configure_combobox_list(combobox, flag, value): popdown_window = combobox.tk.call("ttk::combobox::PopdownWindow", combobox) listbox = f"{popdown_window}.f.l" combobox.tk.call(listbox, "configure", flag, value) - + # Style options, !!!"background" and "bg" is not interchangable for some reason!!! match name: case "dark": @@ -2225,7 +2236,7 @@ def configure_combobox_list(combobox, flag, value): configure_combobox_list(manager.settings._exclude_entry, "-background", bg_grey) configure_combobox_list(manager.settings._exclude_entry, "-foreground", "white") configure_combobox_list(manager.settings._exclude_entry, "-selectbackground", active_grey) - + case "light" | "default" | _ : # When creating a new theme, additional values might need to be set, so the default theme remains consistent # General style.theme_use(set_theme.default_style) @@ -2388,6 +2399,7 @@ async def main(exit_event: asyncio.Event): autostart=False, language="English", priority_only=False, + prioritze_end=False, autostart_tray=False, exclude={"Lit Game"}, tray_notifications=True @@ -2510,4 +2522,4 @@ def main_exit(task: asyncio.Task[None]) -> None: main_task.add_done_callback(main_exit) loop.run_until_complete(exit_event.wait()) if main_task.done(): - loop.run_until_complete(main_task) + loop.run_until_complete(main_task) \ No newline at end of file diff --git a/inventory.py b/inventory.py index c830ccd9..23d7422d 100644 --- a/inventory.py +++ b/inventory.py @@ -354,3 +354,7 @@ def can_earn_within(self, stamp: datetime) -> bool: and self.starts_at < stamp and any(drop.can_earn_within(stamp) for drop in self.drops) ) + + def can_earn_within_next_hour(self): + next_hour = datetime.now(timezone.utc) + timedelta(hours=1) + return self.can_earn_within(next_hour) \ No newline at end of file diff --git a/lang/English.json b/lang/English.json index b3add9cc..06e06e05 100644 --- a/lang/English.json +++ b/lang/English.json @@ -140,7 +140,7 @@ "tray": "Autostart into tray: ", "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", - "prioritze_end": "Prioritize campaigns by end date: ", + "prioritze_end": "Prioritize by ending soonest: ", "proxy": "Proxy (requires restart):" }, "game_name": "Game name", diff --git a/settings.py b/settings.py index 07200d34..4e282188 100644 --- a/settings.py +++ b/settings.py @@ -19,6 +19,7 @@ class SettingsFile(TypedDict): exclude: set[str] priority: list[str] priority_only: bool + prioritze_end: bool autostart_tray: bool connection_quality: int tray_notifications: bool @@ -31,6 +32,7 @@ class SettingsFile(TypedDict): "dark_theme": False, "autostart": False, "priority_only": True, + "prioritze_end": False, "autostart_tray": False, "connection_quality": 1, "language": DEFAULT_LANG, @@ -55,6 +57,7 @@ class Settings: exclude: set[str] priority: list[str] priority_only: bool + prioritze_end: bool autostart_tray: bool connection_quality: int tray_notifications: bool @@ -95,4 +98,4 @@ def alter(self) -> None: def save(self, *, force: bool = False) -> None: if self._altered or force: - json_save(SETTINGS_PATH, self._settings, sort=True) + json_save(SETTINGS_PATH, self._settings, sort=True) \ No newline at end of file diff --git a/translate.py b/translate.py index da6b8535..de5a63b7 100644 --- a/translate.py +++ b/translate.py @@ -166,6 +166,7 @@ class GUISettingsGeneral(TypedDict): tray: str tray_notifications: str priority_only: str + prioritze_end: str proxy: str @@ -364,7 +365,7 @@ class Translation(TypedDict): "tray": "Autostart into tray: ", "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", - "prioritze_end": "Prioritize campaigns by end date: ", + "prioritze_end": "Prioritize by ending soonest: ", "proxy": "Proxy (requires restart):", }, "game_name": "Game name", @@ -470,4 +471,4 @@ def __call__(self, *path: str) -> str: return v -_ = Translator() +_ = Translator() \ No newline at end of file diff --git a/twitch.py b/twitch.py index 6ae0a35a..b712613b 100644 --- a/twitch.py +++ b/twitch.py @@ -747,14 +747,17 @@ def get_priority(self, channel: Channel) -> int: Return a priority number for a given channel. Higher number, higher priority. - Priority 0 is given to channels streaming a game not on the priority list. - Priority -1 is given to OFFLINE channels, or channels streaming no particular games. + Priority requested games are > 0 + Non-priority games are < 0 + (maxsize - 1) Priority is given to OFFLINE channels, or channels streaming no particular games. + (maxsize - 2) Priority is given to channels streaming games without campaigns. """ if (game := channel.game) is None: # None when OFFLINE or no game set - return -1 + return -(sys.maxsize - 1) elif game not in self.wanted_games: - return 0 + # Any channel thats is filtered out by filter_campaigns() + return -(sys.maxsize - 2) return self.wanted_games[game] @staticmethod @@ -826,22 +829,21 @@ async def _run(self): # figure out which games we want self.wanted_games.clear() priorities = self.gui.settings.priorities() - exclude = self.settings.exclude - priority = self.settings.priority - priority_only = self.settings.priority_only - next_hour = datetime.now(timezone.utc) + timedelta(hours=1) - for campaign in self.inventory: + prioritze_end = self.settings.prioritze_end + campaigns = self.inventory + filtered_campaigns = list(filter(self.filter_campaigns, campaigns)) + for i, campaign in enumerate(filtered_campaigns): game = campaign.game - if ( - game not in self.wanted_games # isn't already there - and game.name not in exclude # and isn't excluded - # and isn't excluded by priority_only - and (not priority_only or game.name in priority) - # and can be progressed within the next hour - and campaign.can_earn_within(next_hour) - ): - # non-excluded games with no priority are placed last, below priority ones - self.wanted_games[game] = priorities.get(game.name, 0) + # get users priority preference + game_priority = priorities.get(game.name, 0) + if (game_priority): + if (prioritze_end): + # list is sorted by end_at so this keeps them in order + self.wanted_games[game] = len(filtered_campaigns) - i + else: + self.wanted_games[game] = game_priority + else: + self.wanted_games[game] = -i full_cleanup = True self.restart_watching() self.change_state(State.CHANNELS_CLEANUP) @@ -896,11 +898,10 @@ async def _run(self): # NOTE: we use another set so that we can set them online separately no_acl: set[Game] = set() acl_channels: OrderedSet[Channel] = OrderedSet() - next_hour = datetime.now(timezone.utc) + timedelta(hours=1) for campaign in self.inventory: if ( campaign.game in self.wanted_games - and campaign.can_earn_within(next_hour) + and campaign.can_earn_within_next_hour() ): if campaign.allowed_channels: acl_channels.update(campaign.allowed_channels) @@ -1617,6 +1618,22 @@ async def fetch_campaigns( } return self._merge_data(campaign_ids, fetched_data) + def filter_campaigns(self, campaign: list[DropsCampaign]): + exclude = self.settings.exclude + priority = self.settings.priority + priority_only = self.settings.priority_only + game = campaign.game + if ( + game not in self.wanted_games # isn't already there + and game.name not in exclude # and isn't excluded + # and isn't excluded by priority_only + and (not priority_only or game.name in priority) + # and can be progressed within the next hour + and campaign.can_earn_within_next_hour() + ): + return True + return False + async def fetch_inventory(self) -> None: status_update = self.gui.status.update status_update(_("gui", "status", "fetching_inventory")) @@ -1663,13 +1680,12 @@ async def fetch_inventory(self) -> None: self.gui.inv.clear() self.inventory.clear() switch_triggers: set[datetime] = set() - next_hour = datetime.now(timezone.utc) + timedelta(hours=1) for i, campaign in enumerate(campaigns, start=1): status_update( _("gui", "status", "adding_campaigns").format(counter=f"({i}/{len(campaigns)})") ) self._drops.update({drop.id: drop for drop in campaign.drops}) - if campaign.can_earn_within(next_hour): + if campaign.can_earn_within_next_hour(): switch_triggers.update(campaign.time_triggers) # NOTE: this fetches pictures from the CDN, so might be slow without a cache await self.gui.inv.add_campaign(campaign) @@ -1738,4 +1754,4 @@ async def claim_points(self, channel_id: str | int, claim_id: str) -> None: GQL_OPERATIONS["ClaimCommunityPoints"].with_variables( {"input": {"channelID": str(channel_id), "claimID": claim_id}} ) - ) + ) \ No newline at end of file From d16d1d44f262841dceb8e5179ae3c94022b33451 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 18:52:06 +0200 Subject: [PATCH 074/122] patch notes and newlines at end of files --- README.md | 2 +- gui.py | 2 +- inventory.py | 2 +- patch_notes.txt | 18 +++++++++++++----- settings.py | 2 +- translate.py | 2 +- twitch.py | 2 +- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f189545a..5cc59532 100644 --- a/README.md +++ b/README.md @@ -132,4 +132,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns \ No newline at end of file +For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns diff --git a/gui.py b/gui.py index 7f72d5cb..0d06bd19 100644 --- a/gui.py +++ b/gui.py @@ -2522,4 +2522,4 @@ def main_exit(task: asyncio.Task[None]) -> None: main_task.add_done_callback(main_exit) loop.run_until_complete(exit_event.wait()) if main_task.done(): - loop.run_until_complete(main_task) \ No newline at end of file + loop.run_until_complete(main_task) diff --git a/inventory.py b/inventory.py index 23d7422d..eb1f048e 100644 --- a/inventory.py +++ b/inventory.py @@ -357,4 +357,4 @@ def can_earn_within(self, stamp: datetime) -> bool: def can_earn_within_next_hour(self): next_hour = datetime.now(timezone.utc) + timedelta(hours=1) - return self.can_earn_within(next_hour) \ No newline at end of file + return self.can_earn_within(next_hour) diff --git a/patch_notes.txt b/patch_notes.txt index 23a26ca9..338f6742 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,8 +1,16 @@ +## v15.4.0 + +### 25.5.2024 +- Added ability to sort by Campaign end date (made by @jaredkotoff) +- Updated English, German, Czech, Spanish and Russian translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date + + + ## v15.4.0 ### 23.5.2024 - Fixed crash on Linux caused by trying to apply a Windows-exclusive Tkinter theme -- Updated English, German, Czech, Spanish and Russian translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date +- Updated **English**, **German**, **Czech**, **Spanish** and **Russian** translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date @@ -19,10 +27,10 @@ ## v15.2.0 ### 19.5.2024 -- Updated French translation as well as corresponding credits +- Updated **French** translation as well as corresponding credits ### 18.5.2024 -- Updated Russian, Ukrainian and Traditional Chinese translation as well as corresponding credits +- Updated **Russian**, **Ukrainian** and **Traditional Chinese** translation as well as corresponding credits - Various changes to github workflows @@ -30,5 +38,5 @@ ## v15.1.0 ### 17.5.2024 -- Updated Italian, Simplified Chinese and Spanish translation as well as corresponding credits -- Various changes to github workflows \ No newline at end of file +- Updated **Italian**, **Simplified Chinese** and **Spanish** translation as well as corresponding credits +- Various changes to github workflows diff --git a/settings.py b/settings.py index 4e282188..72a531b4 100644 --- a/settings.py +++ b/settings.py @@ -98,4 +98,4 @@ def alter(self) -> None: def save(self, *, force: bool = False) -> None: if self._altered or force: - json_save(SETTINGS_PATH, self._settings, sort=True) \ No newline at end of file + json_save(SETTINGS_PATH, self._settings, sort=True) diff --git a/translate.py b/translate.py index de5a63b7..0a694a1d 100644 --- a/translate.py +++ b/translate.py @@ -471,4 +471,4 @@ def __call__(self, *path: str) -> str: return v -_ = Translator() \ No newline at end of file +_ = Translator() diff --git a/twitch.py b/twitch.py index b712613b..32580f2d 100644 --- a/twitch.py +++ b/twitch.py @@ -1754,4 +1754,4 @@ async def claim_points(self, channel_id: str | int, claim_id: str) -> None: GQL_OPERATIONS["ClaimCommunityPoints"].with_variables( {"input": {"channelID": str(channel_id), "claimID": claim_id}} ) - ) \ No newline at end of file + ) From 919ac15015773c6058407142a8a04be8bca3021f Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 19:01:12 +0200 Subject: [PATCH 075/122] updated patch notes --- patch_notes.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patch_notes.txt b/patch_notes.txt index 338f6742..a352926a 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,8 +1,8 @@ -## v15.4.0 +## v15.5.0 ### 25.5.2024 - Added ability to sort by Campaign end date (made by @jaredkotoff) -- Updated English, German, Czech, Spanish and Russian translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date +- Updated ... translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date From a2434c4552aae85493c232ce069d36aa43f9d236 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 17:12:58 +0000 Subject: [PATCH 076/122] =?UTF-8?q?Translate=20=E7=B9=81=E9=AB=94=E4=B8=AD?= =?UTF-8?q?=E6=96=87.json=20via=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\351\253\224\344\270\255\346\226\207.json" | 310 +++++++++--------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git "a/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" "b/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" index ef226783..69496172 100644 --- "a/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" +++ "b/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" @@ -1,162 +1,164 @@ { - "english_name": "Traditional Chinese", + "english_name": "Traditional Chinese", + "status": { + "terminated": "\n應用程序已終止,請關閉窗口以退出應用程序。", + "watching": "正在觀看: {channel}", + "goes_online": "{channel} 該頻道已上線, 正在切換...", + "goes_offline": "{channel} 該頻道已離線, 正在切換...", + "claimed_drop": "領取的掉寶: {drop}", + "claimed_points": "領取的積分獎勵: {points}", + "earned_points": "觀看直播獲得積分: {points}, 總積分: {balance}", + "no_channel": "沒有可觀看的頻道,等待一個在線直播頻道...", + "no_campaign": "沒有可用於掉寶的活動,等待一個有效的掉寶活動..." + }, + "login": { + "unexpected_content": "返回的內容類型有誤通常是由於被重定向.您需要設置VPN或者確認登錄頁面才能聯網嗎?", + "chrome": { + "startup": "正在打開Chrome瀏覽器...", + "login_to_complete": "請再次點擊登錄按鈕來完成登陸.", + "no_token": "無法獲取授權令牌.", + "closed_window": "在登錄完成之前關閉了Chrome瀏覽器." + }, + "error_code": "登錄出錯: {error_code}", + "incorrect_login_pass": "用戶名或密碼錯誤.", + "incorrect_email_code": "電子郵箱驗證碼錯誤.", + "incorrect_twofa_code": "雙重驗證2FA令牌錯誤.", + "email_code_required": "需要電子郵件驗證碼 查看你的郵件.", + "twofa_code_required": "需要雙重驗證2FA令牌." + }, + "error": { + "captcha": "您的登錄存在異常,Twitch官方已進行限制,請在12小時後重試.", + "site_down": "Twitch無法連接,{seconds} 秒後重試...", + "no_connection": "無法連接到Twitch,請確保已經開啟VPN並添加了代理,{seconds} 秒後重試..." + }, + "gui": { + "output": "輸出日志", "status": { - "terminated": "\n應用程序已終止,請關閉窗口以退出應用程序。", - "watching": "正在觀看: {channel}", - "goes_online": "{channel} 該頻道已上線, 正在切換...", - "goes_offline": "{channel} 該頻道已離線, 正在切換...", - "claimed_drop": "領取的掉寶: {drop}", - "claimed_points": "領取的積分獎勵: {points}", - "earned_points": "觀看直播獲得積分: {points}, 總積分: {balance}", - "no_channel": "沒有可觀看的頻道,等待一個在線直播頻道...", - "no_campaign": "沒有可用於掉寶的活動,等待一個有效的掉寶活動..." + "name": "狀態", + "idle": "已完成獲取", + "exiting": "正在退出...", + "terminated": "應用已終止運行", + "cleanup": "清除頻道中...", + "gathering": "搜索直播頻道...", + "switching": "切換直播頻道中...", + "fetching_inventory": "獲取庫存中...", + "fetching_campaigns": "獲取掉寶活動...", + "adding_campaigns": "將掉寶活動列表添加至庫存... {counter}" + }, + "tabs": { + "main": "主面板", + "inventory": "掉寶庫存", + "settings": "設置", + "help": "幫助" + }, + "tray": { + "notification_title": "開始掉寶活動", + "minimize": "窗口最小化", + "show": "掉寶活動", + "quit": "退出" }, "login": { - "chrome": { - "startup": "正在打開Chrome瀏覽器...", - "login_to_complete": "請再次點擊登錄按鈕來完成登陸.", - "no_token": "無法獲取授權令牌.", - "closed_window": "在登錄完成之前關閉了Chrome瀏覽器." - }, - "error_code": "登錄出錯: {error_code}", - "unexpected_content": "返回的內容類型有誤通常是由於被重定向.您需要設置VPN或者確認登錄頁面才能聯網嗎?", - "incorrect_login_pass": "用戶名或密碼錯誤.", - "incorrect_email_code": "電子郵箱驗證碼錯誤.", - "incorrect_twofa_code": "雙重驗證2FA令牌錯誤.", - "email_code_required": "需要電子郵件驗證碼 查看你的郵件.", - "twofa_code_required": "需要雙重驗證2FA令牌." + "name": "登錄Twitch賬號", + "labels": "狀態:\n用戶ID:", + "logged_in": "已登錄", + "logged_out": "未登錄", + "logging_in": "正在登錄中...", + "required": "請先登錄", + "request": "請先登錄以訪問更多內容.", + "username": "用戶名", + "password": "密碼", + "twofa_code": "郵箱2FA令牌", + "button": "登錄" + }, + "websocket": { + "name": "網絡協議連接狀態", + "websocket": "Websocket #{id}:", + "initializing": "初始化...", + "connected": "已連接", + "disconnected": "斷開連接", + "connecting": "連接中...", + "disconnecting": "斷開連接中...", + "reconnecting": "重新連接中..." + }, + "progress": { + "name": "掉寶活動進度", + "drop": "掉寶獎勵:", + "game": "遊戲:", + "campaign": "掉寶活動名稱:", + "remaining": "剩余 {time}", + "drop_progress": "掉寶進度:", + "campaign_progress": "活動進度:" + }, + "channels": { + "name": "活動頻道", + "switch": "切換", + "load_points": "加載積分", + "online": "ONLINE ✔", + "pending": "OFFLINE ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "直播頻道", + "status": "在線狀態", + "game": "遊戲", + "viewers": "觀眾", + "points": "積分" + } + }, + "inventory": { + "filter": { + "name": "篩選", + "show": "掉寶活動:", + "not_linked": "未關聯賬戶的遊戲掉寶", + "upcoming": "即將上線", + "expired": "已結束", + "excluded": "未添加的掉寶活動", + "finished": "已完成", + "refresh": "刷新" + }, + "status": { + "linked": "已關聯 ✔", + "not_linked": "未關聯賬戶 ❌", + "active": "已上線 ✔", + "upcoming": "即將上線 ⏳", + "expired": "已結束 ❌", + "claimed": "已領取 ✔", + "ready_to_claim": "可以領取 ⏳" + }, + "starts": "開始時間: {time}", + "ends": "結束時間: {time}", + "allowed_channels": "允許的頻道:", + "all_channels": "全部", + "and_more": "還有 {amount} 個...", + "percent_progress": "{minutes} 分鐘的 {percent}", + "minutes_progress": "{minutes} 分鐘" }, - "error": { - "captcha": "您的登錄存在異常,Twitch官方已進行限制,請在12小時后重試.", - "site_down": "Twitch無法連接,{seconds} 秒后重試...", - "no_connection": "無法連接到Twitch,請確保已經開啟VPN並添加了代理,{seconds} 秒后重試..." + "settings": { + "general": { + "name": "功能設置", + "dark_theme": "暗色主題: ", + "autostart": "開機自啟動: ", + "tray": "開機自啟動並最小化: ", + "tray_notifications": "啟用托盤通知: ", + "priority_only": "僅參與優先掉寶遊戲: ", + "prioritze_end": "按掉寶遊戲的結束日期決定優先度: ", + "proxy": "代理:" + }, + "game_name": "遊戲名稱", + "priority": "優先掉寶遊戲", + "exclude": "不參與掉寶遊戲", + "reload": "刷新", + "reload_text": "大多數設置更改後需要重新啟動軟件或刷新才能生效:" }, - "gui": { - "output": "輸出日志", - "status": { - "name": "狀態", - "idle": "已完成獲取", - "exiting": "正在退出...", - "terminated": "應用已終止運行", - "cleanup": "清除頻道中...", - "gathering": "搜索直播頻道...", - "switching": "切換直播頻道中...", - "fetching_inventory": "獲取庫存中...", - "fetching_campaigns": "獲取掉寶活動...", - "adding_campaigns": "將掉寶活動列表添加至庫存... {counter}" - }, - "tabs": { - "main": "主面板", - "inventory": "掉寶庫存", - "settings": "設置", - "help": "幫助" - }, - "tray": { - "notification_title": "開始掉寶活動", - "minimize": "窗口最小化", - "show": "掉寶活動", - "quit": "退出" - }, - "login": { - "name": "登錄Twitch賬號", - "labels": "狀態:\n用戶ID:", - "logged_in": "已登錄", - "logged_out": "未登錄", - "logging_in": "正在登錄中...", - "required": "請先登錄", - "request": "請先登錄以訪問更多內容.", - "username": "用戶名", - "password": "密碼", - "twofa_code": "郵箱2FA令牌", - "button": "登錄" - }, - "websocket": { - "name": "網絡協議連接狀態", - "websocket": "Websocket #{id}:", - "initializing": "初始化...", - "connected": "已連接", - "disconnected": "斷開連接", - "connecting": "連接中...", - "disconnecting": "斷開連接中...", - "reconnecting": "重新連接中..." - }, - "progress": { - "name": "掉寶活動進度", - "drop": "掉寶獎勵:", - "game": "遊戲:", - "remaining": "剩余 {time}", - "campaign": "掉寶活動名稱:", - "drop_progress": "掉寶進度:", - "campaign_progress": "活動進度:" - }, - "channels": { - "name": "活動頻道", - "switch": "切換", - "load_points": "加載積分", - "online": "ONLINE \u2714", - "pending": "OFFLINE \u23f3", - "offline": "OFFLINE \u274c", - "headings": { - "channel": "直播頻道", - "game": "遊戲", - "points": "積分", - "status": "在線狀態", - "viewers": "觀眾" - } - }, - "inventory": { - "filter": { - "name": "篩選", - "show": "掉寶活動:", - "not_linked": "未關聯賬戶的遊戲掉寶", - "expired": "已結束", - "excluded": "未添加的掉寶活動", - "upcoming": "即將上線", - "finished": "已完成", - "refresh": "刷新" - }, - "status": { - "linked": "已關聯 \u2714", - "not_linked": "未關聯賬戶 \u274c", - "active": "已上線 \u2714", - "upcoming": "即將上線 \u23f3", - "expired": "已結束 \u274c", - "claimed": "已領取 \u2714", - "ready_to_claim": "可以領取 \u23f3" - }, - "starts": "開始時間: {time}", - "ends": "結束時間: {time}", - "allowed_channels": "允許的頻道:", - "all_channels": "全部", - "and_more": "還有 {amount} 個...", - "percent_progress": "{minutes} 分鐘的 {percent}", - "minutes_progress": "{minutes} 分鐘" - }, - "settings": { - "general": { - "name": "功能設置", - "autostart": "開機自啟動: ", - "tray": "開機自啟動並最小化: ", - "tray_notifications": "啟用托盤通知: ", - "priority_only": "僅參與優先掉寶遊戲: ", - "proxy": "代理:" - }, - "game_name": "遊戲名稱", - "priority": "優先掉寶遊戲", - "exclude": "不參與掉寶遊戲", - "reload": "刷新", - "reload_text": "大多數設置更改后需要重新啟動軟件或刷新才能生效: " - }, - "help": { - "links": { - "name": "幫助", - "inventory": "查看Twitch庫存", - "campaigns": "查看所有掉寶活動並管理連接賬號" - }, - "how_it_works": "工作原理", - "how_it_works_text": "每隔約 20 秒,程序就會向 Twitch 詢問當前正在觀看的頻道的原始數據流 URL。然后,它會獲取這個數據流的元數據。 - 這足以推進掉寶進度。這完全不需要下載任何實際的視頻流和音頻流。為了使頻道的狀態(在線或離線)保持最新,程序會建立 Websocket 連接,用於接收有關頻道開播和下播的事件,並更新當前的觀眾數量。", - "getting_started": "入門設置", - "getting_started_text": "1. 登錄應用程序。\n2.確保所有感興趣挖掘的遊戲的賬號已連接到您的Twitch賬號。\n3.如果您想挖掘所有掉寶,請不要勾選“僅參與優先掉寶遊戲”,然后按“刷新”。\n4.如果您想優先挖掘特定遊戲,請使用“優先掉寶遊戲”列表設置您想挖掘的遊戲的優先順序。程序將嘗試先挖掘列表頂部的遊戲,然后再挖掘后邊的遊戲。\n5.勾選“僅參與優先掉寶遊戲”時,不會挖掘不在優先列表中的遊戲。勾不勾選取決於你。\n6。使用“不參與掉寶遊戲”列表設置永不挖掘的遊戲。\n7.更改任一列表的內容,或更改“僅參與優先掉寶遊戲”勾選狀態,需要手動按“刷新”才能使更改生效。" - } + "help": { + "links": { + "name": "幫助", + "inventory": "查看Twitch庫存", + "campaigns": "查看所有掉寶活動並管理連接賬號" + }, + "how_it_works": "工作原理", + "how_it_works_text": "每隔約 20 秒,程序就會向 Twitch 詢問當前正在觀看的頻道的原始數據流 URL。然後,它會獲取這個數據流的元數據。 - 這足以推進掉寶進度。這完全不需要下載任何實際的視頻流和音頻流。為了使頻道的狀態(在線或離線)保持最新,程序會建立 Websocket 連接,用於接收有關頻道開播和下播的事件,並更新當前的觀眾數量。", + "getting_started": "入門設置", + "getting_started_text": "1. 登錄應用程序。\n2.確保所有感興趣挖掘的遊戲的賬號已連接到您的Twitch賬號。\n3.如果您想挖掘所有掉寶,請不要勾選“僅參與優先掉寶遊戲”,然後按“刷新”。\n4.如果您想優先挖掘特定遊戲,請使用“優先掉寶遊戲”列表設置您想挖掘的遊戲的優先順序。程序將嘗試先挖掘列表頂部的遊戲,然後再挖掘後邊的遊戲。\n5.勾選“僅參與優先掉寶遊戲”時,不會挖掘不在優先列表中的遊戲。勾不勾選取決於你。\n6。使用“不參與掉寶遊戲”列表設置永不挖掘的遊戲。\n7.更改任一列表的內容,或更改“僅參與優先掉寶遊戲”勾選狀態,需要手動按“刷新”才能使更改生效。" } + } } From 551f387f6345309a9738bd9c48f530f85b83392e Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 17:12:42 +0000 Subject: [PATCH 077/122] =?UTF-8?q?Translate=20=E7=AE=80=E4=BD=93=E4=B8=AD?= =?UTF-8?q?=E6=96=87.json=20via=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\344\275\223\344\270\255\346\226\207.json" | 310 +++++++++--------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" index 755adc33..48de12a9 100644 --- "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" +++ "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" @@ -1,162 +1,164 @@ { - "english_name": "Simplified Chinese", + "english_name": "Simplified Chinese", + "status": { + "terminated": "\n应用程序已终止,请关闭窗口以退出应用程序。", + "watching": "正在观看: {channel}", + "goes_online": "{channel} 该频道已上线, 正在切换...", + "goes_offline": "{channel} 该频道已离线, 正在切换...", + "claimed_drop": "领取的掉宝: {drop}", + "claimed_points": "领取的积分奖励: {points}", + "earned_points": "观看直播获得积分: {points}, 总积分: {balance}", + "no_channel": "没有可观看的频道,等待一个在线直播频道...", + "no_campaign": "没有可用于掉宝的活动,等待一个有效的掉宝活动..." + }, + "login": { + "unexpected_content": "返回的内容类型有误通常是由于被重定向.您需要设置VPN或者确认登录页面才能联网吗?", + "chrome": { + "startup": "正在打开Chrome浏览器...", + "login_to_complete": "请再次点击登录按钮来完成登陆.", + "no_token": "无法获取授权令牌.", + "closed_window": "在登录完成之前关闭了Chrome浏览器." + }, + "error_code": "登录出错: {error_code}", + "incorrect_login_pass": "用户名或密码错误.", + "incorrect_email_code": "电子邮箱验证码错误.", + "incorrect_twofa_code": "双重验证2FA令牌错误.", + "email_code_required": "需要电子邮件验证码 查看你的邮件.", + "twofa_code_required": "需要双重验证2FA令牌." + }, + "error": { + "captcha": "您的登录存在异常,Twitch官方已进行限制,请在12小时后重试.", + "site_down": "Twitch无法连接,{seconds} 秒后重试...", + "no_connection": "无法连接到Twitch,请确保已经开启VPN并添加了代理,{seconds} 秒后重试..." + }, + "gui": { + "output": "输出日志", "status": { - "terminated": "\n应用程序已终止,请关闭窗口以退出应用程序。", - "watching": "正在观看: {channel}", - "goes_online": "{channel} 该频道已上线, 正在切换...", - "goes_offline": "{channel} 该频道已离线, 正在切换...", - "claimed_drop": "领取的掉宝: {drop}", - "claimed_points": "领取的积分奖励: {points}", - "earned_points": "观看直播获得积分: {points}, 总积分: {balance}", - "no_channel": "没有可观看的频道,等待一个在线直播频道...", - "no_campaign": "没有可用于掉宝的活动,等待一个有效的掉宝活动..." + "name": "状态", + "idle": "已完成获取", + "exiting": "正在退出...", + "terminated": "应用已终止运行", + "cleanup": "清除频道中...", + "gathering": "搜索直播频道...", + "switching": "切换直播频道中...", + "fetching_inventory": "获取库存中...", + "fetching_campaigns": "获取掉宝活动...", + "adding_campaigns": "将掉宝活动列表添加至库存... {counter}" + }, + "tabs": { + "main": "主面板", + "inventory": "掉宝库存", + "settings": "设置", + "help": "帮助" + }, + "tray": { + "notification_title": "开始掉宝活动", + "minimize": "窗口最小化", + "show": "掉宝活动", + "quit": "退出" }, "login": { - "chrome": { - "startup": "正在打开Chrome浏览器...", - "login_to_complete": "请再次点击登录按钮来完成登陆.", - "no_token": "无法获取授权令牌.", - "closed_window": "在登录完成之前关闭了Chrome浏览器." - }, - "error_code": "登录出错: {error_code}", - "unexpected_content": "返回的内容类型有误通常是由于被重定向.您需要设置VPN或者确认登录页面才能联网吗?", - "incorrect_login_pass": "用户名或密码错误.", - "incorrect_email_code": "电子邮箱验证码错误.", - "incorrect_twofa_code": "双重验证2FA令牌错误.", - "email_code_required": "需要电子邮件验证码 查看你的邮件.", - "twofa_code_required": "需要双重验证2FA令牌." + "name": "登录Twitch账号", + "labels": "状态:\n用户ID:", + "logged_in": "已登录", + "logged_out": "未登录", + "logging_in": "正在登录中...", + "required": "请先登录", + "request": "请先登录以访问更多内容.", + "username": "用户名", + "password": "密码", + "twofa_code": "邮箱2FA令牌", + "button": "登录" + }, + "websocket": { + "name": "网络协议连接状态", + "websocket": "Websocket #{id}:", + "initializing": "初始化...", + "connected": "已连接", + "disconnected": "断开连接", + "connecting": "连接中...", + "disconnecting": "断开连接中...", + "reconnecting": "重新连接中..." + }, + "progress": { + "name": "掉宝活动进度", + "drop": "掉宝奖励:", + "game": "游戏:", + "campaign": "掉宝活动名称:", + "remaining": "剩余 {time}", + "drop_progress": "掉宝进度:", + "campaign_progress": "活动进度:" + }, + "channels": { + "name": "活动频道", + "switch": "切换", + "load_points": "加载积分", + "online": "ONLINE ✔", + "pending": "OFFLINE ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "直播频道", + "status": "在线状态", + "game": "游戏", + "viewers": "观众", + "points": "积分" + } + }, + "inventory": { + "filter": { + "name": "筛选", + "show": "掉宝活动:", + "not_linked": "未关联账户的游戏掉宝", + "upcoming": "即将上线", + "expired": "已结束", + "excluded": "未添加的掉宝活动", + "finished": "已完成", + "refresh": "刷新" + }, + "status": { + "linked": "已关联 ✔", + "not_linked": "未关联账户 ❌", + "active": "已上线 ✔", + "upcoming": "即将上线 ⏳", + "expired": "已结束 ❌", + "claimed": "已领取 ✔", + "ready_to_claim": "可以领取 ⏳" + }, + "starts": "开始时间: {time}", + "ends": "结束时间: {time}", + "allowed_channels": "允许的频道:", + "all_channels": "全部", + "and_more": "还有 {amount} 个...", + "percent_progress": "{minutes} 分钟的 {percent}", + "minutes_progress": "{minutes} 分钟" }, - "error": { - "captcha": "您的登录存在异常,Twitch官方已进行限制,请在12小时后重试.", - "site_down": "Twitch无法连接,{seconds} 秒后重试...", - "no_connection": "无法连接到Twitch,请确保已经开启VPN并添加了代理,{seconds} 秒后重试..." + "settings": { + "general": { + "name": "功能设置", + "dark_theme": "暗色主题: ", + "autostart": "开机自启动: ", + "tray": "开机自启动并最小化: ", + "tray_notifications": "启用托盘通知: ", + "priority_only": "仅参与优先掉宝游戏: ", + "prioritze_end": "按掉宝游戏的结束日期决定优先度: ", + "proxy": "代理:" + }, + "game_name": "游戏名称", + "priority": "优先掉宝游戏", + "exclude": "不参与掉宝游戏", + "reload": "刷新", + "reload_text": "大多数设置更改后需要重新启动软件或刷新才能生效: " }, - "gui": { - "output": "输出日志", - "status": { - "name": "状态", - "idle": "已完成获取", - "exiting": "正在退出...", - "terminated": "应用已终止运行", - "cleanup": "清除频道中...", - "gathering": "搜索直播频道...", - "switching": "切换直播频道中...", - "fetching_inventory": "获取库存中...", - "fetching_campaigns": "获取掉宝活动...", - "adding_campaigns": "将掉宝活动列表添加至库存... {counter}" - }, - "tabs": { - "main": "主面板", - "inventory": "掉宝库存", - "settings": "设置", - "help": "帮助" - }, - "tray": { - "notification_title": "开始掉宝活动", - "minimize": "窗口最小化", - "show": "掉宝活动", - "quit": "退出" - }, - "login": { - "name": "登录Twitch账号", - "labels": "状态:\n用户ID:", - "logged_in": "已登录", - "logged_out": "未登录", - "logging_in": "正在登录中...", - "required": "请先登录", - "request": "请先登录以访问更多内容.", - "username": "用户名", - "password": "密码", - "twofa_code": "邮箱2FA令牌", - "button": "登录" - }, - "websocket": { - "name": "网络协议连接状态", - "websocket": "Websocket #{id}:", - "initializing": "初始化...", - "connected": "已连接", - "disconnected": "断开连接", - "connecting": "连接中...", - "disconnecting": "断开连接中...", - "reconnecting": "重新连接中..." - }, - "progress": { - "name": "掉宝活动进度", - "drop": "掉宝奖励:", - "game": "游戏:", - "remaining": "剩余 {time}", - "campaign": "掉宝活动名称:", - "drop_progress": "掉宝进度:", - "campaign_progress": "活动进度:" - }, - "channels": { - "name": "活动频道", - "switch": "切换", - "load_points": "加载积分", - "online": "ONLINE \u2714", - "pending": "OFFLINE \u23f3", - "offline": "OFFLINE \u274c", - "headings": { - "channel": "直播频道", - "game": "游戏", - "points": "积分", - "status": "在线状态", - "viewers": "观众" - } - }, - "inventory": { - "filter": { - "name": "筛选", - "show": "掉宝活动:", - "not_linked": "未关联账户的游戏掉宝", - "expired": "已结束", - "excluded": "未添加的掉宝活动", - "upcoming": "即将上线", - "finished": "已完成", - "refresh": "刷新" - }, - "status": { - "linked": "已关联 \u2714", - "not_linked": "未关联账户 \u274c", - "active": "已上线 \u2714", - "upcoming": "即将上线 \u23f3", - "expired": "已结束 \u274c", - "claimed": "已领取 \u2714", - "ready_to_claim": "可以领取 \u23f3" - }, - "starts": "开始时间: {time}", - "ends": "结束时间: {time}", - "allowed_channels": "允许的频道:", - "all_channels": "全部", - "and_more": "还有 {amount} 个...", - "percent_progress": "{minutes} 分钟的 {percent}", - "minutes_progress": "{minutes} 分钟" - }, - "settings": { - "general": { - "name": "功能设置", - "autostart": "开机自启动: ", - "tray": "开机自启动并最小化: ", - "tray_notifications": "启用托盘通知: ", - "priority_only": "仅参与优先掉宝游戏: ", - "proxy": "代理:" - }, - "game_name": "游戏名称", - "priority": "优先掉宝游戏", - "exclude": "不参与掉宝游戏", - "reload": "刷新", - "reload_text": "大多数设置更改后需要重新启动软件或刷新才能生效: " - }, - "help": { - "links": { - "name": "帮助", - "inventory": "查看Twitch库存", - "campaigns": "查看所有掉宝活动并管理连接账号" - }, - "how_it_works": "工作原理", - "how_it_works_text": "每隔约 20 秒,程序就会向 Twitch 询问当前正在观看的频道的原始数据流 URL。然后,它会获取这个数据流的元数据。 - 这足以推进掉宝进度。这完全不需要下载任何实际的视频流和音频流。为了使频道的状态(在线或离线)保持最新,程序会建立 Websocket 连接,用于接收有关频道开播和下播的事件,并更新当前的观众数量。", - "getting_started": "入门设置", - "getting_started_text": "1. 登录应用程序。\n2.确保所有感兴趣挖掘的游戏的账号已连接到您的Twitch账号。\n3.如果您想挖掘所有掉宝,请不要勾选“仅参与优先掉宝游戏”,然后按“刷新”。\n4.如果您想优先挖掘特定游戏,请使用“优先掉宝游戏”列表设置您想挖掘的游戏的优先顺序。程序将尝试先挖掘列表顶部的游戏,然后再挖掘后边的游戏。\n5.勾选“仅参与优先掉宝游戏”时,不会挖掘不在优先列表中的游戏。勾不勾选取决于你。\n6。使用“不参与掉宝游戏”列表设置永不挖掘的游戏。\n7.更改任一列表的内容,或更改“仅参与优先掉宝游戏”勾选状态,需要手动按“刷新”才能使更改生效。" - } + "help": { + "links": { + "name": "帮助", + "inventory": "查看Twitch库存", + "campaigns": "查看所有掉宝活动并管理连接账号" + }, + "how_it_works": "工作原理", + "how_it_works_text": "每隔约 20 秒,程序就会向 Twitch 询问当前正在观看的频道的原始数据流 URL。然后,它会获取这个数据流的元数据。 - 这足以推进掉宝进度。这完全不需要下载任何实际的视频流和音频流。为了使频道的状态(在线或离线)保持最新,程序会建立 Websocket 连接,用于接收有关频道开播和下播的事件,并更新当前的观众数量。", + "getting_started": "入门设置", + "getting_started_text": "1. 登录应用程序。\n2.确保所有感兴趣挖掘的游戏的账号已连接到您的Twitch账号。\n3.如果您想挖掘所有掉宝,请不要勾选“仅参与优先掉宝游戏”,然后按“刷新”。\n4.如果您想优先挖掘特定游戏,请使用“优先掉宝游戏”列表设置您想挖掘的游戏的优先顺序。程序将尝试先挖掘列表顶部的游戏,然后再挖掘后边的游戏。\n5.勾选“仅参与优先掉宝游戏”时,不会挖掘不在优先列表中的游戏。勾不勾选取决于你。\n6。使用“不参与掉宝游戏”列表设置永不挖掘的游戏。\n7.更改任一列表的内容,或更改“仅参与优先掉宝游戏”勾选状态,需要手动按“刷新”才能使更改生效。" } + } } From 68063bbb2c7798a671c7c91ae0aa3eebf1871223 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 19:16:14 +0200 Subject: [PATCH 078/122] updated patch notes --- patch_notes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch_notes.txt b/patch_notes.txt index a352926a..fb20a790 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -2,7 +2,7 @@ ### 25.5.2024 - Added ability to sort by Campaign end date (made by @jaredkotoff) -- Updated ... translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date +- Updated **Simplified and Traditional Chinese** translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date From 342df8d2577278c2045dccf1a6c50f07d83eaf1d Mon Sep 17 00:00:00 2001 From: Dmytro Zozulia Date: Sat, 25 May 2024 21:27:53 +0000 Subject: [PATCH 079/122] =?UTF-8?q?Translate=20=D0=A3=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D1=97=D0=BD=D1=81=D1=8C=D0=BA=D0=B0.json=20via=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\275\321\201\321\214\320\272\320\260.json" | 310 +++++++++--------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" index 40586677..2aabea75 100644 --- "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" +++ "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" @@ -1,162 +1,164 @@ { - "english_name": "Ukrainian", + "english_name": "Ukrainian", + "status": { + "terminated": "\nЗастосунок зупинено.\nЗакрийте вікно для виходу з програми.", + "watching": "Переглядає: {channel}", + "goes_online": "{channel} онлайн, зміна...", + "goes_offline": "{channel} офлайн, зміна...", + "claimed_drop": "Отримано дроп: {drop}", + "claimed_points": "Отримано {points} бонусних балів", + "earned_points": "Зароблено {points} балів за перегляд, усього: {balance}", + "no_channel": "Немає активних каналів для перегляду. Очікування...", + "no_campaign": "Немає активних каналів для видобутку дропів. Очікування..." + }, + "login": { + "unexpected_content": "Повернуто неочікуваний тип вмісту, зазвичай через перенаправлення. Чи не потрібно вам увійти задля доступу в інтернет?", + "chrome": { + "startup": "Відкриття браузера...", + "login_to_complete": "Завершіть процедуру входу власноруч, натиснувши кнопку \"Увійти ще раз\".", + "no_token": "Жетон авторизації не знайдено.", + "closed_window": "Вікно браузера було закрито до завершення процедури входу." + }, + "error_code": "Код помилки входу: {error_code}", + "incorrect_login_pass": "Неправильне ім'я користувача або пароль.", + "incorrect_email_code": "Неправильний код електронної пошти.", + "incorrect_twofa_code": "Неправильний код двофакторної аутентифікації.", + "email_code_required": "Потрібен код електронної пошти.", + "twofa_code_required": "Потрібен жетон двофакторної аутентифікації." + }, + "error": { + "captcha": "Ваша спроба входу була відхилена через капчу.\nБудь ласка, спробуйте ще раз через 12 або більше годин.", + "site_down": "Twitch не працює, спроба через {seconds} секунд...", + "no_connection": "Не вдається з'єднатися з Twitch, повторна спроба через {seconds} секунд..." + }, + "gui": { + "output": "Вивід", "status": { - "terminated": "\nЗастосунок зупинено.\nЗакрийте вікно для виходу з програми.", - "watching": "Переглядає: {channel}", - "goes_online": "{channel} онлайн, зміна...", - "goes_offline": "{channel} офлайн, зміна...", - "claimed_drop": "Отримано дроп: {drop}", - "claimed_points": "Отримано {points} бонусних балів", - "earned_points": "Зароблено {points} балів за перегляд, усього: {balance}", - "no_channel": "Немає активних каналів для перегляду. Очікування...", - "no_campaign": "Немає активних каналів для видобутку дропів. Очікування..." + "name": "Стан", + "idle": "Бездіяльність", + "exiting": "Вихід...", + "terminated": "Зупинено", + "cleanup": "Очищення каналів...", + "gathering": "Збір каналів...", + "switching": "Перемикання на канал...", + "fetching_inventory": "Отримання інвентарю...", + "fetching_campaigns": "Отримання кампаній...", + "adding_campaigns": "Додавання кампаній до інвентарю... {counter}" + }, + "tabs": { + "main": "Основне", + "inventory": "Інвентар", + "settings": "Налаштування", + "help": "Інформація" + }, + "tray": { + "notification_title": "Дроп отримано", + "minimize": "Згорнути в трей", + "show": "Показати", + "quit": "Вийти" }, "login": { - "unexpected_content": "Повернуто неочікуваний тип вмісту, зазвичай через перенаправлення. Чи не потрібно вам увійти задля доступу в інтернет?", - "chrome": { - "startup": "Відкриття браузера...", - "login_to_complete": "Завершіть процедуру входу власноруч, натиснувши кнопку \"Увійти ще раз\".", - "no_token": "Жетон авторизації не знайдено.", - "closed_window": "Вікно браузера було закрито до завершення процедури входу." - }, - "error_code": "Код помилки входу: {error_code}", - "incorrect_login_pass": "Неправильне ім'я користувача або пароль.", - "incorrect_email_code": "Неправильний код електронної пошти.", - "incorrect_twofa_code": "Неправильний код двофакторної аутентифікації.", - "email_code_required": "Потрібен код електронної пошти.", - "twofa_code_required": "Потрібен жетон двофакторної аутентифікації." + "name": "Форма для входу", + "labels": "Стан:\nІдентифікатор користувача:", + "logged_in": "Увійдено", + "logged_out": "Вийдено", + "logging_in": "Вхід...", + "required": "Потрібен вхід", + "request": "Будь ласка, увійдіть, щоб продовжити.", + "username": "Ім'я користувача", + "password": "Пароль", + "twofa_code": "Код двофакторної автентифікації (необов'язково)", + "button": "Вхід" + }, + "websocket": { + "name": "Стан веб-сокета", + "websocket": "Веб-сокет #{id}:", + "initializing": "Ініціалізація...", + "connected": "Підключено", + "disconnected": "Відключено", + "connecting": "З'єднання...", + "disconnecting": "Від'єднання...", + "reconnecting": "Перепідключення..." + }, + "progress": { + "name": "Поступ кампанії", + "drop": "Дроп:", + "game": "Гра:", + "campaign": "Кампанія:", + "remaining": "{time} залишилося", + "drop_progress": "Поступ:", + "campaign_progress": "Поступ:" + }, + "channels": { + "name": "Канали", + "switch": "Перемкнути", + "load_points": "Завантажити бали", + "online": "ОНЛАЙН ✔", + "pending": "ОФЛАЙН ⏳", + "offline": "ОФЛАЙН ❌", + "headings": { + "channel": "Канал", + "status": "Стан", + "game": "Гра", + "viewers": "Глядачі", + "points": "Бали" + } + }, + "inventory": { + "filter": { + "name": "Фільтри", + "show": "Показати лише:", + "not_linked": "Не пов'язано", + "upcoming": "Наближаються", + "expired": "Прострочені", + "excluded": "Виключені", + "finished": "Завершені", + "refresh": "Оновити" + }, + "status": { + "linked": "Пов'язано ✔", + "not_linked": "Не пов'язано ❌", + "active": "Діюча ✔", + "upcoming": "Наближається ⏳", + "expired": "Прострочено ❌", + "claimed": "Отримано ✔", + "ready_to_claim": "Готове до отримання ⏳" + }, + "starts": "Починається {time}", + "ends": "Завершується {time}", + "allowed_channels": "Дозволені канали:", + "all_channels": "Усі", + "and_more": "і {amount} більше...", + "percent_progress": "{percent} від {minutes} хвилин", + "minutes_progress": "{minutes} хвилин" }, - "error": { - "captcha": "Ваша спроба входу була відхилена через капчу.\nБудь ласка, спробуйте ще раз через 12 або більше годин.", - "site_down": "Twitch не працює, спроба через {seconds} секунд...", - "no_connection": "Не вдається з'єднатися з Twitch, повторна спроба через {seconds} секунд..." + "settings": { + "general": { + "name": "Основні", + "dark_theme": "Темна тема:", + "autostart": "Автозапуск: ", + "tray": "Автозапуск у треї: ", + "tray_notifications": "Сповіщення: ", + "priority_only": "Лише пріоритетні: ", + "prioritze_end": "Пріоритизувати ті, що закінчуються раніше:", + "proxy": "Проксі (потребує перезапуску):" + }, + "game_name": "Назва гри", + "priority": "Пріоритет", + "exclude": "Виключити", + "reload": "Перезавантажити", + "reload_text": "Більшість змін потребують перезавантаження, щоб набути дії: " }, - "gui": { - "output": "Вивід", - "status": { - "name": "Стан", - "idle": "Бездіяльність", - "exiting": "Вихід...", - "terminated": "Зупинено", - "cleanup": "Очищення каналів...", - "gathering": "Збір каналів...", - "switching": "Перемикання на канал...", - "fetching_inventory": "Отримання інвентарю...", - "fetching_campaigns": "Отримання кампаній...", - "adding_campaigns": "Додавання кампаній до інвентарю... {counter}" - }, - "tabs": { - "main": "Основне", - "inventory": "Інвентар", - "settings": "Налаштування", - "help": "Інформація" - }, - "tray": { - "notification_title": "Дроп отримано", - "minimize": "Згорнути в трей", - "show": "Показати", - "quit": "Вийти" - }, - "login": { - "name": "Форма для входу", - "labels": "Стан:\nІдентифікатор користувача:", - "logged_in": "Увійдено", - "logged_out": "Вийдено", - "logging_in": "Вхід...", - "required": "Потрібен вхід", - "request": "Будь ласка, увійдіть, щоб продовжити.", - "username": "Ім'я користувача", - "password": "Пароль", - "twofa_code": "Код двофакторної автентифікації (необов'язково)", - "button": "Вхід" - }, - "websocket": { - "name": "Стан веб-сокета", - "websocket": "Веб-сокет #{id}:", - "initializing": "Ініціалізація...", - "connected": "Підключено", - "disconnected": "Відключено", - "connecting": "З'єднання...", - "disconnecting": "Від'єднання...", - "reconnecting": "Перепідключення..." - }, - "progress": { - "name": "Поступ кампанії", - "drop": "Дроп:", - "game": "Гра:", - "campaign": "Кампанія:", - "remaining": "{time} залишилося", - "drop_progress": "Поступ:", - "campaign_progress": "Поступ:" - }, - "channels": { - "name": "Канали", - "switch": "Перемкнути", - "load_points": "Завантажити бали", - "online": "ОНЛАЙН \u2714", - "pending": "ОФЛАЙН \u23f3", - "offline": "ОФЛАЙН \u274c", - "headings": { - "channel": "Канал", - "status": "Стан", - "game": "Гра", - "viewers": "Глядачі", - "points": "Бали" - } - }, - "inventory": { - "filter": { - "name": "Фільтри", - "show": "Показати лише:", - "not_linked": "Не пов'язано", - "upcoming": "Наближаються", - "expired": "Прострочені", - "excluded": "Виключені", - "finished": "Завершені", - "refresh": "Оновити" - }, - "status": { - "linked": "Пов'язано \u2714", - "not_linked": "Не пов'язано \u274c", - "active": "Діюча \u2714", - "upcoming": "Наближається \u23f3", - "expired": "Прострочено \u274c", - "claimed": "Отримано \u2714", - "ready_to_claim": "Готове до отримання \u23f3" - }, - "starts": "Починається {time}", - "ends": "Завершується {time}", - "allowed_channels": "Дозволені канали:", - "all_channels": "Усі", - "and_more": "і {amount} більше...", - "percent_progress": "{percent} від {minutes} хвилин", - "minutes_progress": "{minutes} хвилин" - }, - "settings": { - "general": { - "name": "Основні", - "autostart": "Автозапуск: ", - "tray": "Автозапуск у треї: ", - "tray_notifications": "Сповіщення: ", - "priority_only": "Лише пріоритетні: ", - "proxy": "Проксі (потребує перезапуску):" - }, - "game_name": "Назва гри", - "priority": "Пріоритет", - "exclude": "Виключити", - "reload": "Перезавантажити", - "reload_text": "Більшість змін потребують перезавантаження, щоб набути дії: " - }, - "help": { - "links": { - "name": "Корисні посилання", - "inventory": "Переглянути інвентар Twitch", - "campaigns": "Переглянути усі кампанії та керувати пов'язаними обліковими записами" - }, - "how_it_works": "Як це працює?", - "how_it_works_text": "Кожні ~20 секунд програма запитує у Twitch URL-адресу необроблених даних потоку каналу, який зараз переглядається. Потім він отримує метадані цього потоку даних. Цього достатньо, щоб здобувати дропи. Зауважте, що це повністю обходить необхідність завантажувати будь-які потокові відео та звук. Щоб підтримувати актуальний стан каналів (ОНЛАЙН або ОФЛАЙН), встановлюється з'єднання з веб-сокетом, який отримує події про збільшення або зменшення кількості трансляцій, або оновлення поточної кількості глядачів.", - "getting_started": "Інструкція", - "getting_started_text": "1. Увійдіть в додаток.\n2. Переконайтеся, що ваш обліковий запис Twitch пов'язаний з усіма обліковими записами ігор, з яких ви хочете здобувати дропи.\n3. Якщо ви зацікавлені у здобуванні всього, зніміть прапорець \"Тільки пріоритет\" і натисніть \"Перезавантажити\".\n4. Якщо ви хочете здобувати з певних ігор, скористайтеся списком \"Пріоритет\", щоб створити впорядкований список ігор за вашим вибором. Ігри будуть здобуватися в порядку розташування в списку.\n5. Не знімайте прапорець \"Тільки пріоритет\", щоб уникнути здобування з ігор, які не входять до пріоритетного списку. Або ні - вирішувати вам.\n6. Використовуйте список \"Виключено\", щоб вказати застосунку, з яких ігор ніколи не слід здобувати.\n7. Зміна вмісту будь-якого зі списків або зміна стану опції \"Тільки пріоритет\" вимагає натискання кнопки \"Перезавантажити\" для набуття змінами чинності.\n\nПереклад виконав Дмитро Зозуля" - } + "help": { + "links": { + "name": "Корисні посилання", + "inventory": "Переглянути інвентар Twitch", + "campaigns": "Переглянути усі кампанії та керувати пов'язаними обліковими записами" + }, + "how_it_works": "Як це працює?", + "how_it_works_text": "Приблизно кожні 20 секунд програма запитує у Twitch URL-адресу необробленого потоку даних каналу, який ви зараз переглядаєте. Потім він отримує метадані цього потоку даних - цього достатньо, щоб здобувати дропи. Зауважте, що це повністю обходить необхідність завантажувати будь-які потокові відео та звук. Щоб підтримувати актуальний стан каналів (ОНЛАЙН або ОФЛАЙН), встановлюється з'єднання з веб-сокетом, який отримує події про збільшення або зменшення кількості трансляцій, або оновлення поточної кількості глядачів.", + "getting_started": "Інструкція", + "getting_started_text": "1. Увійдіть у застосунок.\n2. Переконайтеся, що ваш обліковий запис Twitch пов'язаний з усіма обліковими записами ігор, з яких ви хочете здобувати дропи.\n3. Якщо ви зацікавлені у здобуванні всього, зніміть прапорець \"Тільки пріоритет\" і натисніть \"Перезавантажити\".\n4. Якщо ви хочете здобувати з певних ігор, скористайтеся списком \"Пріоритет\", щоб створити впорядкований список ігор за вашим вибором. Ігри будуть здобуватися в порядку розташування в списку.\n5. Не знімайте прапорець \"Тільки пріоритет\", щоб уникнути здобування з ігор, які не входять до пріоритетного списку. Або ні - вирішувати вам.\n6. Використовуйте список \"Виключено\", щоб вказати застосунку, з яких ігор ніколи не слід здобувати.\n7. Зміна вмісту будь-якого зі списків або зміна стану опції \"Тільки пріоритет\" вимагає натискання кнопки \"Перезавантажити\" для набуття змінами чинності.\n\nПереклад виконав Дмитро Зозуля" } + } } From 7f6ed2bc2b3959ab0e5e9fdd7c859f34055b623b Mon Sep 17 00:00:00 2001 From: DogancanYr Date: Sat, 25 May 2024 21:25:05 +0000 Subject: [PATCH 080/122] =?UTF-8?q?Translate=20T=C3=BCrk=C3=A7e.json=20via?= =?UTF-8?q?=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "lang/T\303\274rk\303\247e.json" | 309 ++++++++++++++++--------------- 1 file changed, 156 insertions(+), 153 deletions(-) diff --git "a/lang/T\303\274rk\303\247e.json" "b/lang/T\303\274rk\303\247e.json" index f4c271cb..beeb21c9 100644 --- "a/lang/T\303\274rk\303\247e.json" +++ "b/lang/T\303\274rk\303\247e.json" @@ -1,161 +1,164 @@ { - "english_name": "Turkish", + "english_name": "Turkish", + "status": { + "terminated": "\nUygulama durduruldu.\nUygulamadan çıkmak için pencereyi kapatın", + "watching": "{channel} izleniyor", + "goes_online": "{channel} ÇEVRİM İÇİ oldu, geçiş yapılıyor...", + "goes_offline": "{channel} ÇEVRİM DIŞI oldu, geçiş yapılıyor...", + "claimed_drop": "Alınan ödül: {drop}", + "claimed_points": "Kazanılan bonus kanal puanları: {points}", + "earned_points": "İzleme karşılığında kazanılan kanal puanları: {points} | Toplam: {balance}", + "no_channel": "İzlenebilecek kanal yok. ÇEVRİM İÇİ kanal bekleniyor...", + "no_campaign": "Ödül madenciliği için aktif kampanya yok. Aktif bir kampanya bekleniyor..." + }, + "login": { + "unexpected_content": "Beklenmeyen içerik türü döndürüldü, genellikle yeniden yönlendirilme nedeniyle. İnternet erişimi için giriş yapmanız gerekiyor mu?", + "chrome": { + "startup": "Tarayıcı Açılıyor...", + "login_to_complete": "Oturum aç düğmesine tekrar basarak oturum açma işlemini kendiniz tamamlayın.", + "no_token": "Yetkilendirme anahtarı bulunamadı.", + "closed_window": "Oturum açma işlemi tamamlanamadan tarayıcı penceresi kapatıldı." + }, + "error_code": "Oturum açma hatası kodu: {error_code}", + "incorrect_login_pass": "Yanlış kullanıcı adı veya şifre.", + "incorrect_email_code": "Yanlış e-posta kodu.", + "incorrect_twofa_code": "Yanlış 2FA kodu.", + "email_code_required": "E-posta kodu gerekli. Lütfen e-postanızı kontrol edin.", + "twofa_code_required": "2FA kodu gerekli." + }, + "error": { + "captcha": "Giriş denemeniz CAPTCHA tarafından reddedildi.\nLütfen en az 12 saat sonra tekrar deneyin.", + "site_down": "Twitch kapalı, {seconds} saniye içinde tekrar denenecek...", + "no_connection": "Twitch'e bağlanılamıyor. {seconds} saniye içinde tekrar deneniyor..." + }, + "gui": { + "output": "Çıktı", "status": { - "terminated": "\nUygulama durduruldu.\nUygulamadan çıkmak için pencereyi kapatın", - "watching": "{channel} izleniyor", - "goes_online": "{channel} ÇEVRİMİÇİ oldu, geçiş yapın...", - "goes_offline": "{channel} ÇEVRİMDIŞI duruma geçti, geçiş yapın...", - "claimed_drop": "Alınan drop: {drop}", - "claimed_points": "Kazanılan kanal puanları: {points}", - "earned_points": "İzleme karşılığında kazanılan kanal puanları: {points} | Toplam: {balance}", - "no_channel": "Çevrimiçi katılımcı kanal yok. Kanallar bekleniyor...", - "no_campaign": "Etkin kampanya yok. Yeni kampanya bekleniyor..." + "name": "Durum", + "idle": "Boşta", + "exiting": "Çıkılıyor...", + "terminated": "Sonlandırıldı", + "cleanup": " Kanallar temizleniyor...", + "gathering": " Kanallar toplanıyor...", + "switching": "Kanal değiştiriliyor...", + "fetching_inventory": "Envanter getiriliyor...", + "fetching_campaigns": "Kampanyalar getiriliyor...", + "adding_campaigns": "Kampanyalar envantere ekleniyor... {counter}" + }, + "tabs": { + "main": "Ana Sayfa", + "inventory": "Envanter", + "settings": "Ayarlar", + "help": "Yardım" + }, + "tray": { + "notification_title": "Ödül alındı", + "minimize": "Sistem tepsisine küçült", + "show": "Göster", + "quit": "Çık" }, "login": { - "chrome": { - "startup": "Chrome'u Başlat...", - "login_to_complete": "Oturum açma işlemini manuel olarak tamamlamak için tekrar Oturum Aç'a basın.", - "no_token": "Yetkilendirme belirteci bulunamadı.", - "closed_window": "Oturum açma işlemi tamamlanamadan Chrome penceresi kapandı." - }, - "error_code": "Giriş Hata Kodu: {error_code}", - "unexpected_content": "Genellikle bir yönlendirme nedeniyle beklenmeyen içerik türü döndürüldü.\nİnternete erişmek için oturum açmanız gerekiyor mu?", - "incorrect_login_pass": "Yanlış kullanıcı adı veya şifre.", - "incorrect_email_code": "Yanlış e-posta kodu.", - "incorrect_twofa_code": "Yanlış 2FA kodu.", - "email_code_required": "E-posta kodu gerekli. Lütfen e-postayı kontrol edin.", - "twofa_code_required": "2FA belirteci gerekli." + "name": "Giriş Yap", + "labels": "Durum:\nKullanıcı ID:", + "logged_in": "Giriş Yapıldı", + "logged_out": "Çıkış Yapıldı", + "logging_in": "Giriş yapılıyor...", + "required": "Oturum açmak gerekli", + "request": "Devam etmek için lütfen giriş yapınız.", + "username": "Kullanıcı Adı", + "password": "Parola", + "twofa_code": "2FA kodu (isteğe bağlı)", + "button": "Giriş yap" + }, + "websocket": { + "name": "WebSocket Durumu", + "websocket": "WebSocket #{id}:", + "initializing": "Başlatılıyor...", + "connected": "Bağlandı", + "disconnected": "Bağlantı koptu", + "connecting": "Bağlanıyor...", + "disconnecting": "Bağlantı kesiliyor...", + "reconnecting": "Yeniden bağlanılıyor..." + }, + "progress": { + "name": "Ödül İlerlemesi", + "drop": "Ödül:", + "game": "Oyun:", + "campaign": "Kampanya:", + "remaining": "{time} geriye kalan", + "drop_progress": "İlerleme:", + "campaign_progress": "İlerleme:" + }, + "channels": { + "name": "Kanallar", + "switch": "Değiştir", + "load_points": "Puanları Yükle", + "online": "ÇEVRİM İÇİ ✔", + "pending": "ÇEVRİM DIŞI⏳", + "offline": "ÇEVRİM DIŞI ❌", + "headings": { + "channel": "Kanal", + "status": "Durum", + "game": "Oyun", + "viewers": "İzleyiciler", + "points": "Puan" + } + }, + "inventory": { + "filter": { + "name": "Filtre", + "show": "Göster:", + "not_linked": "Bağlantılı değil", + "upcoming": "Gelecekler", + "expired": "Süresi dolanlar", + "excluded": "Hariç tutulanlar", + "finished": "Bitenler", + "refresh": "Yenile" + }, + "status": { + "linked": "Bağlantılı ✔", + "not_linked": "Bağlantılı değil ❌", + "active": "Aktif ✔", + "upcoming": "Gelecek ⏳", + "expired": "Süresi dolmuş ❌", + "claimed": "Alındı ​​✔", + "ready_to_claim": "Almaya hazır ⏳" + }, + "starts": "Başladı: {time}", + "ends": "Bitti: {time}", + "allowed_channels": "Katılan Kanallar:", + "all_channels": "Tüm Kanallar", + "and_more": "ve {amount} diğer...", + "percent_progress": "{percent} {minutes} dakika", + "minutes_progress": "{minutes} dakika" }, - "error": { - "captcha": "Giriş girişimi CAPTCHA tarafından reddedildi.\nLütfen en az 12 saat içinde tekrar deneyin.", - "site_down": "cadı ulaşılmaz. {seconds} saniye içinde tekrar deneniyor...", - "no_connection": "Twitch'e bağlanılamıyor. {seconds} saniye içinde tekrar deneniyor..." + "settings": { + "general": { + "name": "Genel", + "dark_theme": "Karanlık tema:", + "autostart": "Otomatik başlat: ", + "tray": "Sistem tepsisine otomatik başlat: ", + "tray_notifications": "Bildirim gönder: ", + "priority_only": "Öncelik sıralamasına göre: ", + "prioritze_end": "En kısa sürede biteceklere öncelik ver:", + "proxy": "Proxy (Yeniden başlatma gerektirir):" + }, + "game_name": "Oyun ismi", + "priority": "Öncelik", + "exclude": "Hariç tut", + "reload": "Yeniden Yükle", + "reload_text": "Değişikliklerin uygulanabilmesi için yeniden yükle tuşuna basılması lazım:" }, - "gui": { - "output": "Protokoll", - "status": { - "name": "Durum", - "idle": "Boşta", - "exiting": "Çıkış...", - "terminated": "Sonlandırıldı", - "cleanup": "Kanalları temizle..", - "gathering": "Kanalları toplama...", - "switching": "Kanal değiştiriliyor...", - "fetching_inventory": "Envanter getiriliyor...", - "fetching_campaigns": "Kampanyalar getiriliyor...", - "adding_campaigns": "Kampanyaları envantere ekle... {counter}" - }, - "tabs": { - "main": "Anasayfa", - "inventory": "Envanter", - "settings": "Ayarlar", - "help": "Yardım" - }, - "tray": { - "notification_title": "Drop alındı", - "minimize": "Sistem tepsisine küçült", - "show": "Göster", - "quit": "Çık" - }, - "login": { - "name": "Giriş Yap", - "labels": "Durum:\nKullanıcı ID:", - "logged_in": "Giriş Yapıldı", - "logged_out": "Çıkış Yapıldı", - "logging_in": "Kayıt Ol...", - "required": "Kaydolmak gerekiyor", - "request": "Devam etmek için lütfen giriş yapınız.", - "username": "Kullanıcı Adı", - "password": "Parola", - "twofa_code": "2FA Kodu (opsyonel)", - "button": "Kayıt Ol" - }, - "websocket": { - "name": "WebSocket Status", - "websocket": "WebSocket #{id}:", - "initializing": "Başlat...", - "connected": "Bağlandı", - "disconnected": "Bağlantı koptu", - "connecting": "Bağlanıyor...", - "disconnecting": "Bağlantı kesiliyor...", - "reconnecting": "Yeniden bağlanılıyor..." - }, - "progress": { - "name": "Drop İlerlemesi", - "drop": "Drop:", - "game": "Oyun:", - "campaign": "Kampanya:", - "remaining": "{time} geriye kalan", - "drop_progress": "İlerleme:", - "campaign_progress": "İlerleme:" - }, - "channels": { - "name": "Kanallar", - "switch": "Değiştir", - "load_points": "Puanları Yükle", - "online": "ONLINE ✔", - "pending": "OFFLINE ⏳", - "offline": "OFFLINE ❌", - "headings": { - "channel": "Kanal", - "status": "Durum", - "game": "Oyun", - "viewers": "İzleyici", - "points": "Puan" - } - }, - "inventory": { - "filter": { - "name": "Filtre", - "show": "Dava etmek:", - "not_linked": "Bağlantılı değil", - "upcoming": "Gelecek", - "expired": "Süresi doldu", - "excluded": "Hariç tutuldu", - "finished": "Aldı", - "refresh": "Güncellemek için" - }, - "status": { - "linked": "Bağlantılı ✔", - "not_linked": "Bağlantılı değil ❌", - "active": "Aktif ✔", - "upcoming": "Gelecek ⏳", - "expired": "Süresi dolmuş ❌", - "claimed": "Alındı ​​✔", - "ready_to_claim": "Almaya hazır ⏳" - }, - "starts": "Başladı: {time}", - "ends": "Bitiş: {time}", - "allowed_channels": "Katılan Kanallar:", - "all_channels": "Tüm Kanallar", - "and_more": "ve {amount} diğer...", - "percent_progress": "{percent} {minutes} dakika", - "minutes_progress": "{minutes} dakika" - }, - "settings": { - "general": { - "name": "Genel", - "autostart": "Otomatik başlatma: ", - "tray": "Sistem tepsisine otomatik başlatma: ", - "priority_only": "Yalnızca öncelik: ", - "proxy": "Proxy (Yeniden başlatma gerektirir):" - }, - "game_name": "Oyun", - "priority": "Öncelik", - "exclude": "Hariç tut", - "reload": "Tekrar yükle", - "reload_text": "Değişikliklerin çoğu, hemen yürürlüğe girmesi için yeniden yükleme gerektirir: " - }, - "help": { - "links": { - "name": "Faydalı Bağlantılar", - "inventory": "Twitch Envanterini Görüntüle", - "campaigns": "Tüm Twitch Kampanyalarını Görüntüle" - }, - "how_it_works": "Nasıl çalışır", - "how_it_works_text": "Uygulama, her ~60 saniyede bir \"izlenen dakika\" olayını o anda izlenmekte olan kanala gönderir.\nBu, düşüşü ileri götürmek için yeterlidir. Bu şekilde, indirmeye gerek yoktur akış sağlar ve bant genişliğinden tasarruf sağlar.\nKanalların çevrimiçi veya çevrimdışı durumunu güncel tutmak için, kanalların durumunu kontrol eden\nbir websocket bağlantısı kurulur.", - "getting_started": "Başlarken", - "getting_started_text": "• Uygulamada oturum açın.\n• Twitch hesabının ilgilendiğiniz tüm kampanyalara bağlı olduğundan emin olun.\n• Tüm ödüllerin işlenmesini istiyorsanız, \"Yalnızca öncelikli \" seçeneğinin işaretini kaldırın ve \"Yeniden Yükle\"ye basın.\n• Yalnızca belirli oyunların dikkate alınmasını istiyorsanız, seçimi oyuna göre daraltmak için \"Öncelik\" listesini kullanın.\n• Liste yukarıdan aşağıya doğru öncelik sırasına göre sıralanır. n• \"Yalnızca öncelik\" seçeneği, öncelik listesinde olmayan oyunların işlenmesini engeller.\n• \"Hariç tut\" listesi ile, asla olması gerektiği düşünülmeyecek oyunların filtrelenmesi mümkündür.\n• Listeler veya seçenekler özelleştirilmişse, değişikliklerin geçerli olması için \"Yeniden Yükle\"ye basılmalıdır." - } + "help": { + "links": { + "name": "Faydalı Bağlantılar", + "inventory": "Twitch Envanterini Görüntüle", + "campaigns": "Tüm Twitch Kampanyalarını Görüntüle" + }, + "how_it_works": "Nasıl çalışır", + "how_it_works_text": "Uygulama, her 20 saniyede bir Twitch'ten o anda izlenmekte olan kanalın ham akış verilerine ait bir URL ister. Daha sonra bu veri akışının meta verilerini alır bu ödülleri ilerletmek için yeterlidir. Bu herhangi bir video ve sesi indirme ihtiyacını tamamen atlar. Kanalların durumunu (Çevrim içi veya Çevrim dışı) güncel tutmak için, akışların yukarı veya aşağı gitmesiyle ilgili olayları veya mevcut izleyici miktarıyla ilgili güncellemeleri alan bir websocket bağlantısı kurulmuştur.", + "getting_started": "Başlarken", + "getting_started_text": "1. Uygulamaya giriş yapın.\n2. Twitch hesabınızın madencilikle ilgilendiğiniz tüm kampanyalara bağlı olduğundan emin olun.\n3. Her şeyi madencilikle ilgileniyorsanız, “Yalnızca öncelikli” seçeneğinin işaretini kaldırın ve “Yeniden Yükle” tuşuna basın.\n4. Önce belirli oyunların madenciliğini yapmak istiyorsanız, seçtiğiniz oyunların sıralı bir listesini oluşturmak için “Öncelik” listesini kullanın. Listenin en üstündeki oyunlar, listenin altındakilerden önce çıkarılmaya çalışılacaktır.\n5. Öncelik listesinde olmayan oyunların madenciliğini önlemek için “Yalnızca öncelik” seçeneğini işaretli tutun. Ya da yapmayın , bu size kalmış.\n6. Uygulamaya hangi oyunların asla madenciliğinin yapılmaması gerektiğini söylemek için “Hariç tut” listesini kullanın.\n7. Listelerden herhangi birinin içeriğini değiştirmek veya “Yalnızca öncelik” seçeneğinin durumunu değiştirmek, değişikliklerin etkili olması için “Yeniden Yükle” düğmesine basmanızı gerektirir." } + } } From 6127388230cfc2138a52e0ad54f16b8d7229324f Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 23:35:53 +0200 Subject: [PATCH 081/122] more translations - readme and patch notes --- README.md | 2 +- patch_notes.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5cc59532..e7ce6283 100644 --- a/README.md +++ b/README.md @@ -132,4 +132,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns +For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns, @DogancanYr, @Nollasko diff --git a/patch_notes.txt b/patch_notes.txt index fb20a790..2d883098 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -2,7 +2,7 @@ ### 25.5.2024 - Added ability to sort by Campaign end date (made by @jaredkotoff) -- Updated **Simplified and Traditional Chinese** translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date +- Updated **Simplified and Traditional Chinese**, **Turkish** and **Ukrainian* translation as well as corresponding credits From b61f80c155d78717f4db5e28b700897c459fbae6 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 25 May 2024 23:43:26 +0200 Subject: [PATCH 082/122] better patch notes readability --- patch_notes.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/patch_notes.txt b/patch_notes.txt index 2d883098..3d8ae4e0 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,6 +1,6 @@ ## v15.5.0 -### 25.5.2024 +25.5.2024 - Added ability to sort by Campaign end date (made by @jaredkotoff) - Updated **Simplified and Traditional Chinese**, **Turkish** and **Ukrainian* translation as well as corresponding credits @@ -8,7 +8,7 @@ ## v15.4.0 -### 23.5.2024 +23.5.2024 - Fixed crash on Linux caused by trying to apply a Windows-exclusive Tkinter theme - Updated **English**, **German**, **Czech**, **Spanish** and **Russian** translation as well as corresponding credits for dark themes and potential future Campaign prioritization by end date @@ -16,20 +16,20 @@ ## v15.3.0 -### 22.5.2024 +22.5.2024 - Completed dark mode 🎉 -### 20.5.2024 +20.5.2024 - Added incomplete dark mode ## v15.2.0 -### 19.5.2024 +19.5.2024 - Updated **French** translation as well as corresponding credits -### 18.5.2024 +18.5.2024 - Updated **Russian**, **Ukrainian** and **Traditional Chinese** translation as well as corresponding credits - Various changes to github workflows @@ -37,6 +37,6 @@ ## v15.1.0 -### 17.5.2024 +17.5.2024 - Updated **Italian**, **Simplified Chinese** and **Spanish** translation as well as corresponding credits - Various changes to github workflows From 0f42b24864caeabc2af71a651c72f4b1d7fefadd Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Sat, 25 May 2024 23:49:52 +0200 Subject: [PATCH 083/122] Added dark mode image --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e7ce6283..ecd43a16 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ Every ~20 seconds, the application asks Twitch for a URL to the raw stream data ![Main](https://user-images.githubusercontent.com/4180725/164298155-c0880ad7-6423-4419-8d73-f3c053730a1b.png) ![Inventory](https://user-images.githubusercontent.com/4180725/164298315-81cae0d2-24a4-4822-a056-154fd763c284.png) ![Settings](https://user-images.githubusercontent.com/4180725/164298391-b13ad40d-3881-436c-8d4c-34e2bbe33a78.png) +![Help](https://github.com/Windows200000/TwitchDropsMiner-updated/assets/72623832/ca1c25e1-650f-415b-ab9d-8cfc001fc7e6) + ### Notes: From 95fa970fc1f11e2e8ac8cf5137b545b77f6cf0f9 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sun, 26 May 2024 00:01:12 +0200 Subject: [PATCH 084/122] fixed patch notes typo --- patch_notes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch_notes.txt b/patch_notes.txt index 3d8ae4e0..b53dd336 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -2,7 +2,7 @@ 25.5.2024 - Added ability to sort by Campaign end date (made by @jaredkotoff) -- Updated **Simplified and Traditional Chinese**, **Turkish** and **Ukrainian* translation as well as corresponding credits +- Updated **Simplified and Traditional Chinese**, **Turkish** and **Ukrainian** translation as well as corresponding credits From cc1d3002718a55f6d4aa199ba2ff13255fdb22be Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Tue, 28 May 2024 15:42:45 +0200 Subject: [PATCH 085/122] translation patch notes and README --- README.md | 2 +- patch_notes.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ecd43a16..03a7119a 100644 --- a/README.md +++ b/README.md @@ -134,4 +134,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns, @DogancanYr, @Nollasko +For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns, @DogancanYr, @Nollasko, @rvpv, @flxderdev diff --git a/patch_notes.txt b/patch_notes.txt index b53dd336..4ebe7935 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,5 +1,8 @@ ## v15.5.0 +28.5.2024 +- updated **Italian**, **Polish**, **Turkish** and **Ukrainian** translation as well as corresponding credits + 25.5.2024 - Added ability to sort by Campaign end date (made by @jaredkotoff) - Updated **Simplified and Traditional Chinese**, **Turkish** and **Ukrainian** translation as well as corresponding credits From 837abba61614799c80a07f6c2340d713b157159a Mon Sep 17 00:00:00 2001 From: Kuddus73 Date: Tue, 28 May 2024 13:43:12 +0000 Subject: [PATCH 086/122] Translate Italiano.json via GitLocalize --- lang/Italiano.json | 310 +++++++++++++++++++++++---------------------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git a/lang/Italiano.json b/lang/Italiano.json index 320f09dc..3567ea1e 100644 --- a/lang/Italiano.json +++ b/lang/Italiano.json @@ -1,162 +1,164 @@ { - "english_name": "Italian", + "english_name": "Italian", + "status": { + "terminated": "\nApplicazione Terminata.\nChiudi la finestra per uscire dall'applicazione.", + "watching": "Guardando: {channel}", + "goes_online": "{channel} è ONLINE, cambiando...", + "goes_offline": "{channel} è OFFLINE, cambiando...", + "claimed_drop": "Contenuti riscattati: {drop}", + "claimed_points": "Punti bonus riscattati: {points}", + "earned_points": "Punti bonus guadagnati per aver guardato la stream: {points}, totale: {balance}", + "no_channel": "Nessun canale disponibile da guardare. In attesa di un canale ONLINE...", + "no_campaign": "Nessuna campagna attiva per ottenere i premi. In attesa di una campagna attiva..." + }, + "login": { + "unexpected_content": "Tipo di contenuto inaspettato restituito, di solito a causa di un reindirizzamento. Hai bisogno di fare il login per accedere a internet?", + "chrome": { + "startup": "Apertura di Chrome...", + "login_to_complete": "Completa la procedura di login manualmente premendo nuovamente il pulsante Login.", + "no_token": "Nessun token di autorizzazione trovato.", + "closed_window": "La finestra di Chrome è stata chiusa prima che la procedura di login potesse completarsi." + }, + "error_code": "Codice di errore del login: {error_code}", + "incorrect_login_pass": "Nome utente o password errati.", + "incorrect_email_code": "Codice email errato.", + "incorrect_twofa_code": "Codice 2FA errato.", + "email_code_required": "Codice email richiesto. Controlla la tua email.", + "twofa_code_required": "Token 2FA richiesto." + }, + "error": { + "captcha": "Il tuo tentativo di login è stato negato da CAPTCHA.\nRiprova tra 12+ ore.", + "site_down": "Twitch è irraggiungibile, riprovo tra {seconds} secondi...", + "no_connection": "Impossibile connettersi a Twitch, riprovo tra {seconds} secondi..." + }, + "gui": { + "output": "Output", "status": { - "terminated": "\nApplicazione Terminata.\nChiudi la finestra per uscire dall'applicazione.", - "watching": "Guardando: {channel}", - "goes_online": "{channel} è ONLINE, cambiando...", - "goes_offline": "{channel} è OFFLINE, cambiando...", - "claimed_drop": "Contenuti riscattati: {drop}", - "claimed_points": "Punti bonus riscattati: {points}", - "earned_points": "Punti bonus guadagnati per aver guardato la stream: {points}, totale: {balance}", - "no_channel": "Nessun canale disponibile da guardare. In attesa di un canale ONLINE...", - "no_campaign": "Nessuna campagna attiva per ottenere i premi. In attesa di una campagna attiva..." + "name": "Stato", + "idle": "Inattivo", + "exiting": "Uscendo...", + "terminated": "Terminato", + "cleanup": "Pulendo i canali...", + "gathering": "Raccogliendo i canali...", + "switching": "Cambiando canale...", + "fetching_inventory": "Recupero dell'inventario...", + "fetching_campaigns": "Recupero delle campagne...", + "adding_campaigns": "Aggiunta delle campagne all'inventario... {counter}" + }, + "tabs": { + "main": "Principale", + "inventory": "Inventario", + "settings": "Impostazioni", + "help": "Aiuto" + }, + "tray": { + "notification_title": "Premio Ottenuto", + "minimize": "Minimizza nella barra delle applicazioni", + "show": "Mostra", + "quit": "Esci" }, "login": { - "unexpected_content": "Tipo di contenuto inaspettato restituito, di solito a causa di un reindirizzamento. Hai bisogno di fare il login per accedere a internet?", - "chrome": { - "startup": "Apertura di Chrome...", - "login_to_complete": "Completa la procedura di login manualmente premendo nuovamente il pulsante Login.", - "no_token": "Nessun token di autorizzazione trovato.", - "closed_window": "La finestra di Chrome è stata chiusa prima che la procedura di login potesse completarsi." - }, - "error_code": "Codice di errore del login: {error_code}", - "incorrect_login_pass": "Nome utente o password errati.", - "incorrect_email_code": "Codice email errato.", - "incorrect_twofa_code": "Codice 2FA errato.", - "email_code_required": "Codice email richiesto. Controlla la tua email.", - "twofa_code_required": "Token 2FA richiesto." + "name": "Dettagli Login", + "labels": "Stato:\nID Utente:", + "logged_in": "Loggato", + "logged_out": "Non loggato", + "logging_in": "Loggando...", + "required": "Login richiesto", + "request": "Per favore, effettua il login per continuare.", + "username": "Nome utente", + "password": "Password", + "twofa_code": "Codice 2FA (opzionale)", + "button": "Login" + }, + "websocket": { + "name": "Stato del Websocket", + "websocket": "Websocket #{id}:", + "initializing": "Inizializzando...", + "connected": "Connesso", + "disconnected": "Disconnesso", + "connecting": "Connettendo...", + "disconnecting": "Disconnettendo...", + "reconnecting": "Riconnettendo..." + }, + "progress": { + "name": "Progresso della Campagna", + "drop": "Contenuto:", + "game": "Gioco:", + "campaign": "Campagna:", + "remaining": "{time} rimanenti", + "drop_progress": "Progresso:", + "campaign_progress": "Progresso:" + }, + "channels": { + "name": "Canali", + "switch": "Cambia", + "load_points": "Carica Punti", + "online": "ONLINE ✔", + "pending": "OFFLINE ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "Canale", + "status": "Stato", + "game": "Gioco", + "viewers": "Spettatori", + "points": "Punti" + } + }, + "inventory": { + "filter": { + "name": "Filtro", + "show": "Mostra:", + "not_linked": "Non collegato", + "upcoming": "In arrivo", + "expired": "Scaduti", + "excluded": "Esclusi", + "finished": "Finiti", + "refresh": "Aggiorna" + }, + "status": { + "linked": "Collegato ✔", + "not_linked": "Non collegato ❌", + "active": "Attivo ✔", + "upcoming": "In arrivo ⏳", + "expired": "Scaduto ❌", + "claimed": "Riscattato ✔", + "ready_to_claim": "Pronto per essere riscattato ⏳" + }, + "starts": "Inizia: {time}", + "ends": "Finisce: {time}", + "allowed_channels": "Canali consentiti:", + "all_channels": "Tutti", + "and_more": "e altri {amount}...", + "percent_progress": "{percent} di {minutes} minuti", + "minutes_progress": "{minutes} minuti" }, - "error": { - "captcha": "Il tuo tentativo di login è stato negato da CAPTCHA.\nRiprova tra 12+ ore.", - "site_down": "Twitch è irraggiungibile, riprovo tra {seconds} secondi...", - "no_connection": "Impossibile connettersi a Twitch, riprovo tra {seconds} secondi..." + "settings": { + "general": { + "name": "Generale", + "dark_theme": "Tema scuro: ", + "autostart": "Avvio automatico: ", + "tray": "Avvio automatico nella barra delle applicazioni: ", + "tray_notifications": "Notifiche: ", + "priority_only": "Solo priorità: ", + "prioritze_end": "Dai la priorità in base all'ora di fine: ", + "proxy": "Proxy (richiede il riavvio):" + }, + "game_name": "Nome del gioco", + "priority": "Priorità", + "exclude": "Escludi", + "reload": "Ricarica", + "reload_text": "La maggior parte delle modifiche richiede una ricarica con il botto nqui di fianco per avere un effetto immediato: " }, - "gui": { - "output": "Output", - "status": { - "name": "Stato", - "idle": "Inattivo", - "exiting": "Uscendo...", - "terminated": "Terminato", - "cleanup": "Pulendo i canali...", - "gathering": "Raccogliendo i canali...", - "switching": "Cambiando canale...", - "fetching_inventory": "Recupero dell'inventario...", - "fetching_campaigns": "Recupero delle campagne...", - "adding_campaigns": "Aggiunta delle campagne all'inventario... {counter}" - }, - "tabs": { - "main": "Principale", - "inventory": "Inventario", - "settings": "Impostazioni", - "help": "Aiuto" - }, - "tray": { - "notification_title": "Premio Ottenuto", - "minimize": "Minimizza nella barra delle applicazioni", - "show": "Mostra", - "quit": "Esci" - }, - "login": { - "name": "Dettagli Login", - "labels": "Stato:\nID Utente:", - "logged_in": "Loggato", - "logged_out": "Non loggato", - "logging_in": "Loggando...", - "required": "Login richiesto", - "request": "Per favore, effettua il login per continuare.", - "username": "Nome utente", - "password": "Password", - "twofa_code": "Codice 2FA (opzionale)", - "button": "Login" - }, - "websocket": { - "name": "Stato del Websocket", - "websocket": "Websocket #{id}:", - "initializing": "Inizializzando...", - "connected": "Connesso", - "disconnected": "Disconnesso", - "connecting": "Connettendo...", - "disconnecting": "Disconnettendo...", - "reconnecting": "Riconnettendo..." - }, - "progress": { - "name": "Progresso della Campagna", - "drop": "Contenuto:", - "game": "Gioco:", - "campaign": "Campagna:", - "remaining": "{time} rimanenti", - "drop_progress": "Progresso:", - "campaign_progress": "Progresso:" - }, - "channels": { - "name": "Canali", - "switch": "Cambia", - "load_points": "Carica Punti", - "online": "ONLINE \u2714", - "pending": "OFFLINE \u23f3", - "offline": "OFFLINE \u274c", - "headings": { - "channel": "Canale", - "status": "Stato", - "game": "Gioco", - "viewers": "Spettatori", - "points": "Punti" - } - }, - "inventory": { - "filter": { - "name": "Filtro", - "show": "Mostra:", - "not_linked": "Non collegato", - "upcoming": "In arrivo", - "expired": "Scaduti", - "excluded": "Esclusi", - "finished": "Finiti", - "refresh": "Aggiorna" - }, - "status": { - "linked": "Collegato \u2714", - "not_linked": "Non collegato \u274c", - "active": "Attivo \u2714", - "upcoming": "In arrivo \u23f3", - "expired": "Scaduto \u274c", - "claimed": "Riscattato \u2714", - "ready_to_claim": "Pronto per essere riscattato \u23f3" - }, - "starts": "Inizia: {time}", - "ends": "Finisce: {time}", - "allowed_channels": "Canali consentiti:", - "all_channels": "Tutti", - "and_more": "e altri {amount}...", - "percent_progress": "{percent} di {minutes} minuti", - "minutes_progress": "{minutes} minuti" - }, - "settings": { - "general": { - "name": "Generale", - "autostart": "Avvio automatico: ", - "tray": "Avvio automatico nella barra delle applicazioni: ", - "tray_notifications": "Notifiche: ", - "priority_only": "Solo priorità: ", - "proxy": "Proxy (richiede il riavvio):" - }, - "game_name": "Nome del gioco", - "priority": "Priorità", - "exclude": "Escludi", - "reload": "Ricarica", - "reload_text": "La maggior parte delle modifiche richiede una ricarica con il botto nqui di fianco per avere un effetto immediato: " - }, - "help": { - "links": { - "name": "Link utili", - "inventory": "Vedi l'inventario di Twitch", - "campaigns": "Vedi tutte le campagne e gestisci i collegamenti dell'account" - }, - "how_it_works": "Come funziona", - "how_it_works_text": "Circa ogni 20 secondi, l'applicazione chiede a Twitch un URL per il flusso di dati grezzi del canale attualmente guardato. Successivamente, recupera i metadati di questo flusso e ciò è sufficiente per far avanzare il progresso dei drop. Da notare che questo bypassa completamente la necessità di scaricare qualsiasi video o audio della diretta. Per mantenere aggiornato lo stato (ONLINE o OFFLINE) dei canali, viene stabilita una connessione websocket che riceve eventi sui canali che vanno online o offline, oppure aggiornamenti relativi al numero attuale di spettatori.", - "getting_started": "Per iniziare", - "getting_started_text": "1. Effettua il login nell'applicazione.\n2. Assicurati che il tuo account Twitch sia collegato a tutte le campagne per cui sei interessato a ottenere i drop.\n3. Se sei interessato a ottenere tutto, deseleziona \"Solo priorità\" e premi su \"Ricarica\".\n4. Se vuoi ottenere prima giochi specifici, usa la lista \"Priorità\" per impostare una lista ordinata di giochi a tua scelta. I giochi in cima alla lista verranno ottenuti prima.\n5. Mantieni l'opzione \"Solo priorità\" selezionata, per evitare di ottenere giochi che non sono nella lista delle priorità. Oppure non farlo - dipende da te.\n6. Usa la lista \"Escludi\" per dire all'applicazione quali giochi non devono mai essere ottenuti.\n7. Cambiare il contenuto di una delle liste, o cambiare lo stato dell'opzione \"Solo priorità\", richiede di premere su \"Ricarica\" perché le modifiche abbiano effetto." - } + "help": { + "links": { + "name": "Link utili", + "inventory": "Vedi l'inventario di Twitch", + "campaigns": "Vedi tutte le campagne e gestisci i collegamenti dell'account" + }, + "how_it_works": "Come funziona", + "how_it_works_text": "Circa ogni 20 secondi, l'applicazione chiede a Twitch un URL per il flusso di dati grezzi del canale attualmente guardato. Successivamente, recupera i metadati di questo flusso e ciò è sufficiente per far avanzare il progresso dei drop. Da notare che questo bypassa completamente la necessità di scaricare qualsiasi video o audio della diretta. Per mantenere aggiornato lo stato (ONLINE o OFFLINE) dei canali, viene stabilita una connessione websocket che riceve eventi sui canali che vanno online o offline, oppure aggiornamenti relativi al numero attuale di spettatori.", + "getting_started": "Per iniziare", + "getting_started_text": "1. Effettua il login nell'applicazione.\n2. Assicurati che il tuo account Twitch sia collegato a tutte le campagne per cui sei interessato a ottenere i drop.\n3. Se sei interessato a ottenere tutto, deseleziona \"Solo priorità\" e premi su \"Ricarica\".\n4. Se vuoi ottenere prima giochi specifici, usa la lista \"Priorità\" per impostare una lista ordinata di giochi a tua scelta. I giochi in cima alla lista verranno ottenuti prima.\n5. Mantieni l'opzione \"Solo priorità\" selezionata, per evitare di ottenere giochi che non sono nella lista delle priorità. Oppure non farlo - dipende da te.\n6. Usa la lista \"Escludi\" per dire all'applicazione quali giochi non devono mai essere ottenuti.\n7. Cambiare il contenuto di una delle liste, o cambiare lo stato dell'opzione \"Solo priorità\", richiede di premere su \"Ricarica\" perché le modifiche abbiano effetto." } + } } From 05b1edc78c050d66009255bcda9ea854c4baacd2 Mon Sep 17 00:00:00 2001 From: flxder Date: Tue, 28 May 2024 13:43:17 +0000 Subject: [PATCH 087/122] Translate Polski.json via GitLocalize --- lang/Polski.json | 309 ++++++++++++++++++++++++----------------------- 1 file changed, 155 insertions(+), 154 deletions(-) diff --git a/lang/Polski.json b/lang/Polski.json index 85cfa44e..566faafa 100644 --- a/lang/Polski.json +++ b/lang/Polski.json @@ -1,162 +1,163 @@ { - "english_name": "Polish", + "english_name": "Polish", + "status": { + "terminated": "\nAplikacja została zatrzymana.\nZamknij okno, aby wyjść z aplikacji.", + "watching": "Oglądam kanał: {channel}", + "goes_online": "Nowy status kanału {channel}: ONLINE, zmieniam...", + "goes_offline": "Nowy status kanału {channel}: OFFLINE, zmieniam...", + "claimed_drop": "Odebrano drop: {drop}", + "claimed_points": "Odebrano punkty: {points}", + "earned_points": "Zdobyto punkty za oglądanie: {points} | Łącznie: {balance}", + "no_channel": "Brak możliwych kanałów do oglądania. Oczekiwanie na nową kampanię...", + "no_campaign": "Brak dostępnych aktywnych kampanii. Oczekiwanie na nową kampanię..." + }, + "login": { + "unexpected_content": "Nieoczekiwany błąd zawartości, zwykle z powodu przekierowania.\nUpewnij się że nie jest wymagane dodatkowe logowanie bądź potwierdzenie dostępu do internetu.", + "chrome": { + "startup": "Uruchamianie Chrome...", + "login_to_complete": "Naciśnij ponownie zaloguj, aby zakończyć proces ręcznego logowania...", + "no_token": "Nie znaleziono tokena autoryzacyjnego.", + "closed_window": "Okno przeglądarki Chrome zostało zamknięte przed zakończeniem procesu logowania." + }, + "error_code": "Kod błędu logowania: {error_code}", + "incorrect_login_pass": "Nieprawidłowa nazwa użytkownika lub hasło.", + "incorrect_email_code": "Nieprawidłowy kod z e-maila.", + "incorrect_twofa_code": "Nieprawidłowy kod 2FA.", + "email_code_required": "Wymagany kod z e-maila.", + "twofa_code_required": "Wymagany token 2FA." + }, + "error": { + "captcha": "Próba logowania została odrzucona przez CAPTCHA.\nProszę spróbować ponownie za co najmniej 12 godzin.", + "site_down": "Strona Twitcha nie jest dostępna. Spróbuj ponownie za {seconds} s....", + "no_connection": "Nie można połączyć się z Twitchem. Spróbuj ponownie za {seconds} s...." + }, + "gui": { + "output": "Dziennik zdarzeń", "status": { - "terminated": "\nAplikacja została zatrzymana.\nZamknij okno, aby wyjść z aplikacji.", - "watching": "Oglądam kanał: {channel}", - "goes_online": "Nowy status kanału {channel}: ONLINE, zmieniam...", - "goes_offline": "Nowy status kanału {channel}: OFFLINE, zmieniam...", - "claimed_drop": "Odebrano drop: {drop}", - "claimed_points": "Odebrano punkty: {points}", - "earned_points": "Zdobyto punkty za oglądanie: {points} | Łącznie: {balance}", - "no_channel": "Brak możliwych kanałów do oglądania. Oczekiwanie na nową kampanię...", - "no_campaign": "Brak dostępnych aktywnych kampanii. Oczekiwanie na nową kampanię..." + "name": "Status", + "idle": "Bezczynność", + "exiting": "Zamykanie...", + "terminated": "Zatrzymano", + "cleanup": "Czyszczenie kanałów...", + "gathering": "Szukanie kanałów...", + "switching": "Zmiana kanałów...", + "fetching_inventory": "Odświeżanie ekwipunku...", + "fetching_campaigns": "Odświeżanie kampanii...", + "adding_campaigns": "Dodawanie kampanii do ekwipunku... {counter}" + }, + "tabs": { + "main": "Główna", + "inventory": "Ekwipunek", + "settings": "Ustawienia", + "help": "Pomoc" + }, + "tray": { + "notification_title": "Drop odebrany", + "minimize": "Zminimalizuj", + "show": "Pokaż", + "quit": "Wyjdź" }, "login": { - "unexpected_content": "Nieoczekiwany błąd zawartości, zwykle z powodu przekierowania.\nUpewnij się że nie jest wymagane dodatkowe logowanie bądź potwierdzenie dostępu do internetu.", - "chrome": { - "startup": "Uruchamianie Chrome...", - "login_to_complete": "Naciśnij ponownie zaloguj, aby zakończyć proces ręcznego logowania...", - "no_token": "Nie znaleziono tokena autoryzacyjnego.", - "closed_window": "Okno przeglądarki Chrome zostało zamknięte przed zakończeniem procesu logowania." - }, - "error_code": "Kod błędu logowania: {error_code}", - "incorrect_login_pass": "Nieprawidłowa nazwa użytkownika lub hasło.", - "incorrect_email_code": "Nieprawidłowy kod z e-maila.", - "incorrect_twofa_code": "Nieprawidłowy kod 2FA.", - "email_code_required": "Wymagany kod z e-maila.", - "twofa_code_required": "Wymagany token 2FA." + "name": "Logowanie", + "labels": "Status:\nIdentyfikator:", + "logged_in": "Zalogowano", + "logged_out": "Wylogowano", + "logging_in": "Logowanie...", + "required": "Wymagane zalogowanie", + "request": "Zaloguj się, by kontynuować.", + "username": "Nazwa użytkownika", + "password": "Hasło", + "twofa_code": "Kod 2FA (opcjonalnie)", + "button": "Zaloguj" + }, + "websocket": { + "name": "Status WebSocket", + "websocket": "WebSocket #{id}:", + "initializing": "Inicjalizacja...", + "connected": "Połączono", + "disconnected": "Rozłączono", + "connecting": "Łączenie...", + "disconnecting": "Rozłączanie...", + "reconnecting": "Ponowne łączenie..." + }, + "progress": { + "name": "Postępy kampanii", + "drop": "Drop:", + "game": "Gra:", + "campaign": "Kampania:", + "remaining": "Pozostało: {time}", + "drop_progress": "Postęp dropu:", + "campaign_progress": "Postęp kampanii:" + }, + "channels": { + "name": "Kanały", + "switch": "Zmień", + "load_points": "Załaduj punkty", + "online": "ONLINE ✔", + "pending": "W TOKU ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "Kanał", + "status": "Status", + "game": "Gra", + "viewers": "Widzowie", + "points": "Punkty" + } + }, + "inventory": { + "filter": { + "name": "Filtr", + "show": "Pokaż:", + "not_linked": "Niepołączone", + "upcoming": "Nadchodzące", + "expired": "Wygasłe", + "excluded": "Wykluczone", + "finished": "Ukończone", + "refresh": "Odśwież" + }, + "status": { + "linked": "Połączono ✔", + "not_linked": "Nie połączono ❌", + "active": "Aktywna ✔", + "upcoming": "Nadchodząca ⏳", + "expired": "Wygasła ❌", + "claimed": "Odebrano ✔", + "ready_to_claim": "Gotowe do odebrania ⏳" + }, + "starts": "Rozpoczęcie: {time}", + "ends": "Koniec: {time}", + "allowed_channels": "Dozwolone kanały:", + "all_channels": "Wszystkie kanały", + "and_more": "i {amount} więcej...", + "percent_progress": "{percent} z {minutes} min.", + "minutes_progress": "{minutes} min." }, - "error": { - "captcha": "Próba logowania została odrzucona przez CAPTCHA.\nProszę spróbować ponownie za co najmniej 12 godzin.", - "site_down": "Strona Twitcha nie jest dostępna. Spróbuj ponownie za {seconds} s....", - "no_connection": "Nie można połączyć się z Twitchem. Spróbuj ponownie za {seconds} s...." + "settings": { + "general": { + "name": "Ogólne", + "dark_theme": "Ciemny motyw:", + "autostart": "Autostart: ", + "tray": "Autostart z zasobnika: ", + "tray_notifications": "Powiadomienia z zasobnika: ", + "priority_only": "Tylko priorytetowe: ", + "proxy": "Proxy (wymaga restartu):" + }, + "game_name": "Nazwa gry", + "priority": "Priorytety", + "exclude": "Wykluczone", + "reload": "Przeładuj", + "reload_text": "Większość zmian wymaga przeładowania, które natychmiastowo je zastosuje: " }, - "gui": { - "output": "Dziennik zdarzeń", - "status": { - "name": "Status", - "idle": "Bezczynność", - "exiting": "Zamykanie...", - "terminated": "Zatrzymano", - "cleanup": "Czyszczenie kanałów...", - "gathering": "Szukanie kanałów...", - "switching": "Zmiana kanałów...", - "fetching_inventory": "Odświeżanie ekwipunku...", - "fetching_campaigns": "Odświeżanie kampanii...", - "adding_campaigns": "Dodawanie kampanii do ekwipunku... {counter}" - }, - "tabs": { - "main": "Główna", - "inventory": "Ekwipunek", - "settings": "Ustawienia", - "help": "Pomoc" - }, - "tray": { - "notification_title": "Drop odebrany", - "minimize": "Zminimalizuj", - "show": "Pokaż", - "quit": "Wyjdź" - }, - "login": { - "name": "Logowanie", - "labels": "Status:\nIdentyfikator:", - "logged_in": "Zalogowano", - "logged_out": "Wylogowano", - "logging_in": "Logowanie...", - "required": "Wymagane zalogowanie", - "request": "Zaloguj się, by kontynuować.", - "username": "Nazwa użytkownika", - "password": "Hasło", - "twofa_code": "Kod 2FA (opcjonalnie)", - "button": "Zaloguj" - }, - "websocket": { - "name": "Status WebSocket", - "websocket": "WebSocket #{id}:", - "initializing": "Inicjalizacja...", - "connected": "Połączono", - "disconnected": "Rozłączono", - "connecting": "Łączenie...", - "disconnecting": "Rozłączanie...", - "reconnecting": "Ponowne łączenie..." - }, - "progress": { - "name": "Postępy kampanii", - "drop": "Drop:", - "game": "Gra:", - "campaign": "Kampania:", - "remaining": "Pozostało: {time}", - "drop_progress": "Postęp dropu:", - "campaign_progress": "Postęp kampanii:" - }, - "channels": { - "name": "Kanały", - "switch": "Zmień", - "load_points": "Załaduj punkty", - "online": "ONLINE ✔", - "pending": "W TOKU ⏳", - "offline": "OFFLINE ❌", - "headings": { - "channel": "Kanał", - "status": "Status", - "game": "Gra", - "viewers": "Widzowie", - "points": "Punkty" - } - }, - "inventory": { - "filter": { - "name": "Filtr", - "show": "Pokaż:", - "not_linked": "Niepołączone", - "upcoming": "Nadchodzące", - "expired": "Wygasłe", - "excluded": "Wykluczone", - "finished": "Ukończone", - "refresh": "Odśwież" - }, - "status": { - "linked": "Połączono ✔", - "not_linked": "Nie połączono ❌", - "active": "Aktywna ✔", - "upcoming": "Nadchodząca ⏳", - "expired": "Wygasła ❌", - "claimed": "Odebrano ✔", - "ready_to_claim": "Gotowe do odebrania ⏳" - }, - "starts": "Rozpoczęcie: {time}", - "ends": "Koniec: {time}", - "allowed_channels": "Dozwolone kanały:", - "all_channels": "Wszystkie kanały", - "and_more": "i {amount} więcej...", - "percent_progress": "{percent} z {minutes} min.", - "minutes_progress": "{minutes} min." - }, - "settings": { - "general": { - "name": "Ogólne", - "autostart": "Autostart: ", - "tray": "Autostart z zasobnika: ", - "tray_notifications": "Powiadomienia z zasobnika: ", - "priority_only": "Tylko priorytetowe: ", - "proxy": "Proxy (wymaga restartu):" - }, - "game_name": "Nazwa gry", - "priority": "Priorytety", - "exclude": "Wykluczone", - "reload": "Przeładuj", - "reload_text": "Większość zmian wymaga przeładowania, które natychmiastowo je zastosuje: " - }, - "help": { - "links": { - "name": "Pomocne linki", - "inventory": "Zobacz swój ekwipunek na Twitchu", - "campaigns": "Zobacz wszystkie kampanie na Twitchu" - }, - "how_it_works": "Jak to działa?", - "how_it_works_text": "Co ~60 sekund aplikacja wysyła zdarzenie „obejrzana minuta” do kanału, który jest aktualnie oglądany - to wystarczy, aby ukończyć dropienie. Zauważ, że w ten sposób możesz całkowicie pominąć konieczność pobierania rzeczywistego strumienia wideo i dźwięku. Do utrzymania statusu ONLINE lub OFFLINE kanałów używane jest połączenie WebSocket, które odbiera zdarzenia o zmianie statusu kanałów oraz aktualizuje aktualną ilość widzów.", - "getting_started": "Pierwsze kroki", - "getting_started_text": "1. Zaloguj się do aplikacji.\n2. Upewnij się, że twoje konto Twitch jest połączone ze wszystkimi kampaniami, z których chcesz dropić.\n3. Odznacz opcję „Tylko priorytetowe” i kliknij „Przeładuj”, jeśli chcesz rozpocząć dropienie ze wszystkich aktywnych kampanii.\n4. Użyj listy „Priorytety”, aby wybrać uporządkowaną listę gier, z których chcesz otrzymać dropy. Gry z górnej części listy będą miały większy priorytet dropienia niż te niżej na liście.\n5. Zaznacz opcję „Tylko priorytetowe”, aby wykluczyć z dropienia gry, które nie są na liście priorytetowej.\n6. Użyj listy „Wykluczone”, aby wskazać aplikacji gry, z których przedmioty nigdy nie powinny być dropione.\n7. Zmiana zawartości list lub opcji „Tylko priorytetowe” wymaga kliknięcia „Przeładuj”, aby aplikacja mogła zastosować wprowadzone zmiany." - } + "help": { + "links": { + "name": "Pomocne linki", + "inventory": "Zobacz swój ekwipunek na Twitchu", + "campaigns": "Zobacz wszystkie kampanie na Twitchu" + }, + "how_it_works": "Jak to działa?", + "how_it_works_text": "Co ~60 sekund aplikacja wysyła zdarzenie „obejrzana minuta” do kanału, który jest aktualnie oglądany - to wystarczy, aby ukończyć dropienie. Zauważ, że w ten sposób możesz całkowicie pominąć konieczność pobierania rzeczywistego strumienia wideo i dźwięku. Do utrzymania statusu ONLINE lub OFFLINE kanałów używane jest połączenie WebSocket, które odbiera zdarzenia o zmianie statusu kanałów oraz aktualizuje aktualną ilość widzów.", + "getting_started": "Pierwsze kroki", + "getting_started_text": "1. Zaloguj się do aplikacji.\n2. Upewnij się, że twoje konto Twitch jest połączone ze wszystkimi kampaniami, z których chcesz dropić.\n3. Odznacz opcję „Tylko priorytetowe” i kliknij „Przeładuj”, jeśli chcesz rozpocząć dropienie ze wszystkich aktywnych kampanii.\n4. Użyj listy „Priorytety”, aby wybrać uporządkowaną listę gier, z których chcesz otrzymać dropy. Gry z górnej części listy będą miały większy priorytet dropienia niż te niżej na liście.\n5. Zaznacz opcję „Tylko priorytetowe”, aby wykluczyć z dropienia gry, które nie są na liście priorytetowej.\n6. Użyj listy „Wykluczone”, aby wskazać aplikacji gry, z których przedmioty nigdy nie powinny być dropione.\n7. Zmiana zawartości list lub opcji „Tylko priorytetowe” wymaga kliknięcia „Przeładuj”, aby aplikacja mogła zastosować wprowadzone zmiany." } + } } From fcbe9e1ce48b7157bca0b10c600c61e9eab12088 Mon Sep 17 00:00:00 2001 From: rvpv Date: Tue, 28 May 2024 13:43:18 +0000 Subject: [PATCH 088/122] Translate Polski.json via GitLocalize --- lang/Polski.json | 1 + 1 file changed, 1 insertion(+) diff --git a/lang/Polski.json b/lang/Polski.json index 566faafa..a5667731 100644 --- a/lang/Polski.json +++ b/lang/Polski.json @@ -140,6 +140,7 @@ "tray": "Autostart z zasobnika: ", "tray_notifications": "Powiadomienia z zasobnika: ", "priority_only": "Tylko priorytetowe: ", + "prioritze_end": "Priorytetyzuj według czasu zakończenia:", "proxy": "Proxy (wymaga restartu):" }, "game_name": "Nazwa gry", From ebd18e23ee45af1500372d8ef17a3cedfc0dab39 Mon Sep 17 00:00:00 2001 From: DogancanYr Date: Tue, 28 May 2024 13:43:25 +0000 Subject: [PATCH 089/122] =?UTF-8?q?Translate=20T=C3=BCrk=C3=A7e.json=20via?= =?UTF-8?q?=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "lang/T\303\274rk\303\247e.json" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/lang/T\303\274rk\303\247e.json" "b/lang/T\303\274rk\303\247e.json" index beeb21c9..92475dd5 100644 --- "a/lang/T\303\274rk\303\247e.json" +++ "b/lang/T\303\274rk\303\247e.json" @@ -124,8 +124,8 @@ "claimed": "Alındı ​​✔", "ready_to_claim": "Almaya hazır ⏳" }, - "starts": "Başladı: {time}", - "ends": "Bitti: {time}", + "starts": "Başlangıç: {time}", + "ends": "Bitiş: {time}", "allowed_channels": "Katılan Kanallar:", "all_channels": "Tüm Kanallar", "and_more": "ve {amount} diğer...", From 66e34f65dd55c98d2c270cb41aefd25a47b7a652 Mon Sep 17 00:00:00 2001 From: Dmytro Zozulia Date: Tue, 28 May 2024 13:43:36 +0000 Subject: [PATCH 090/122] =?UTF-8?q?Translate=20=D0=A3=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D1=97=D0=BD=D1=81=D1=8C=D0=BA=D0=B0.json=20via=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\227\320\275\321\201\321\214\320\272\320\260.json" | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" index 2aabea75..5d4a9a73 100644 --- "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" +++ "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" @@ -53,7 +53,7 @@ }, "tray": { "notification_title": "Дроп отримано", - "minimize": "Згорнути в трей", + "minimize": "Згорнути в лоток", "show": "Показати", "quit": "Вийти" }, @@ -128,7 +128,7 @@ "ends": "Завершується {time}", "allowed_channels": "Дозволені канали:", "all_channels": "Усі", - "and_more": "і {amount} більше...", + "and_more": "та ще {amount}...", "percent_progress": "{percent} від {minutes} хвилин", "minutes_progress": "{minutes} хвилин" }, @@ -137,7 +137,7 @@ "name": "Основні", "dark_theme": "Темна тема:", "autostart": "Автозапуск: ", - "tray": "Автозапуск у треї: ", + "tray": "Автозапуск у лотку: ", "tray_notifications": "Сповіщення: ", "priority_only": "Лише пріоритетні: ", "prioritze_end": "Пріоритизувати ті, що закінчуються раніше:", @@ -147,7 +147,7 @@ "priority": "Пріоритет", "exclude": "Виключити", "reload": "Перезавантажити", - "reload_text": "Більшість змін потребують перезавантаження, щоб набути дії: " + "reload_text": "Більшість змін потребують перезавантаження, щоб набути негайної дії: " }, "help": { "links": { @@ -158,7 +158,7 @@ "how_it_works": "Як це працює?", "how_it_works_text": "Приблизно кожні 20 секунд програма запитує у Twitch URL-адресу необробленого потоку даних каналу, який ви зараз переглядаєте. Потім він отримує метадані цього потоку даних - цього достатньо, щоб здобувати дропи. Зауважте, що це повністю обходить необхідність завантажувати будь-які потокові відео та звук. Щоб підтримувати актуальний стан каналів (ОНЛАЙН або ОФЛАЙН), встановлюється з'єднання з веб-сокетом, який отримує події про збільшення або зменшення кількості трансляцій, або оновлення поточної кількості глядачів.", "getting_started": "Інструкція", - "getting_started_text": "1. Увійдіть у застосунок.\n2. Переконайтеся, що ваш обліковий запис Twitch пов'язаний з усіма обліковими записами ігор, з яких ви хочете здобувати дропи.\n3. Якщо ви зацікавлені у здобуванні всього, зніміть прапорець \"Тільки пріоритет\" і натисніть \"Перезавантажити\".\n4. Якщо ви хочете здобувати з певних ігор, скористайтеся списком \"Пріоритет\", щоб створити впорядкований список ігор за вашим вибором. Ігри будуть здобуватися в порядку розташування в списку.\n5. Не знімайте прапорець \"Тільки пріоритет\", щоб уникнути здобування з ігор, які не входять до пріоритетного списку. Або ні - вирішувати вам.\n6. Використовуйте список \"Виключено\", щоб вказати застосунку, з яких ігор ніколи не слід здобувати.\n7. Зміна вмісту будь-якого зі списків або зміна стану опції \"Тільки пріоритет\" вимагає натискання кнопки \"Перезавантажити\" для набуття змінами чинності.\n\nПереклад виконав Дмитро Зозуля" + "getting_started_text": "1. Увійдіть у застосунок.\n2. Переконайтеся, що ваш обліковий запис Twitch пов'язаний з усіма обліковими записами ігор, з яких ви хочете здобувати дропи.\n3. Якщо ви зацікавлені у здобуванні всього, зніміть прапорець \"Тільки пріоритет\" і натисніть \"Перезавантажити\".\n4. Якщо ви хочете здобувати дропи з певних ігор, скористайтеся списком \"Пріоритет\", щоб створити впорядкований список ігор за вашим вибором. Ігри будуть здобуватися в порядку розташування в списку.\n5. Не знімайте прапорець \"Тільки пріоритет\", щоб уникнути здобування з ігор, які не входять до пріоритетного списку. Або ні - вирішувати вам.\n6. Використовуйте список \"Виключено\", щоб вказати застосунку, з яких ігор ніколи не слід здобувати.\n7. Зміна вмісту будь-якого зі списків або зміна стану опції \"Тільки пріоритет\" вимагає натискання кнопки \"Перезавантажити\" для набуття змінами чинності.\n\nПереклад виконав @Nollasko" } } } From 22300ca3c7b6f76e059f5f68d1d8e3d2d8794b25 Mon Sep 17 00:00:00 2001 From: 5wi_5wi Date: Thu, 30 May 2024 09:19:31 +0000 Subject: [PATCH 091/122] =?UTF-8?q?Translate=20=D8=A7=D9=84=D8=B9=D8=B1?= =?UTF-8?q?=D8=A8=D9=8A=D8=A9.json=20via=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\271\330\261\330\250\331\212\330\251.json" | 310 +++++++++--------- 1 file changed, 156 insertions(+), 154 deletions(-) diff --git "a/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" "b/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" index fa25730f..b1261f5b 100644 --- "a/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" +++ "b/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" @@ -1,162 +1,164 @@ { - "english_name": "Arabic", + "english_name": "Arabic", + "status": { + "terminated": "تم إنهاء التطبيق. \n أغلق النافذة للخروج من التطبيق.", + "watching": "{channel} :يتم حالياَ مشاهدة", + "goes_online": "...اصبح نشط ، تبديل {channel}", + "goes_offline": "...اصبح غير نشط ، تبديل {channel}", + "claimed_drop": "{drop} :تم الحصول على", + "claimed_points": "تم الحصول على: {points} من النقاط الإضافية", + "earned_points": "تم الحصول على:{points} من نقاط المشاهدة ، الإجمالي: {balance}", + "no_channel": "...لا توجد قنوات نشطة متاحة للمشاهدة. في انتظار قناة نشطة", + "no_campaign": "...لا توجد حملات نشطة من اجل تنقيب الإسقاطات. في انتظار حملة نشطة" + }, + "login": { + "unexpected_content": "تم إرجاع نوع محتوى غير متوقع ، يحدث عادة بسبب إعادة التوجيه. هل تحتاج إلى تسجيل الدخول للوصول إلى الإنترنت؟", + "chrome": { + "startup": "...فتح متصفح كروم", + "login_to_complete": "أكمل إجراء تسجيل الدخول يدويًا عن طريق الضغط على زر تسجيل الدخول مرة أخرى.", + "no_token": ".لا يمكن العثور على رمز التفويض", + "closed_window": ".تم إغلاق نافذة متصفح كروم قبل أن يكتمل إجراء تسجيل الدخول" + }, + "error_code": "{error_code} :رمز خطأ تسجيل الدخول", + "incorrect_login_pass": ".اسم المستخدم أو كلمة المرور غير صحيحة", + "incorrect_email_code": ".كود البريد الإلكتروني غير صحيح", + "incorrect_twofa_code": ".كود المصادقة الثنائية غير صحيح", + "email_code_required": ".كود البريد الإلكتروني مطلوب. تحقق من بريدك الالكتروني", + "twofa_code_required": ".رمز المصادقة الثنائية مطلوب" + }, + "error": { + "captcha": ".يرجى المحاولة مجدداَ بعد مرور 12 ساعة \n .CAPTCHA تم رفض محاولة تسجيل الدخول الخاصة بك من قبل", + "site_down": "...ثانية {seconds} معطل ، إعادة المحاولة خلال Twitch", + "no_connection": "...ثانية {seconds} إعادة المحاولة خلال ، Twitch لا يمكن الإتصال بـ" + }, + "gui": { + "output": "الإخراج", "status": { - "terminated": "تم إنهاء التطبيق. \n أغلق النافذة للخروج من التطبيق.", - "watching": "{channel} :يتم حالياَ مشاهدة", - "goes_online": "...اصبح نشط ، تبديل {channel}", - "goes_offline": "...اصبح غير نشط ، تبديل {channel}", - "claimed_drop": "{drop} :تم الحصول على", - "claimed_points": "تم الحصول على: {points} من النقاط الإضافية", - "earned_points": "تم الحصول على:{points} من نقاط المشاهدة ، الإجمالي: {balance}", - "no_channel": "...لا توجد قنوات نشطة متاحة للمشاهدة. في انتظار قناة نشطة", - "no_campaign": "...لا توجد حملات نشطة من اجل تنقيب الإسقاطات. في انتظار حملة نشطة" + "name": "الحالة", + "idle": "خامل", + "exiting": "...جاري الخروج", + "terminated": "تم الانهاء", + "cleanup": "...مسح القنوات", + "gathering": "...جمع القنوات", + "switching": "...تبديل القناة", + "fetching_inventory": "...جلب محتويات الحقيبة", + "fetching_campaigns": "...جلب الحملات", + "adding_campaigns": "{counter} ...إضافة الحملات إلى الحقيبة" + }, + "tabs": { + "main": "الرئيسية", + "inventory": "الحقيبة", + "settings": "الإعدادات", + "help": "مساعدة" + }, + "tray": { + "notification_title": "تم الحصول على هذا الإسقاط", + "minimize": "تصغير الى الدرج", + "show": "عرض", + "quit": "خروج" }, "login": { - "unexpected_content": "تم إرجاع نوع محتوى غير متوقع ، يحدث عادة بسبب إعادة التوجيه. هل تحتاج إلى تسجيل الدخول للوصول إلى الإنترنت؟", - "chrome": { - "startup": "...فتح متصفح كروم", - "login_to_complete": "أكمل إجراء تسجيل الدخول يدويًا عن طريق الضغط على زر تسجيل الدخول مرة أخرى.", - "no_token": ".لا يمكن العثور على رمز التفويض", - "closed_window": ".تم إغلاق نافذة متصفح كروم قبل أن يكتمل إجراء تسجيل الدخول" - }, - "error_code": "{error_code} :رمز خطأ تسجيل الدخول", - "incorrect_login_pass": ".اسم المستخدم أو كلمة المرور غير صحيحة", - "incorrect_email_code": ".كود البريد الإلكتروني غير صحيح", - "incorrect_twofa_code": ".كود المصادقة الثنائية غير صحيح", - "email_code_required": ".كود البريد الإلكتروني مطلوب. تحقق من بريدك الالكتروني", - "twofa_code_required": ".رمز المصادقة الثنائية مطلوب" + "name": "تسجيل الدخول و معلومات عن الحساب", + "labels": "الحالة ➜\nالمستخدم ID ➜", + "logged_in": "تم تسجيل الدخول", + "logged_out": "تم تسجيل الخروج", + "logging_in": "...تسجيل الدخول", + "required": "تسجيل الدخول مطلوب", + "request": ".الرجاء تسجيل الدخول للمتابعة", + "username": "اسم المستخدم", + "password": "كلمة المرور", + "twofa_code": "المصادقة الثنائية (اختياري)", + "button": "تسجيل الدخول" + }, + "websocket": { + "name": "WebSocket حالة الـ", + "websocket": "WebSocket #{id}:", + "initializing": "...جاري التهيئة", + "connected": "متصل", + "disconnected": "غير متصل", + "connecting": "...جاري الاتصال", + "disconnecting": "...جاري قطع الاتصال", + "reconnecting": "...إعادة الاتصال" + }, + "progress": { + "name": "تقدم الحملة", + "drop": ":الإسقاط", + "game": ":اللعبة", + "campaign": ":الحملة", + "remaining": "{time} متبقي", + "drop_progress": "التقدم ➜", + "campaign_progress": "التقدم ➜" + }, + "channels": { + "name": "القنوات", + "switch": "تبديل", + "load_points": "تحميل النقاط", + "online": "✔ نشط", + "pending": "⏳ غير نشط", + "offline": "❌ غير نشط", + "headings": { + "channel": "القناة", + "status": "الحالة", + "game": "اللعبة", + "viewers": "المشاهدين", + "points": "النقاط" + } + }, + "inventory": { + "filter": { + "name": "تصفية", + "show": "عرض ➜", + "not_linked": "غير مرتبط", + "upcoming": "القادمة", + "expired": "المنتهية", + "excluded": "المستبعدة", + "finished": "المكتملة", + "refresh": "تحديث" + }, + "status": { + "linked": "✔ مرتبط", + "not_linked": "❌ غير مرتبط", + "active": "✔ نشط", + "upcoming": "⏳ قادم", + "expired": "❌ منتهي", + "claimed": "✔ تم الحصول عليه", + "ready_to_claim": "⏳ جاهز للحصول عليه" + }, + "starts": "{time} :يبدأ", + "ends": "{time} :ينتهي", + "allowed_channels": ":القنوات المسموح بها", + "all_channels": "الكل", + "and_more": "...و {amount} قناة اخرى", + "percent_progress": "تم التقدم {percent} من {minutes} دقيقة", + "minutes_progress": "متبقي {minutes} دقيقة" }, - "error": { - "captcha": ".يرجى المحاولة مجدداَ بعد مرور 12 ساعة \n .CAPTCHA تم رفض محاولة تسجيل الدخول الخاصة بك من قبل", - "site_down": "...ثانية {seconds} معطل ، إعادة المحاولة خلال Twitch", - "no_connection": "...ثانية {seconds} إعادة المحاولة خلال ، Twitch لا يمكن الإتصال بـ" + "settings": { + "general": { + "name": "عام", + "dark_theme": "المظهر الداكن: ", + "autostart": "تشغيل تلقائي ", + "tray": "تشغيل تلقائي في الدرج ", + "tray_notifications": "إشعارات الدرج ", + "priority_only": "الأولوية فقط ", + "prioritze_end": "تحديد الأولويات من خلال الانتهاء في أقرب وقت: ", + "proxy": "بروكسي (يتطلب إعادة التشغيل) " + }, + "game_name": "اسم اللعبة", + "priority": "أولوية", + "exclude": "إستبعاد", + "reload": "إعادة تحميل", + "reload_text": ".ملاحظة: تتطلب معظم التغييرات إعادة التحميل حتى تصبح سارية المفعول " }, - "gui": { - "output": "الإخراج", - "status": { - "name": "الحالة", - "idle": "خامل", - "exiting": "...جاري الخروج", - "terminated": "تم الانهاء", - "cleanup": "...مسح القنوات", - "gathering": "...جمع القنوات", - "switching": "...تبديل القناة", - "fetching_inventory": "...جلب محتويات الحقيبة", - "fetching_campaigns": "...جلب الحملات", - "adding_campaigns": "{counter} ...إضافة الحملات إلى الحقيبة" - }, - "tabs": { - "main": "الرئيسية", - "inventory": "الحقيبة", - "settings": "الإعدادات", - "help": "مساعدة" - }, - "tray": { - "notification_title": "تم الحصول على هذا الإسقاط", - "minimize": "تصغير الى الدرج", - "show": "عرض", - "quit": "خروج" - }, - "login": { - "name": "تسجيل الدخول و معلومات عن الحساب", - "labels": "الحالة \u279C\nالمستخدم ID \u279C", - "logged_in": "تم تسجيل الدخول", - "logged_out": "تم تسجيل الخروج", - "logging_in": "...تسجيل الدخول", - "required": "تسجيل الدخول مطلوب", - "request": ".الرجاء تسجيل الدخول للمتابعة", - "username": "اسم المستخدم", - "password": "كلمة المرور", - "twofa_code": "المصادقة الثنائية (اختياري)", - "button": "تسجيل الدخول" - }, - "websocket": { - "name": "WebSocket حالة الـ", - "websocket": "WebSocket #{id}:", - "initializing": "...جاري التهيئة", - "connected": "متصل", - "disconnected": "غير متصل", - "connecting": "...جاري الاتصال", - "disconnecting": "...جاري قطع الاتصال", - "reconnecting": "...إعادة الاتصال" - }, - "progress": { - "name": "تقدم الحملة", - "drop": ":الإسقاط", - "game": ":اللعبة", - "campaign": ":الحملة", - "remaining": "{time} متبقي", - "drop_progress": "التقدم \u279C", - "campaign_progress": "التقدم \u279C" - }, - "channels": { - "name": "القنوات", - "switch": "تبديل", - "load_points": "تحميل النقاط", - "online": "\u2714 نشط", - "pending": "\u23f3 غير نشط", - "offline": "\u274c غير نشط", - "headings": { - "channel": "القناة", - "status": "الحالة", - "game": "اللعبة", - "viewers": "المشاهدين", - "points": "النقاط" - } - }, - "inventory": { - "filter": { - "name": "تصفية", - "show": "عرض \u279C", - "not_linked": "غير مرتبط", - "upcoming": "القادمة", - "expired": "المنتهية", - "excluded": "المستبعدة", - "finished": "المكتملة", - "refresh": "تحديث" - }, - "status": { - "linked": "\u2714 مرتبط", - "not_linked": "\u274c غير مرتبط", - "active": "\u2714 نشط", - "upcoming": "\u23f3 قادم", - "expired": "\u274c منتهي", - "claimed": "\u2714 تم الحصول عليه", - "ready_to_claim": "\u23f3 جاهز للحصول عليه" - }, - "starts": "{time} :يبدأ", - "ends": "{time} :ينتهي", - "allowed_channels": ":القنوات المسموح بها", - "all_channels": "الكل", - "and_more": "...و {amount} قناة اخرى", - "percent_progress": "تم التقدم {percent} من {minutes} دقيقة", - "minutes_progress": "متبقي {minutes} دقيقة" - }, - "settings": { - "general": { - "name": "عام", - "autostart": "تشغيل تلقائي ", - "tray": "تشغيل تلقائي في الدرج ", - "tray_notifications": "إشعارات الدرج ", - "priority_only": "الأولوية فقط ", - "proxy": "بروكسي (يتطلب إعادة التشغيل) " - }, - "game_name": "اسم اللعبة", - "priority": "أولوية", - "exclude": "إستبعاد", - "reload": "إعادة تحميل", - "reload_text": ".ملاحظة: تتطلب معظم التغييرات إعادة التحميل حتى تصبح سارية المفعول " - }, - "help": { - "links": { - "name": "روابط مفيدة", - "inventory": "Twitch رؤية الحقيبة على", - "campaigns": "الإطلاع على جميع الحملات وإدارة روابط الحساب" - }, - "how_it_works": "!كيف يعمل التطبيق", - "how_it_works_text": " ، كل 60 ثانية تقريباَ يرسل التطبيق حدثاَ \"دقيقة تمت مشاهدتها\" إلى القناة التي تتم مشاهدتها حالياَ\n.وهذا يكفي لتعزيز تقدم الإسقاطات\n.لاحظ أن هذا يتخطى تمامًا الحاجة إلى تنزيل أي فيديو أو صوت فعلي\nو للمحافظة على تحديث حالة القنوات هناك اتصال ويب سوكت والذي يتلقى احداثاَ\nحول البثوت المباشرة التي تصبح نشطة او غير نشطة ، او عن العدد الحالي للمشاهدين", - "getting_started": "البدء", - "getting_started_text": "1. قم بتسجيل الدخول للتطبيق\n2. مرتبط بجميع الحملات المهتم بتنقيبها Twitch تأكد من ان حسابك على\n3. إذا كنت مهتم بتنقيب كل شي فقم بإلغاء تحديد خيار \"الأولوية فقط\" واضغط على إعادة التحميل\n4. اذا كنت تريد تنقيب لعبة معينة اولا ، فقم بإستخدام قائمة \"أولوية\" لإعداد قائمة مرتبة من الألعاب الي تختارها\n وسيتم محاولة تعدين الألعاب من اعلى القائمة اولاَ ، قبل الألعاب الموجودة في الاسفل\n5. \"قم بتحديد خيار \"الأولوية فقط\" ، لتجنب تنقيب العاب غير مدرجة في قائمة \"أولوية\n6. استخدم قائمة \"إستبعاد\" لإخبار التطبيق بالألعاب التي يجب ألا يتم تنقيبها ابداَ\n7. \"لإحداث تغيير في احد القوائم او تحديد او الغاء تحديد خيار \"الأولويةفقط\nيتطلب الضغط على خيار \"إعادة التحميل\" لتصبح التغييرات سارية المفعول" - } + "help": { + "links": { + "name": "روابط مفيدة", + "inventory": "Twitch رؤية الحقيبة على", + "campaigns": "الإطلاع على جميع الحملات وإدارة روابط الحساب" + }, + "how_it_works": "!كيف يعمل التطبيق", + "how_it_works_text": " ، كل 60 ثانية تقريباَ يرسل التطبيق حدثاَ \"دقيقة تمت مشاهدتها\" إلى القناة التي تتم مشاهدتها حالياَ\n.وهذا يكفي لتعزيز تقدم الإسقاطات\n.لاحظ أن هذا يتخطى تمامًا الحاجة إلى تنزيل أي فيديو أو صوت فعلي\nو للمحافظة على تحديث حالة القنوات هناك اتصال ويب سوكت والذي يتلقى احداثاَ\nحول البثوت المباشرة التي تصبح نشطة او غير نشطة ، او عن العدد الحالي للمشاهدين", + "getting_started": "البدء", + "getting_started_text": "1. قم بتسجيل الدخول للتطبيق\n2. مرتبط بجميع الحملات المهتم بتنقيبها Twitch تأكد من ان حسابك على\n3. إذا كنت مهتم بتنقيب كل شي فقم بإلغاء تحديد خيار \"الأولوية فقط\" واضغط على إعادة التحميل\n4. اذا كنت تريد تنقيب لعبة معينة اولا ، فقم بإستخدام قائمة \"أولوية\" لإعداد قائمة مرتبة من الألعاب الي تختارها\n وسيتم محاولة تعدين الألعاب من اعلى القائمة اولاَ ، قبل الألعاب الموجودة في الاسفل\n5. \"قم بتحديد خيار \"الأولوية فقط\" ، لتجنب تنقيب العاب غير مدرجة في قائمة \"أولوية\n6. استخدم قائمة \"إستبعاد\" لإخبار التطبيق بالألعاب التي يجب ألا يتم تنقيبها ابداَ\n7. \"لإحداث تغيير في احد القوائم او تحديد او الغاء تحديد خيار \"الأولويةفقط\nيتطلب الضغط على خيار \"إعادة التحميل\" لتصبح التغييرات سارية المفعول" } + } } From 53a0e2b95ec67b0b2ad2e56c39e452ab7f01cefa Mon Sep 17 00:00:00 2001 From: DogancanYr Date: Thu, 30 May 2024 09:22:01 +0000 Subject: [PATCH 092/122] =?UTF-8?q?Translate=20T=C3=BCrk=C3=A7e.json=20via?= =?UTF-8?q?=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "lang/T\303\274rk\303\247e.json" | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git "a/lang/T\303\274rk\303\247e.json" "b/lang/T\303\274rk\303\247e.json" index 92475dd5..bd0eb7db 100644 --- "a/lang/T\303\274rk\303\247e.json" +++ "b/lang/T\303\274rk\303\247e.json" @@ -53,12 +53,12 @@ }, "tray": { "notification_title": "Ödül alındı", - "minimize": "Sistem tepsisine küçült", + "minimize": "Sistem Tepsisine Küçült", "show": "Göster", "quit": "Çık" }, "login": { - "name": "Giriş Yap", + "name": "Giriş Kısmı", "labels": "Durum:\nKullanıcı ID:", "logged_in": "Giriş Yapıldı", "logged_out": "Çıkış Yapıldı", @@ -100,7 +100,7 @@ "channel": "Kanal", "status": "Durum", "game": "Oyun", - "viewers": "İzleyiciler", + "viewers": "İzleyici", "points": "Puan" } }, @@ -144,8 +144,8 @@ "proxy": "Proxy (Yeniden başlatma gerektirir):" }, "game_name": "Oyun ismi", - "priority": "Öncelik", - "exclude": "Hariç tut", + "priority": "Öncelik Sırası", + "exclude": "Hariç Tutulacaklar", "reload": "Yeniden Yükle", "reload_text": "Değişikliklerin uygulanabilmesi için yeniden yükle tuşuna basılması lazım:" }, From 19badbf290e9f91605e116af4ec9884aa96d6666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=AB=E7=83=A6?= Date: Thu, 30 May 2024 09:28:45 +0000 Subject: [PATCH 093/122] =?UTF-8?q?Translate=20=E7=AE=80=E4=BD=93=E4=B8=AD?= =?UTF-8?q?=E6=96=87.json=20via=20GitLocalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" index 48de12a9..73140947 100644 --- "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" +++ "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" @@ -135,7 +135,7 @@ "settings": { "general": { "name": "功能设置", - "dark_theme": "暗色主题: ", + "dark_theme": "黑夜模式: ", "autostart": "开机自启动: ", "tray": "开机自启动并最小化: ", "tray_notifications": "启用托盘通知: ", From 6cf6fc7e644c6877eb21d64f3a8c83cec68a9a7f Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 30 May 2024 11:31:54 +0200 Subject: [PATCH 094/122] udpated README and patch notes --- README.md | 2 +- patch_notes.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 03a7119a..b3b0eb2c 100644 --- a/README.md +++ b/README.md @@ -134,4 +134,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @VSeryi, @notNSANE, @ElvisDesigns, @DogancanYr, @Nollasko, @rvpv, @flxderdev +For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @notNSANE, @ElvisDesigns, @DogancanYr, @Nollasko, @rvpv, @flxderdev, @5wi5wi, @fgr1178707QQ, @Suz1e diff --git a/patch_notes.txt b/patch_notes.txt index 4ebe7935..c24aadac 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,5 +1,8 @@ ## v15.5.0 +30.5.2024 +- updated **Arabic**, **Turkish** and **Simplified Chinese** translation as well as corresponding credits + 28.5.2024 - updated **Italian**, **Polish**, **Turkish** and **Ukrainian** translation as well as corresponding credits From e27728a416085b08ddaee52378447cf910c72508 Mon Sep 17 00:00:00 2001 From: Valentin Metz Date: Wed, 29 May 2024 01:52:49 +0200 Subject: [PATCH 095/122] Fixed prioritize_by_ending_soonest --- gui.py | 14 +++++++------- lang/Deutsch.json | 2 +- lang/English.json | 4 ++-- "lang/Espa\303\261ol.json" | 2 +- lang/Italiano.json | 2 +- lang/Polski.json | 2 +- "lang/T\303\274rk\303\247e.json" | 2 +- "lang/\304\214e\305\241tina.json" | 2 +- ...3\321\201\321\201\320\272\320\270\320\271.json" | 2 +- ...7\320\275\321\201\321\214\320\272\320\260.json" | 2 +- ...6\200\344\275\223\344\270\255\346\226\207.json" | 2 +- ...1\201\351\253\224\344\270\255\346\226\207.json" | 2 +- settings.py | 6 +++--- translate.py | 4 ++-- twitch.py | 4 ++-- 15 files changed, 26 insertions(+), 26 deletions(-) diff --git a/gui.py b/gui.py index 0d06bd19..c50c91e6 100644 --- a/gui.py +++ b/gui.py @@ -1458,7 +1458,7 @@ class _SettingsVars(TypedDict): dark_theme: IntVar autostart: IntVar priority_only: IntVar - prioritze_end: IntVar + prioritize_by_ending_soonest: IntVar tray_notifications: IntVar @@ -1477,7 +1477,7 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): "dark_theme": IntVar(master, self._settings.dark_theme), "autostart": IntVar(master, self._settings.autostart), "priority_only": IntVar(master, self._settings.priority_only), - "prioritze_end": IntVar(master, self._settings.prioritze_end), + "prioritize_by_ending_soonest": IntVar(master, self._settings.prioritize_by_ending_soonest), "tray_notifications": IntVar(master, self._settings.tray_notifications), } master.rowconfigure(0, weight=1) @@ -1543,10 +1543,10 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): checkboxes_frame, variable=self._vars["priority_only"], command=self.priority_only ).grid(column=1, row=irow, sticky="w") ttk.Label( - checkboxes_frame, text=_("gui", "settings", "general", "prioritze_end") + checkboxes_frame, text=_("gui", "settings", "general", "prioritize_by_ending_soonest") ).grid(column=0, row=(irow := irow + 1), sticky="e") ttk.Checkbutton( - checkboxes_frame, variable=self._vars["prioritze_end"], command=self.prioritze_end + checkboxes_frame, variable=self._vars["prioritize_by_ending_soonest"], command=self.prioritize_by_ending_soonest ).grid(column=1, row=irow, sticky="w") # proxy frame proxy_frame = ttk.Frame(center_frame2) @@ -1767,8 +1767,8 @@ def priority_delete(self) -> None: def priority_only(self) -> None: self._settings.priority_only = bool(self._vars["priority_only"].get()) - def prioritze_end(self) -> None: - self._settings.prioritze_end = bool(self._vars["prioritze_end"].get()) + def prioritize_by_ending_soonest(self) -> None: + self._settings.prioritize_by_ending_soonest = bool(self._vars["prioritize_by_ending_soonest"].get()) def exclude_add(self) -> None: game_name: str = self._exclude_entry.get() @@ -2399,7 +2399,7 @@ async def main(exit_event: asyncio.Event): autostart=False, language="English", priority_only=False, - prioritze_end=False, + prioritize_by_ending_soonest=False, autostart_tray=False, exclude={"Lit Game"}, tray_notifications=True diff --git a/lang/Deutsch.json b/lang/Deutsch.json index f47ca00f..ae59d8cb 100644 --- a/lang/Deutsch.json +++ b/lang/Deutsch.json @@ -140,7 +140,7 @@ "tray": "Autostart ins System Tray: ", "tray_notifications": "System Tray Benachrichtigungen:", "priority_only": "Nur Priorität: ", - "prioritze_end": "Kampagnen nach Ende priorisieren: ", + "prioritize_by_ending_soonest": "Kampagnen nach Ende priorisieren: ", "proxy": "Proxy (Erfordert Neustart):" }, "game_name": "Spiel", diff --git a/lang/English.json b/lang/English.json index 06e06e05..4c6e0178 100644 --- a/lang/English.json +++ b/lang/English.json @@ -140,7 +140,7 @@ "tray": "Autostart into tray: ", "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", - "prioritze_end": "Prioritize by ending soonest: ", + "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", "proxy": "Proxy (requires restart):" }, "game_name": "Game name", @@ -161,4 +161,4 @@ "getting_started_text": "1. Login into the application.\n2. Ensure your Twitch account is linked to all campaigns you're interested in mining.\n3. If you're interested in just mining everything, uncheck \"Priority only\" and press on \"Reload\".\n4. If you want to mine specific games first, use the \"Priority\" list to setup an ordered list of games of your choice. Games from the top of the list will be attempted to be mined first, before the ones lower down the list.\n5. Keep the \"Priority only\" option checked, to avoid mining games that are not on the priority list. Or not - it's up to you.\n6. Use the \"Exclude\" list to tell the application which games should never be mined.\n7. Changing the contents of either of the lists, or changing the state of the \"Priority only\" option, requires you to press on \"Reload\" for the changes to take an effect." } } -} \ No newline at end of file +} diff --git "a/lang/Espa\303\261ol.json" "b/lang/Espa\303\261ol.json" index e7bae604..b73859d7 100644 --- "a/lang/Espa\303\261ol.json" +++ "b/lang/Espa\303\261ol.json" @@ -140,7 +140,7 @@ "tray": "Ejecutar en la bandeja del sistema: ", "tray_notifications": "Mostrar notificaciones: ", "priority_only": "Minar solo juegos preferidos: ", - "prioritze_end": "Priorizar campañas por fecha de finalización: ", + "prioritize_by_ending_soonest": "Priorizar campañas por fecha de finalización: ", "proxy": "Proxy (requiere reinicio):" }, "game_name": "Nombre del juego", diff --git a/lang/Italiano.json b/lang/Italiano.json index 3567ea1e..8ea7016d 100644 --- a/lang/Italiano.json +++ b/lang/Italiano.json @@ -140,7 +140,7 @@ "tray": "Avvio automatico nella barra delle applicazioni: ", "tray_notifications": "Notifiche: ", "priority_only": "Solo priorità: ", - "prioritze_end": "Dai la priorità in base all'ora di fine: ", + "prioritize_by_ending_soonest": "Dai la priorità in base all'ora di fine: ", "proxy": "Proxy (richiede il riavvio):" }, "game_name": "Nome del gioco", diff --git a/lang/Polski.json b/lang/Polski.json index a5667731..feded1a7 100644 --- a/lang/Polski.json +++ b/lang/Polski.json @@ -140,7 +140,7 @@ "tray": "Autostart z zasobnika: ", "tray_notifications": "Powiadomienia z zasobnika: ", "priority_only": "Tylko priorytetowe: ", - "prioritze_end": "Priorytetyzuj według czasu zakończenia:", + "prioritize_by_ending_soonest": "Priorytetyzuj według czasu zakończenia:", "proxy": "Proxy (wymaga restartu):" }, "game_name": "Nazwa gry", diff --git "a/lang/T\303\274rk\303\247e.json" "b/lang/T\303\274rk\303\247e.json" index bd0eb7db..9bede2ac 100644 --- "a/lang/T\303\274rk\303\247e.json" +++ "b/lang/T\303\274rk\303\247e.json" @@ -140,7 +140,7 @@ "tray": "Sistem tepsisine otomatik başlat: ", "tray_notifications": "Bildirim gönder: ", "priority_only": "Öncelik sıralamasına göre: ", - "prioritze_end": "En kısa sürede biteceklere öncelik ver:", + "prioritize_by_ending_soonest": "En kısa sürede biteceklere öncelik ver:", "proxy": "Proxy (Yeniden başlatma gerektirir):" }, "game_name": "Oyun ismi", diff --git "a/lang/\304\214e\305\241tina.json" "b/lang/\304\214e\305\241tina.json" index 60e9d303..640c31b3 100644 --- "a/lang/\304\214e\305\241tina.json" +++ "b/lang/\304\214e\305\241tina.json" @@ -140,7 +140,7 @@ "tray": "Automaticky spusti minimalizovaně: ", "tray_notifications": "Oznámení v systémové liště:", "priority_only": "Pouze prioritní: ", - "prioritze_end": "Upřednostnit kampaně podle data ukončení:", + "prioritize_by_ending_soonest": "Upřednostnit kampaně podle data ukončení:", "proxy": "Proxy:" }, "game_name": "Název Hry", diff --git "a/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" "b/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" index b3082bec..4df7b03a 100644 --- "a/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" +++ "b/lang/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.json" @@ -140,7 +140,7 @@ "tray": "Автозапуск свёрнутым", "tray_notifications": "Всплывающие уведомления", "priority_only": "Только приоритет", - "prioritze_end": "Приоритизация кампаний по дате окончания:", + "prioritize_by_ending_soonest": "Приоритизация кампаний по дате окончания:", "proxy": "Прокси (Требуется перезапуск):" }, "game_name": "Игра", diff --git "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" index 5d4a9a73..51893244 100644 --- "a/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" +++ "b/lang/\320\243\320\272\321\200\320\260\321\227\320\275\321\201\321\214\320\272\320\260.json" @@ -140,7 +140,7 @@ "tray": "Автозапуск у лотку: ", "tray_notifications": "Сповіщення: ", "priority_only": "Лише пріоритетні: ", - "prioritze_end": "Пріоритизувати ті, що закінчуються раніше:", + "prioritize_by_ending_soonest": "Пріоритизувати ті, що закінчуються раніше:", "proxy": "Проксі (потребує перезапуску):" }, "game_name": "Назва гри", diff --git "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" index 73140947..edd6edca 100644 --- "a/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" +++ "b/lang/\347\256\200\344\275\223\344\270\255\346\226\207.json" @@ -140,7 +140,7 @@ "tray": "开机自启动并最小化: ", "tray_notifications": "启用托盘通知: ", "priority_only": "仅参与优先掉宝游戏: ", - "prioritze_end": "按掉宝游戏的结束日期决定优先度: ", + "prioritize_by_ending_soonest": "按掉宝游戏的结束日期决定优先度: ", "proxy": "代理:" }, "game_name": "游戏名称", diff --git "a/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" "b/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" index 69496172..aeb97384 100644 --- "a/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" +++ "b/lang/\347\271\201\351\253\224\344\270\255\346\226\207.json" @@ -140,7 +140,7 @@ "tray": "開機自啟動並最小化: ", "tray_notifications": "啟用托盤通知: ", "priority_only": "僅參與優先掉寶遊戲: ", - "prioritze_end": "按掉寶遊戲的結束日期決定優先度: ", + "prioritize_by_ending_soonest": "按掉寶遊戲的結束日期決定優先度: ", "proxy": "代理:" }, "game_name": "遊戲名稱", diff --git a/settings.py b/settings.py index 72a531b4..eb0a0a16 100644 --- a/settings.py +++ b/settings.py @@ -19,7 +19,7 @@ class SettingsFile(TypedDict): exclude: set[str] priority: list[str] priority_only: bool - prioritze_end: bool + prioritize_by_ending_soonest: bool autostart_tray: bool connection_quality: int tray_notifications: bool @@ -32,7 +32,7 @@ class SettingsFile(TypedDict): "dark_theme": False, "autostart": False, "priority_only": True, - "prioritze_end": False, + "prioritize_by_ending_soonest": False, "autostart_tray": False, "connection_quality": 1, "language": DEFAULT_LANG, @@ -57,7 +57,7 @@ class Settings: exclude: set[str] priority: list[str] priority_only: bool - prioritze_end: bool + prioritize_by_ending_soonest: bool autostart_tray: bool connection_quality: int tray_notifications: bool diff --git a/translate.py b/translate.py index 0a694a1d..57ef1081 100644 --- a/translate.py +++ b/translate.py @@ -166,7 +166,7 @@ class GUISettingsGeneral(TypedDict): tray: str tray_notifications: str priority_only: str - prioritze_end: str + prioritize_by_ending_soonest: str proxy: str @@ -365,7 +365,7 @@ class Translation(TypedDict): "tray": "Autostart into tray: ", "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", - "prioritze_end": "Prioritize by ending soonest: ", + "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", "proxy": "Proxy (requires restart):", }, "game_name": "Game name", diff --git a/twitch.py b/twitch.py index 32580f2d..d6ee64d8 100644 --- a/twitch.py +++ b/twitch.py @@ -829,7 +829,7 @@ async def _run(self): # figure out which games we want self.wanted_games.clear() priorities = self.gui.settings.priorities() - prioritze_end = self.settings.prioritze_end + prioritize_by_ending_soonest = self.settings.prioritize_by_ending_soonest campaigns = self.inventory filtered_campaigns = list(filter(self.filter_campaigns, campaigns)) for i, campaign in enumerate(filtered_campaigns): @@ -837,7 +837,7 @@ async def _run(self): # get users priority preference game_priority = priorities.get(game.name, 0) if (game_priority): - if (prioritze_end): + if (prioritize_by_ending_soonest): # list is sorted by end_at so this keeps them in order self.wanted_games[game] = len(filtered_campaigns) - i else: From f8cadecc5cd2ed71469f12f91e143dd678131dcf Mon Sep 17 00:00:00 2001 From: Valentin Metz Date: Wed, 29 May 2024 02:03:00 +0200 Subject: [PATCH 096/122] Print logs to stdout --- gui.py | 2 ++ main.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/gui.py b/gui.py index c50c91e6..d001bf59 100644 --- a/gui.py +++ b/gui.py @@ -687,6 +687,7 @@ async def _timer_loop(self): self._timer_task = None def start_timer(self): + self._manager.print(f"Progress: {self._drop.current_minutes}/{self._drop.required_minutes} - {self._drop.campaign}") if self._timer_task is None: if self._drop is None or self._drop.remaining_minutes <= 0: # if we're starting the timer at 0 drop minutes, @@ -2164,6 +2165,7 @@ def clear_drop(self): self.tray.update_title(None) def print(self, message: str): + print(f"{datetime.now().strftime('%Y-%m-%d %X')}: {message}") # print to our custom output self.output.print(message) diff --git a/main.py b/main.py index ff5eb932..5b51ab27 100644 --- a/main.py +++ b/main.py @@ -2,9 +2,11 @@ # import an additional thing for proper PyInstaller freeze support from multiprocessing import freeze_support +from datetime import datetime if __name__ == "__main__": + print(f"{datetime.now().strftime('%Y-%m-%d %X')}: Starting: Twitch Drops Miner") freeze_support() import io import sys From 10988d81454615dd9f0653f2009b936241f78a0b Mon Sep 17 00:00:00 2001 From: Valentin Metz Date: Wed, 29 May 2024 02:10:50 +0200 Subject: [PATCH 097/122] Support unlinked campaigns --- gui.py | 12 ++++++++++++ inventory.py | 6 ++---- lang/English.json | 1 + settings.py | 11 +++++++++++ translate.py | 2 ++ twitch.py | 3 +++ 6 files changed, 31 insertions(+), 4 deletions(-) diff --git a/gui.py b/gui.py index d001bf59..07d508bb 100644 --- a/gui.py +++ b/gui.py @@ -1460,6 +1460,7 @@ class _SettingsVars(TypedDict): autostart: IntVar priority_only: IntVar prioritize_by_ending_soonest: IntVar + unlinked_campaigns: IntVar tray_notifications: IntVar @@ -1479,6 +1480,7 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): "autostart": IntVar(master, self._settings.autostart), "priority_only": IntVar(master, self._settings.priority_only), "prioritize_by_ending_soonest": IntVar(master, self._settings.prioritize_by_ending_soonest), + "unlinked_campaigns": IntVar(master, self._settings.unlinked_campaigns), "tray_notifications": IntVar(master, self._settings.tray_notifications), } master.rowconfigure(0, weight=1) @@ -1549,6 +1551,12 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): ttk.Checkbutton( checkboxes_frame, variable=self._vars["prioritize_by_ending_soonest"], command=self.prioritize_by_ending_soonest ).grid(column=1, row=irow, sticky="w") + ttk.Label( + checkboxes_frame, text=_("gui", "settings", "general", "unlinked_campaigns") + ).grid(column=0, row=(irow := irow + 1), sticky="e") + ttk.Checkbutton( + checkboxes_frame, variable=self._vars["unlinked_campaigns"], command=self.unlinked_campaigns + ).grid(column=1, row=irow, sticky="w") # proxy frame proxy_frame = ttk.Frame(center_frame2) proxy_frame.grid(column=0, row=2) @@ -1771,6 +1779,9 @@ def priority_only(self) -> None: def prioritize_by_ending_soonest(self) -> None: self._settings.prioritize_by_ending_soonest = bool(self._vars["prioritize_by_ending_soonest"].get()) + def unlinked_campaigns(self) -> None: + self._settings.unlinked_campaigns = bool(self._vars["unlinked_campaigns"].get()) + def exclude_add(self) -> None: game_name: str = self._exclude_entry.get() if not game_name: @@ -2402,6 +2413,7 @@ async def main(exit_event: asyncio.Event): language="English", priority_only=False, prioritize_by_ending_soonest=False, + unlinked_campaigns=False, autostart_tray=False, exclude={"Lit Game"}, tray_notifications=True diff --git a/inventory.py b/inventory.py index eb1f048e..7c57c1cf 100644 --- a/inventory.py +++ b/inventory.py @@ -335,8 +335,7 @@ def get_drop(self, drop_id: str) -> TimedDrop | None: def _base_can_earn(self, channel: Channel | None = None) -> bool: return ( - self.linked # account is connected - and self.active # campaign is active + self.active # campaign is active # channel isn't specified, or there's no ACL, or the channel is in the ACL and (channel is None or not self.allowed_channels or channel in self.allowed_channels) ) @@ -349,8 +348,7 @@ def can_earn_within(self, stamp: datetime) -> bool: # Same as can_earn, but doesn't check the channel # and uses a future timestamp to see if we can earn this campaign later return ( - self.linked - and self.ends_at > datetime.now(timezone.utc) + self.ends_at > datetime.now(timezone.utc) and self.starts_at < stamp and any(drop.can_earn_within(stamp) for drop in self.drops) ) diff --git a/lang/English.json b/lang/English.json index 4c6e0178..68175b63 100644 --- a/lang/English.json +++ b/lang/English.json @@ -141,6 +141,7 @@ "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", + "unlinked_campaigns": "Allow Unlinked Campaigns: ", "proxy": "Proxy (requires restart):" }, "game_name": "Game name", diff --git a/settings.py b/settings.py index eb0a0a16..c1a9a406 100644 --- a/settings.py +++ b/settings.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os from typing import Any, TypedDict, TYPE_CHECKING from yarl import URL @@ -20,6 +21,7 @@ class SettingsFile(TypedDict): priority: list[str] priority_only: bool prioritize_by_ending_soonest: bool + unlinked_campaigns: bool autostart_tray: bool connection_quality: int tray_notifications: bool @@ -33,6 +35,7 @@ class SettingsFile(TypedDict): "autostart": False, "priority_only": True, "prioritize_by_ending_soonest": False, + "unlinked_campaigns": False, "autostart_tray": False, "connection_quality": 1, "language": DEFAULT_LANG, @@ -58,6 +61,7 @@ class Settings: priority: list[str] priority_only: bool prioritize_by_ending_soonest: bool + unlinked_campaigns: bool autostart_tray: bool connection_quality: int tray_notifications: bool @@ -66,9 +70,16 @@ class Settings: def __init__(self, args: ParsedArgs): self._settings: SettingsFile = json_load(SETTINGS_PATH, default_settings) + self.__get_settings_from_env__() self._args: ParsedArgs = args self._altered: bool = False + def __get_settings_from_env__(self): + if(os.environ.get('prioritize_by_ending_soonest') == '1'): + self._settings["prioritize_by_ending_soonest"] = True + if(os.environ.get('UNLINKED_CAMPAIGNS') == '1'): + self._settings["unlinked_campaigns"] = True + # default logic of reading settings is to check args first, then the settings file def __getattr__(self, name: str, /) -> Any: if name in self.PASSTHROUGH: diff --git a/translate.py b/translate.py index 57ef1081..65619cd5 100644 --- a/translate.py +++ b/translate.py @@ -167,6 +167,7 @@ class GUISettingsGeneral(TypedDict): tray_notifications: str priority_only: str prioritize_by_ending_soonest: str + unlinked_campaigns: str proxy: str @@ -366,6 +367,7 @@ class Translation(TypedDict): "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", + "unlinked_campaigns": "Allow Unlinked Campaigns: ", "proxy": "Proxy (requires restart):", }, "game_name": "Game name", diff --git a/twitch.py b/twitch.py index d6ee64d8..33307aec 100644 --- a/twitch.py +++ b/twitch.py @@ -1622,12 +1622,15 @@ def filter_campaigns(self, campaign: list[DropsCampaign]): exclude = self.settings.exclude priority = self.settings.priority priority_only = self.settings.priority_only + unlinked_campaigns = self.settings.unlinked_campaigns game = campaign.game if ( game not in self.wanted_games # isn't already there and game.name not in exclude # and isn't excluded # and isn't excluded by priority_only and (not priority_only or game.name in priority) + # and user wants unlinked games or the game is linked + and (unlinked_campaigns or campaign.linked) # and can be progressed within the next hour and campaign.can_earn_within_next_hour() ): From b9d152fb213f5126b8356c2de28bf4fac0e21436 Mon Sep 17 00:00:00 2001 From: Valentin Metz Date: Thu, 30 May 2024 11:55:16 +0200 Subject: [PATCH 098/122] Revert "Support unlinked campaigns" This reverts commit b2fe84fe011671238f5ebb09dea29ff1b4a82ee9. --- gui.py | 12 ------------ inventory.py | 6 ++++-- lang/English.json | 1 - settings.py | 11 ----------- translate.py | 2 -- twitch.py | 3 --- 6 files changed, 4 insertions(+), 31 deletions(-) diff --git a/gui.py b/gui.py index 07d508bb..d001bf59 100644 --- a/gui.py +++ b/gui.py @@ -1460,7 +1460,6 @@ class _SettingsVars(TypedDict): autostart: IntVar priority_only: IntVar prioritize_by_ending_soonest: IntVar - unlinked_campaigns: IntVar tray_notifications: IntVar @@ -1480,7 +1479,6 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): "autostart": IntVar(master, self._settings.autostart), "priority_only": IntVar(master, self._settings.priority_only), "prioritize_by_ending_soonest": IntVar(master, self._settings.prioritize_by_ending_soonest), - "unlinked_campaigns": IntVar(master, self._settings.unlinked_campaigns), "tray_notifications": IntVar(master, self._settings.tray_notifications), } master.rowconfigure(0, weight=1) @@ -1551,12 +1549,6 @@ def __init__(self, manager: GUIManager, master: ttk.Widget, root: tk.Tk): ttk.Checkbutton( checkboxes_frame, variable=self._vars["prioritize_by_ending_soonest"], command=self.prioritize_by_ending_soonest ).grid(column=1, row=irow, sticky="w") - ttk.Label( - checkboxes_frame, text=_("gui", "settings", "general", "unlinked_campaigns") - ).grid(column=0, row=(irow := irow + 1), sticky="e") - ttk.Checkbutton( - checkboxes_frame, variable=self._vars["unlinked_campaigns"], command=self.unlinked_campaigns - ).grid(column=1, row=irow, sticky="w") # proxy frame proxy_frame = ttk.Frame(center_frame2) proxy_frame.grid(column=0, row=2) @@ -1779,9 +1771,6 @@ def priority_only(self) -> None: def prioritize_by_ending_soonest(self) -> None: self._settings.prioritize_by_ending_soonest = bool(self._vars["prioritize_by_ending_soonest"].get()) - def unlinked_campaigns(self) -> None: - self._settings.unlinked_campaigns = bool(self._vars["unlinked_campaigns"].get()) - def exclude_add(self) -> None: game_name: str = self._exclude_entry.get() if not game_name: @@ -2413,7 +2402,6 @@ async def main(exit_event: asyncio.Event): language="English", priority_only=False, prioritize_by_ending_soonest=False, - unlinked_campaigns=False, autostart_tray=False, exclude={"Lit Game"}, tray_notifications=True diff --git a/inventory.py b/inventory.py index 7c57c1cf..eb1f048e 100644 --- a/inventory.py +++ b/inventory.py @@ -335,7 +335,8 @@ def get_drop(self, drop_id: str) -> TimedDrop | None: def _base_can_earn(self, channel: Channel | None = None) -> bool: return ( - self.active # campaign is active + self.linked # account is connected + and self.active # campaign is active # channel isn't specified, or there's no ACL, or the channel is in the ACL and (channel is None or not self.allowed_channels or channel in self.allowed_channels) ) @@ -348,7 +349,8 @@ def can_earn_within(self, stamp: datetime) -> bool: # Same as can_earn, but doesn't check the channel # and uses a future timestamp to see if we can earn this campaign later return ( - self.ends_at > datetime.now(timezone.utc) + self.linked + and self.ends_at > datetime.now(timezone.utc) and self.starts_at < stamp and any(drop.can_earn_within(stamp) for drop in self.drops) ) diff --git a/lang/English.json b/lang/English.json index 68175b63..4c6e0178 100644 --- a/lang/English.json +++ b/lang/English.json @@ -141,7 +141,6 @@ "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", - "unlinked_campaigns": "Allow Unlinked Campaigns: ", "proxy": "Proxy (requires restart):" }, "game_name": "Game name", diff --git a/settings.py b/settings.py index c1a9a406..eb0a0a16 100644 --- a/settings.py +++ b/settings.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os from typing import Any, TypedDict, TYPE_CHECKING from yarl import URL @@ -21,7 +20,6 @@ class SettingsFile(TypedDict): priority: list[str] priority_only: bool prioritize_by_ending_soonest: bool - unlinked_campaigns: bool autostart_tray: bool connection_quality: int tray_notifications: bool @@ -35,7 +33,6 @@ class SettingsFile(TypedDict): "autostart": False, "priority_only": True, "prioritize_by_ending_soonest": False, - "unlinked_campaigns": False, "autostart_tray": False, "connection_quality": 1, "language": DEFAULT_LANG, @@ -61,7 +58,6 @@ class Settings: priority: list[str] priority_only: bool prioritize_by_ending_soonest: bool - unlinked_campaigns: bool autostart_tray: bool connection_quality: int tray_notifications: bool @@ -70,16 +66,9 @@ class Settings: def __init__(self, args: ParsedArgs): self._settings: SettingsFile = json_load(SETTINGS_PATH, default_settings) - self.__get_settings_from_env__() self._args: ParsedArgs = args self._altered: bool = False - def __get_settings_from_env__(self): - if(os.environ.get('prioritize_by_ending_soonest') == '1'): - self._settings["prioritize_by_ending_soonest"] = True - if(os.environ.get('UNLINKED_CAMPAIGNS') == '1'): - self._settings["unlinked_campaigns"] = True - # default logic of reading settings is to check args first, then the settings file def __getattr__(self, name: str, /) -> Any: if name in self.PASSTHROUGH: diff --git a/translate.py b/translate.py index 65619cd5..57ef1081 100644 --- a/translate.py +++ b/translate.py @@ -167,7 +167,6 @@ class GUISettingsGeneral(TypedDict): tray_notifications: str priority_only: str prioritize_by_ending_soonest: str - unlinked_campaigns: str proxy: str @@ -367,7 +366,6 @@ class Translation(TypedDict): "tray_notifications": "Tray notifications: ", "priority_only": "Priority Only: ", "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", - "unlinked_campaigns": "Allow Unlinked Campaigns: ", "proxy": "Proxy (requires restart):", }, "game_name": "Game name", diff --git a/twitch.py b/twitch.py index 33307aec..d6ee64d8 100644 --- a/twitch.py +++ b/twitch.py @@ -1622,15 +1622,12 @@ def filter_campaigns(self, campaign: list[DropsCampaign]): exclude = self.settings.exclude priority = self.settings.priority priority_only = self.settings.priority_only - unlinked_campaigns = self.settings.unlinked_campaigns game = campaign.game if ( game not in self.wanted_games # isn't already there and game.name not in exclude # and isn't excluded # and isn't excluded by priority_only and (not priority_only or game.name in priority) - # and user wants unlinked games or the game is linked - and (unlinked_campaigns or campaign.linked) # and can be progressed within the next hour and campaign.can_earn_within_next_hour() ): From 9c1b44dd14cd5891c8ba818da2b0d0e20305f230 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 30 May 2024 13:54:11 +0200 Subject: [PATCH 099/122] updated english translation --- README.md | 2 +- lang/English.json | 6 +++--- patch_notes.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b3b0eb2c..1cb1ddf1 100644 --- a/README.md +++ b/README.md @@ -134,4 +134,4 @@ if they aren't already there. Doing so ensures proper markdown rendering on Gith @Bamboozul - For the entirety of the Arabic (العربية) translation. @Kjerne - For the entirety of the Danish (Dansk) translation. -For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @notNSANE, @ElvisDesigns, @DogancanYr, @Nollasko, @rvpv, @flxderdev, @5wi5wi, @fgr1178707QQ, @Suz1e +For updating Translations: @Kuddus73, @VSeryi, @Windows200000, @BreakshadowCN, @kilroy98, @zelda0079, @Calvineries, @notNSANE, @ElvisDesigns, @DogancanYr, @Nollasko, @rvpv, @flxderdev, @5wi5wi, @fgr1178707QQ, @Suz1e, @Patriot99 diff --git a/lang/English.json b/lang/English.json index 4c6e0178..fbc833e9 100644 --- a/lang/English.json +++ b/lang/English.json @@ -17,7 +17,7 @@ "startup": "Opening Chrome...", "login_to_complete": "Complete the login procedure manually by pressing the Login button again.", "no_token": "No authorization token could be found.", - "closed_window": "Chrome window was closed before the login procedure could complete." + "closed_window": "The Chrome window was closed before the login procedure could be completed." }, "error_code": "Login error code: {error_code}", "incorrect_login_pass": "Incorrect username or password.", @@ -156,9 +156,9 @@ "campaigns": "See all campaigns and manage account links" }, "how_it_works": "How It Works", - "how_it_works_text": "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. It then fetches the metadata of this data stream - this is enough to advance the drops. Note that this completely bypasses the need to download any actual stream video and sound. To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection estabilished that receives events about streams going up or down, or updates regarding the current amount of viewers.", + "how_it_works_text": "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. It then fetches the metadata of this data stream - this is enough to advance the drops. Note that this completely bypasses the need to download any actual stream video and sound. To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection established that receives events about streams going up or down, or updates regarding the current number of viewers.", "getting_started": "Getting Started", - "getting_started_text": "1. Login into the application.\n2. Ensure your Twitch account is linked to all campaigns you're interested in mining.\n3. If you're interested in just mining everything, uncheck \"Priority only\" and press on \"Reload\".\n4. If you want to mine specific games first, use the \"Priority\" list to setup an ordered list of games of your choice. Games from the top of the list will be attempted to be mined first, before the ones lower down the list.\n5. Keep the \"Priority only\" option checked, to avoid mining games that are not on the priority list. Or not - it's up to you.\n6. Use the \"Exclude\" list to tell the application which games should never be mined.\n7. Changing the contents of either of the lists, or changing the state of the \"Priority only\" option, requires you to press on \"Reload\" for the changes to take an effect." + "getting_started_text": "1. Log in to the application.\n2. Ensure your Twitch account is linked to all campaigns you're interested in mining.\n3. If you're interested in just mining everything, uncheck \"Priority only\" and press \"Reload\".\n4. If you want to mine specific games first, use the \"Priority\" list to set up an ordered list of games of your choice. Games from the top of the list will be attempted to be mined first, before the ones lower down the list.\n5. Keep the \"Priority only\" option checked to avoid mining games that are not on the priority list. Or not - it's up to you.\n6. Use the \"Exclude\" list to tell the application which games should never be mined.\n7. Changing the contents of either of the lists or changing the state of the \"Priority only\" option, requires you to press \"Reload\" for the changes to take effect." } } } diff --git a/patch_notes.txt b/patch_notes.txt index c24aadac..45778f98 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,7 +1,7 @@ ## v15.5.0 30.5.2024 -- updated **Arabic**, **Turkish** and **Simplified Chinese** translation as well as corresponding credits +- updated **Arabic**, **Turkish**, **Simplified Chinese** and **English** translation as well as corresponding credits 28.5.2024 - updated **Italian**, **Polish**, **Turkish** and **Ukrainian** translation as well as corresponding credits From 664dd22d5dce4e317472d22f9eca0c550f01e64b Mon Sep 17 00:00:00 2001 From: Arne Weber <72623832+Windows200000@users.noreply.github.com> Date: Thu, 30 May 2024 14:08:33 +0200 Subject: [PATCH 100/122] =?UTF-8?q?Update=20=D8=A7=D9=84=D8=B9=D8=B1=D8=A8?= =?UTF-8?q?=D9=8A=D8=A9.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...30\247\331\204\330\271\330\261\330\250\331\212\330\251.json" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" "b/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" index b1261f5b..1bfe6d2d 100644 --- "a/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" +++ "b/lang/\330\247\331\204\330\271\330\261\330\250\331\212\330\251.json" @@ -140,7 +140,7 @@ "tray": "تشغيل تلقائي في الدرج ", "tray_notifications": "إشعارات الدرج ", "priority_only": "الأولوية فقط ", - "prioritze_end": "تحديد الأولويات من خلال الانتهاء في أقرب وقت: ", + "prioritize_by_ending_soonest": "تحديد الأولويات من خلال الانتهاء في أقرب وقت: ", "proxy": "بروكسي (يتطلب إعادة التشغيل) " }, "game_name": "اسم اللعبة", From 35151ecb66f077b035f8f637af2a5efbc813b543 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 30 May 2024 14:28:47 +0200 Subject: [PATCH 101/122] fixed patch patch_notes --- patch_notes.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/patch_notes.txt b/patch_notes.txt index 45778f98..edc9a06f 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,4 +1,4 @@ -## v15.5.0 +## v15.6.0 30.5.2024 - updated **Arabic**, **Turkish**, **Simplified Chinese** and **English** translation as well as corresponding credits @@ -6,6 +6,10 @@ 28.5.2024 - updated **Italian**, **Polish**, **Turkish** and **Ukrainian** translation as well as corresponding credits + + +## v15.5.0 + 25.5.2024 - Added ability to sort by Campaign end date (made by @jaredkotoff) - Updated **Simplified and Traditional Chinese**, **Turkish** and **Ukrainian** translation as well as corresponding credits From ffe127ad483900fd09834615a30d2c88ca777a6b Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Thu, 30 May 2024 14:48:27 +0200 Subject: [PATCH 102/122] fixed translate.py to match English.json --- translate.py | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/translate.py b/translate.py index 57ef1081..2e1f196f 100644 --- a/translate.py +++ b/translate.py @@ -236,13 +236,9 @@ class Translation(TypedDict): ), "chrome": { "startup": "Opening Chrome...", - "login_to_complete": ( - "Complete the login procedure manually by pressing the Login button again." - ), + "login_to_complete": "Complete the login procedure manually by pressing the Login button again.", "no_token": "No authorization token could be found.", - "closed_window": ( - "Chrome window was closed before the login procedure could complete." - ), + "closed_window": "The Chrome window was closed before the login procedure could be completed.", }, "error_code": "Login error code: {error_code}", "incorrect_login_pass": "Incorrect username or password.", @@ -383,30 +379,22 @@ class Translation(TypedDict): "how_it_works": "How It Works", "how_it_works_text": ( "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. " - "It then fetches the metadata of this data stream - this is enough " - "to advance the drops. Note that this completely bypasses the need to download " - "any actual stream video and sound. " - "To keep the status (ONLINE or OFFLINE) of the channels up-to-date, " - "there's a websocket connection estabilished that receives events about streams " - "going up or down, or updates regarding the current amount of viewers." + "It then fetches the metadata of this data stream - this is enough to advance the drops. " + "Note that this completely bypasses the need to download any actual stream video and sound. " + "To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection established " + "that receives events about streams going up or down, or updates regarding the current number of viewers." ), "getting_started": "Getting Started", "getting_started_text": ( - "1. Login into the application.\n" - "2. Ensure your Twitch account is linked to all campaigns " - "you're interested in mining.\n" - "3. If you're interested in just mining everything, " - "uncheck \"Priority only\" and press on \"Reload\".\n" - "4. If you want to mine specific games first, use the \"Priority\" list " - "to setup an ordered list of games of your choice. Games from the top of the list " - "will be attempted to be mined first, before the ones lower down the list.\n" - "5. Keep the \"Priority only\" option checked, to avoid mining games " - "that are not on the priority list. Or not - it's up to you.\n" - "6. Use the \"Exclude\" list to tell the application " - "which games should never be mined.\n" - "7. Changing the contents of either of the lists, or changing the state " - "of the \"Priority only\" option, requires you to press on \"Reload\" " - "for the changes to take an effect." + "1. Log in to the application.\n" + "2. Ensure your Twitch account is linked to all campaigns you're interested in mining.\n" + "3. If you're interested in just mining everything, uncheck \"Priority only\" and press \"Reload\".\n" + "4. If you want to mine specific games first, use the \"Priority\" list to set up an ordered list of games of your choice. " + "Games from the top of the list will be attempted to be mined first, before the ones lower down the list.\n" + "5. Keep the \"Priority only\" option checked to avoid mining games that are not on the priority list. Or not - it's up to you.\n" + "6. Use the \"Exclude\" list to tell the application which games should never be mined.\n" + "7. Changing the contents of either of the lists or changing the state of the \"Priority only\" option, " + "requires you to press \"Reload\" for the changes to take effect." ), }, }, From ea067fffa81c4748cd18fc29903473f1d377dcaa Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 16:29:50 +0200 Subject: [PATCH 103/122] moved default translation from .py to .json --- lang/English.json | 2 +- translate.py | 188 +--------------------------------------------- 2 files changed, 4 insertions(+), 186 deletions(-) diff --git a/lang/English.json b/lang/English.json index fbc833e9..b231dcef 100644 --- a/lang/English.json +++ b/lang/English.json @@ -161,4 +161,4 @@ "getting_started_text": "1. Log in to the application.\n2. Ensure your Twitch account is linked to all campaigns you're interested in mining.\n3. If you're interested in just mining everything, uncheck \"Priority only\" and press \"Reload\".\n4. If you want to mine specific games first, use the \"Priority\" list to set up an ordered list of games of your choice. Games from the top of the list will be attempted to be mined first, before the ones lower down the list.\n5. Keep the \"Priority only\" option checked to avoid mining games that are not on the priority list. Or not - it's up to you.\n6. Use the \"Exclude\" list to tell the application which games should never be mined.\n7. Changing the contents of either of the lists or changing the state of the \"Priority only\" option, requires you to press \"Reload\" for the changes to take effect." } } -} +} \ No newline at end of file diff --git a/translate.py b/translate.py index 2e1f196f..acfe144e 100644 --- a/translate.py +++ b/translate.py @@ -6,6 +6,7 @@ from exceptions import MinerException from utils import json_load, json_save from constants import IS_PACKAGED, LANG_PATH, DEFAULT_LANG +import json if TYPE_CHECKING: from typing_extensions import NotRequired @@ -215,191 +216,8 @@ class Translation(TypedDict): error: ErrorMessages gui: GUIMessages - -default_translation: Translation = { - "english_name": "English", - "status": { - "terminated": "\nApplication Terminated.\nClose the window to exit the application.", - "watching": "Watching: {channel}", - "goes_online": "{channel} goes ONLINE, switching...", - "goes_offline": "{channel} goes OFFLINE, switching...", - "claimed_drop": "Claimed drop: {drop}", - "claimed_points": "Claimed bonus points: {points}", - "earned_points": "Earned points for watching: {points}, total: {balance}", - "no_channel": "No available channels to watch. Waiting for an ONLINE channel...", - "no_campaign": "No active campaigns to mine drops for. Waiting for an active campaign...", - }, - "login": { - "unexpected_content": ( - "Unexpected content type returned, usually due to being redirected. " - "Do you need to login for internet access?" - ), - "chrome": { - "startup": "Opening Chrome...", - "login_to_complete": "Complete the login procedure manually by pressing the Login button again.", - "no_token": "No authorization token could be found.", - "closed_window": "The Chrome window was closed before the login procedure could be completed.", - }, - "error_code": "Login error code: {error_code}", - "incorrect_login_pass": "Incorrect username or password.", - "incorrect_email_code": "Incorrect email code.", - "incorrect_twofa_code": "Incorrect 2FA code.", - "email_code_required": "Email code required. Check your email.", - "twofa_code_required": "2FA token required.", - }, - "error": { - "captcha": "Your login attempt was denied by CAPTCHA.\nPlease try again in 12+ hours.", - "site_down": "Twitch is down, retrying in {seconds} seconds...", - "no_connection": "Cannot connect to Twitch, retrying in {seconds} seconds...", - }, - "gui": { - "output": "Output", - "status": { - "name": "Status", - "idle": "Idle", - "exiting": "Exiting...", - "terminated": "Terminated", - "cleanup": "Cleaning up channels...", - "gathering": "Gathering channels...", - "switching": "Switching the channel...", - "fetching_inventory": "Fetching inventory...", - "fetching_campaigns": "Fetching campaigns...", - "adding_campaigns": "Adding campaigns to inventory... {counter}", - }, - "tabs": { - "main": "Main", - "inventory": "Inventory", - "settings": "Settings", - "help": "Help", - }, - "tray": { - "notification_title": "Mined Drop", - "minimize": "Minimize to Tray", - "show": "Show", - "quit": "Quit", - }, - "login": { - "name": "Login Form", - "labels": "Status:\nUser ID:", - "logged_in": "Logged in", - "logged_out": "Logged out", - "logging_in": "Logging in...", - "required": "Login required", - "request": "Please log in to continue.", - "username": "Username", - "password": "Password", - "twofa_code": "2FA code (optional)", - "button": "Login", - }, - "websocket": { - "name": "Websocket Status", - "websocket": "Websocket #{id}:", - "initializing": "Initializing...", - "connected": "Connected", - "disconnected": "Disconnected", - "connecting": "Connecting...", - "disconnecting": "Disconnecting...", - "reconnecting": "Reconnecting...", - }, - "progress": { - "name": "Campaign Progress", - "drop": "Drop:", - "game": "Game:", - "campaign": "Campaign:", - "remaining": "{time} remaining", - "drop_progress": "Progress:", - "campaign_progress": "Progress:", - }, - "channels": { - "name": "Channels", - "switch": "Switch", - "load_points": "Load Points", - "online": "ONLINE ✔", - "pending": "OFFLINE ⏳", - "offline": "OFFLINE ❌", - "headings": { - "channel": "Channel", - "status": "Status", - "game": "Game", - "viewers": "Viewers", - "points": "Points", - }, - }, - "inventory": { - "filter": { - "name": "Filter", - "show": "Show:", - "not_linked": "Not linked", - "upcoming": "Upcoming", - "expired": "Expired", - "excluded": "Excluded", - "finished": "Finished", - "refresh": "Refresh", - }, - "status": { - "linked": "Linked ✔", - "not_linked": "Not Linked ❌", - "active": "Active ✔", - "upcoming": "Upcoming ⏳", - "expired": "Expired ❌", - "claimed": "Claimed ✔", - "ready_to_claim": "Ready to claim ⏳", - }, - "starts": "Starts: {time}", - "ends": "Ends: {time}", - "allowed_channels": "Allowed Channels:", - "all_channels": "All", - "and_more": "and {amount} more...", - "percent_progress": "{percent} of {minutes} minutes", - "minutes_progress": "{minutes} minutes", - }, - "settings": { - "general": { - "name": "General", - "dark_theme": "Dark theme: ", - "autostart": "Autostart: ", - "tray": "Autostart into tray: ", - "tray_notifications": "Tray notifications: ", - "priority_only": "Priority Only: ", - "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", - "proxy": "Proxy (requires restart):", - }, - "game_name": "Game name", - "priority": "Priority", - "exclude": "Exclude", - "reload": "Reload", - "reload_text": "Most changes require a reload to take an immediate effect: ", - }, - "help": { - "links": { - "name": "Useful Links", - "inventory": "See Twitch inventory", - "campaigns": "See all campaigns and manage account links", - }, - "how_it_works": "How It Works", - "how_it_works_text": ( - "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. " - "It then fetches the metadata of this data stream - this is enough to advance the drops. " - "Note that this completely bypasses the need to download any actual stream video and sound. " - "To keep the status (ONLINE or OFFLINE) of the channels up-to-date, there's a websocket connection established " - "that receives events about streams going up or down, or updates regarding the current number of viewers." - ), - "getting_started": "Getting Started", - "getting_started_text": ( - "1. Log in to the application.\n" - "2. Ensure your Twitch account is linked to all campaigns you're interested in mining.\n" - "3. If you're interested in just mining everything, uncheck \"Priority only\" and press \"Reload\".\n" - "4. If you want to mine specific games first, use the \"Priority\" list to set up an ordered list of games of your choice. " - "Games from the top of the list will be attempted to be mined first, before the ones lower down the list.\n" - "5. Keep the \"Priority only\" option checked to avoid mining games that are not on the priority list. Or not - it's up to you.\n" - "6. Use the \"Exclude\" list to tell the application which games should never be mined.\n" - "7. Changing the contents of either of the lists or changing the state of the \"Priority only\" option, " - "requires you to press \"Reload\" for the changes to take effect." - ), - }, - }, -} - +with open("./lang/English.json", 'r', encoding='utf-8') as file: + default_translation: Translation = json.load(file) class Translator: def __init__(self) -> None: From d7caa465f7db0dec184c7858709b64a13e62e2f2 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 16:34:07 +0200 Subject: [PATCH 104/122] added dark theme to dypeddict --- translate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/translate.py b/translate.py index acfe144e..f2740230 100644 --- a/translate.py +++ b/translate.py @@ -169,6 +169,7 @@ class GUISettingsGeneral(TypedDict): priority_only: str prioritize_by_ending_soonest: str proxy: str + dark_theme: str class GUISettings(TypedDict): From 0cdd5076be9297cd8a564207966fadbb55aa3bad Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 16:47:16 +0200 Subject: [PATCH 105/122] removed writing English.json & using DEFAULT_LANG --- translate.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/translate.py b/translate.py index f2740230..b2123697 100644 --- a/translate.py +++ b/translate.py @@ -217,7 +217,7 @@ class Translation(TypedDict): error: ErrorMessages gui: GUIMessages -with open("./lang/English.json", 'r', encoding='utf-8') as file: +with open(f"./lang/{DEFAULT_LANG}.json", 'r', encoding='utf-8') as file: default_translation: Translation = json.load(file) class Translator: @@ -225,10 +225,6 @@ def __init__(self) -> None: self._langs: list[str] = [] # start with (and always copy) the default translation self._translation: Translation = default_translation.copy() - # if we're in dev, update the template English.json file - if not IS_PACKAGED: - default_langpath = LANG_PATH.joinpath(f"{DEFAULT_LANG}.json") - json_save(default_langpath, default_translation) self._translation["language_name"] = DEFAULT_LANG # load available translation names for filepath in LANG_PATH.glob("*.json"): From 06483b69703d2d4774372779bffbb1f8ba6ec309 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 16:51:09 +0200 Subject: [PATCH 106/122] updated patch notes --- patch_notes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch_notes.txt b/patch_notes.txt index edc9a06f..15a4e16d 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -11,7 +11,7 @@ ## v15.5.0 25.5.2024 -- Added ability to sort by Campaign end date (made by @jaredkotoff) +- Added ability to prioritize by Campaign end date (made by @jaredkotoff) - Updated **Simplified and Traditional Chinese**, **Turkish** and **Ukrainian** translation as well as corresponding credits From 67a5dfc3e1ad2c437f031c9450429af47279aac3 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 17:01:35 +0200 Subject: [PATCH 107/122] pyinstaller --- build.spec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.spec b/build.spec index e14aac63..b8b4f1de 100644 --- a/build.spec +++ b/build.spec @@ -23,8 +23,7 @@ to_add: list[tuple[Path, str, bool]] = [ (Path(SITE_PACKAGES_PATH, "seleniumwire/ca.key"), "./seleniumwire", False), ] for lang_filepath in WORKING_DIR.joinpath("lang").glob("*.json"): - if lang_filepath.stem != DEFAULT_LANG: - to_add.append((lang_filepath, "lang", True)) + to_add.append((lang_filepath, "lang", True)) # ensure the required to-be-added data exists datas: list[tuple[Path, str]] = [] From 5da42c1fda8396ee1add2e7869cd3a316a7a8530 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 17:30:33 +0200 Subject: [PATCH 108/122] testing why English.json isn't included in build --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d96baf9..045cea9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,9 @@ jobs: run: | python3 -m pip install pyinstaller + - name: Check lang + run: echo "${{ github.workspace }}/lang" + - name: Create portable executable run: | pyinstaller build.spec From 0b8d857e51fb0b76bcd8cafc5f0cc735d9ba96cf Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 17:33:45 +0200 Subject: [PATCH 109/122] reverted last commit --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 045cea9d..1d96baf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,9 +54,6 @@ jobs: run: | python3 -m pip install pyinstaller - - name: Check lang - run: echo "${{ github.workspace }}/lang" - - name: Create portable executable run: | pyinstaller build.spec From e79c1ebb88d2504c81b5b43494d11eb25b40fb25 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 18:30:07 +0200 Subject: [PATCH 110/122] reverted default translation for now --- build.spec | 3 +- translate.py | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 223 insertions(+), 4 deletions(-) diff --git a/build.spec b/build.spec index b8b4f1de..e14aac63 100644 --- a/build.spec +++ b/build.spec @@ -23,7 +23,8 @@ to_add: list[tuple[Path, str, bool]] = [ (Path(SITE_PACKAGES_PATH, "seleniumwire/ca.key"), "./seleniumwire", False), ] for lang_filepath in WORKING_DIR.joinpath("lang").glob("*.json"): - to_add.append((lang_filepath, "lang", True)) + if lang_filepath.stem != DEFAULT_LANG: + to_add.append((lang_filepath, "lang", True)) # ensure the required to-be-added data exists datas: list[tuple[Path, str]] = [] diff --git a/translate.py b/translate.py index b2123697..c1a3fdc0 100644 --- a/translate.py +++ b/translate.py @@ -217,14 +217,232 @@ class Translation(TypedDict): error: ErrorMessages gui: GUIMessages -with open(f"./lang/{DEFAULT_LANG}.json", 'r', encoding='utf-8') as file: - default_translation: Translation = json.load(file) +# with open(LANG_PATH.joinpath(f"{DEFAULT_LANG}.json"), 'r', encoding='utf-8') as file: +# default_translation: Translation = json.load(file) + + + + + + + + + +default_translation: Translation = { + "english_name": "English", + "status": { + "terminated": "\nApplication Terminated.\nClose the window to exit the application.", + "watching": "Watching: {channel}", + "goes_online": "{channel} goes ONLINE, switching...", + "goes_offline": "{channel} goes OFFLINE, switching...", + "claimed_drop": "Claimed drop: {drop}", + "claimed_points": "Claimed bonus points: {points}", + "earned_points": "Earned points for watching: {points}, total: {balance}", + "no_channel": "No available channels to watch. Waiting for an ONLINE channel...", + "no_campaign": "No active campaigns to mine drops for. Waiting for an active campaign...", + }, + "login": { + "unexpected_content": ( + "Unexpected content type returned, usually due to being redirected. " + "Do you need to login for internet access?" + ), + "chrome": { + "startup": "Opening Chrome...", + "login_to_complete": ( + "Complete the login procedure manually by pressing the Login button again." + ), + "no_token": "No authorization token could be found.", + "closed_window": ( + "Chrome window was closed before the login procedure could complete." + ), + }, + "error_code": "Login error code: {error_code}", + "incorrect_login_pass": "Incorrect username or password.", + "incorrect_email_code": "Incorrect email code.", + "incorrect_twofa_code": "Incorrect 2FA code.", + "email_code_required": "Email code required. Check your email.", + "twofa_code_required": "2FA token required.", + }, + "error": { + "captcha": "Your login attempt was denied by CAPTCHA.\nPlease try again in 12+ hours.", + "site_down": "Twitch is down, retrying in {seconds} seconds...", + "no_connection": "Cannot connect to Twitch, retrying in {seconds} seconds...", + }, + "gui": { + "output": "Output", + "status": { + "name": "Status", + "idle": "Idle", + "exiting": "Exiting...", + "terminated": "Terminated", + "cleanup": "Cleaning up channels...", + "gathering": "Gathering channels...", + "switching": "Switching the channel...", + "fetching_inventory": "Fetching inventory...", + "fetching_campaigns": "Fetching campaigns...", + "adding_campaigns": "Adding campaigns to inventory... {counter}", + }, + "tabs": { + "main": "Main", + "inventory": "Inventory", + "settings": "Settings", + "help": "Help", + }, + "tray": { + "notification_title": "Mined Drop", + "minimize": "Minimize to Tray", + "show": "Show", + "quit": "Quit", + }, + "login": { + "name": "Login Form", + "labels": "Status:\nUser ID:", + "logged_in": "Logged in", + "logged_out": "Logged out", + "logging_in": "Logging in...", + "required": "Login required", + "request": "Please log in to continue.", + "username": "Username", + "password": "Password", + "twofa_code": "2FA code (optional)", + "button": "Login", + }, + "websocket": { + "name": "Websocket Status", + "websocket": "Websocket #{id}:", + "initializing": "Initializing...", + "connected": "Connected", + "disconnected": "Disconnected", + "connecting": "Connecting...", + "disconnecting": "Disconnecting...", + "reconnecting": "Reconnecting...", + }, + "progress": { + "name": "Campaign Progress", + "drop": "Drop:", + "game": "Game:", + "campaign": "Campaign:", + "remaining": "{time} remaining", + "drop_progress": "Progress:", + "campaign_progress": "Progress:", + }, + "channels": { + "name": "Channels", + "switch": "Switch", + "load_points": "Load Points", + "online": "ONLINE ✔", + "pending": "OFFLINE ⏳", + "offline": "OFFLINE ❌", + "headings": { + "channel": "Channel", + "status": "Status", + "game": "Game", + "viewers": "Viewers", + "points": "Points", + }, + }, + "inventory": { + "filter": { + "name": "Filter", + "show": "Show:", + "not_linked": "Not linked", + "upcoming": "Upcoming", + "expired": "Expired", + "excluded": "Excluded", + "finished": "Finished", + "refresh": "Refresh", + }, + "status": { + "linked": "Linked ✔", + "not_linked": "Not Linked ❌", + "active": "Active ✔", + "upcoming": "Upcoming ⏳", + "expired": "Expired ❌", + "claimed": "Claimed ✔", + "ready_to_claim": "Ready to claim ⏳", + }, + "starts": "Starts: {time}", + "ends": "Ends: {time}", + "allowed_channels": "Allowed Channels:", + "all_channels": "All", + "and_more": "and {amount} more...", + "percent_progress": "{percent} of {minutes} minutes", + "minutes_progress": "{minutes} minutes", + }, + "settings": { + "general": { + "name": "General", + "dark_theme": "Dark theme: ", + "autostart": "Autostart: ", + "tray": "Autostart into tray: ", + "tray_notifications": "Tray notifications: ", + "priority_only": "Priority Only: ", + "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", + "proxy": "Proxy (requires restart):", + }, + "game_name": "Game name", + "priority": "Priority", + "exclude": "Exclude", + "reload": "Reload", + "reload_text": "Most changes require a reload to take an immediate effect: ", + }, + "help": { + "links": { + "name": "Useful Links", + "inventory": "See Twitch inventory", + "campaigns": "See all campaigns and manage account links", + }, + "how_it_works": "How It Works", + "how_it_works_text": ( + "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. " + "It then fetches the metadata of this data stream - this is enough " + "to advance the drops. Note that this completely bypasses the need to download " + "any actual stream video and sound. " + "To keep the status (ONLINE or OFFLINE) of the channels up-to-date, " + "there's a websocket connection estabilished that receives events about streams " + "going up or down, or updates regarding the current amount of viewers." + ), + "getting_started": "Getting Started", + "getting_started_text": ( + "1. Login into the application.\n" + "2. Ensure your Twitch account is linked to all campaigns " + "you're interested in mining.\n" + "3. If you're interested in just mining everything, " + "uncheck \"Priority only\" and press on \"Reload\".\n" + "4. If you want to mine specific games first, use the \"Priority\" list " + "to setup an ordered list of games of your choice. Games from the top of the list " + "will be attempted to be mined first, before the ones lower down the list.\n" + "5. Keep the \"Priority only\" option checked, to avoid mining games " + "that are not on the priority list. Or not - it's up to you.\n" + "6. Use the \"Exclude\" list to tell the application " + "which games should never be mined.\n" + "7. Changing the contents of either of the lists, or changing the state " + "of the \"Priority only\" option, requires you to press on \"Reload\" " + "for the changes to take an effect." + ), + }, + }, +} + + + + + + + + + + + class Translator: def __init__(self) -> None: self._langs: list[str] = [] # start with (and always copy) the default translation - self._translation: Translation = default_translation.copy() + self._translation: Translation = default_translation.copy() # if we're in dev, update the template English.json file + if not IS_PACKAGED: + default_langpath = LANG_PATH.joinpath(f"{DEFAULT_LANG}.json") + json_save(default_langpath, default_translation) self._translation["language_name"] = DEFAULT_LANG # load available translation names for filepath in LANG_PATH.glob("*.json"): From 7721732a24ded685a00d4440362e212c2386fd05 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 19:39:41 +0200 Subject: [PATCH 111/122] Moving default translation to English.json, again --- build.spec | 3 +-- translate.py | 13 +++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/build.spec b/build.spec index e14aac63..b8b4f1de 100644 --- a/build.spec +++ b/build.spec @@ -23,8 +23,7 @@ to_add: list[tuple[Path, str, bool]] = [ (Path(SITE_PACKAGES_PATH, "seleniumwire/ca.key"), "./seleniumwire", False), ] for lang_filepath in WORKING_DIR.joinpath("lang").glob("*.json"): - if lang_filepath.stem != DEFAULT_LANG: - to_add.append((lang_filepath, "lang", True)) + to_add.append((lang_filepath, "lang", True)) # ensure the required to-be-added data exists datas: list[tuple[Path, str]] = [] diff --git a/translate.py b/translate.py index c1a3fdc0..ea2f0ca1 100644 --- a/translate.py +++ b/translate.py @@ -217,9 +217,8 @@ class Translation(TypedDict): error: ErrorMessages gui: GUIMessages -# with open(LANG_PATH.joinpath(f"{DEFAULT_LANG}.json"), 'r', encoding='utf-8') as file: -# default_translation: Translation = json.load(file) - +with open(LANG_PATH.joinpath(f"{DEFAULT_LANG}.json"), 'r', encoding='utf-8') as file: + default_translation: Translation = json.load(file) @@ -228,6 +227,7 @@ class Translation(TypedDict): +""" default_translation: Translation = { "english_name": "English", "status": { @@ -423,7 +423,7 @@ class Translation(TypedDict): }, }, } - +""" @@ -439,10 +439,7 @@ class Translator: def __init__(self) -> None: self._langs: list[str] = [] # start with (and always copy) the default translation - self._translation: Translation = default_translation.copy() # if we're in dev, update the template English.json file - if not IS_PACKAGED: - default_langpath = LANG_PATH.joinpath(f"{DEFAULT_LANG}.json") - json_save(default_langpath, default_translation) + self._translation: Translation = default_translation.copy() self._translation["language_name"] = DEFAULT_LANG # load available translation names for filepath in LANG_PATH.glob("*.json"): From e82f4d8c10404a386d0e32b337977bb1b8415a21 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Fri, 31 May 2024 19:51:03 +0200 Subject: [PATCH 112/122] cleanup translate.py --- translate.py | 219 +-------------------------------------------------- 1 file changed, 2 insertions(+), 217 deletions(-) diff --git a/translate.py b/translate.py index ea2f0ca1..acb929eb 100644 --- a/translate.py +++ b/translate.py @@ -4,8 +4,8 @@ from typing import Any, TypedDict, TYPE_CHECKING from exceptions import MinerException -from utils import json_load, json_save -from constants import IS_PACKAGED, LANG_PATH, DEFAULT_LANG +from utils import json_load +from constants import LANG_PATH, DEFAULT_LANG import json if TYPE_CHECKING: @@ -220,221 +220,6 @@ class Translation(TypedDict): with open(LANG_PATH.joinpath(f"{DEFAULT_LANG}.json"), 'r', encoding='utf-8') as file: default_translation: Translation = json.load(file) - - - - - - - -""" -default_translation: Translation = { - "english_name": "English", - "status": { - "terminated": "\nApplication Terminated.\nClose the window to exit the application.", - "watching": "Watching: {channel}", - "goes_online": "{channel} goes ONLINE, switching...", - "goes_offline": "{channel} goes OFFLINE, switching...", - "claimed_drop": "Claimed drop: {drop}", - "claimed_points": "Claimed bonus points: {points}", - "earned_points": "Earned points for watching: {points}, total: {balance}", - "no_channel": "No available channels to watch. Waiting for an ONLINE channel...", - "no_campaign": "No active campaigns to mine drops for. Waiting for an active campaign...", - }, - "login": { - "unexpected_content": ( - "Unexpected content type returned, usually due to being redirected. " - "Do you need to login for internet access?" - ), - "chrome": { - "startup": "Opening Chrome...", - "login_to_complete": ( - "Complete the login procedure manually by pressing the Login button again." - ), - "no_token": "No authorization token could be found.", - "closed_window": ( - "Chrome window was closed before the login procedure could complete." - ), - }, - "error_code": "Login error code: {error_code}", - "incorrect_login_pass": "Incorrect username or password.", - "incorrect_email_code": "Incorrect email code.", - "incorrect_twofa_code": "Incorrect 2FA code.", - "email_code_required": "Email code required. Check your email.", - "twofa_code_required": "2FA token required.", - }, - "error": { - "captcha": "Your login attempt was denied by CAPTCHA.\nPlease try again in 12+ hours.", - "site_down": "Twitch is down, retrying in {seconds} seconds...", - "no_connection": "Cannot connect to Twitch, retrying in {seconds} seconds...", - }, - "gui": { - "output": "Output", - "status": { - "name": "Status", - "idle": "Idle", - "exiting": "Exiting...", - "terminated": "Terminated", - "cleanup": "Cleaning up channels...", - "gathering": "Gathering channels...", - "switching": "Switching the channel...", - "fetching_inventory": "Fetching inventory...", - "fetching_campaigns": "Fetching campaigns...", - "adding_campaigns": "Adding campaigns to inventory... {counter}", - }, - "tabs": { - "main": "Main", - "inventory": "Inventory", - "settings": "Settings", - "help": "Help", - }, - "tray": { - "notification_title": "Mined Drop", - "minimize": "Minimize to Tray", - "show": "Show", - "quit": "Quit", - }, - "login": { - "name": "Login Form", - "labels": "Status:\nUser ID:", - "logged_in": "Logged in", - "logged_out": "Logged out", - "logging_in": "Logging in...", - "required": "Login required", - "request": "Please log in to continue.", - "username": "Username", - "password": "Password", - "twofa_code": "2FA code (optional)", - "button": "Login", - }, - "websocket": { - "name": "Websocket Status", - "websocket": "Websocket #{id}:", - "initializing": "Initializing...", - "connected": "Connected", - "disconnected": "Disconnected", - "connecting": "Connecting...", - "disconnecting": "Disconnecting...", - "reconnecting": "Reconnecting...", - }, - "progress": { - "name": "Campaign Progress", - "drop": "Drop:", - "game": "Game:", - "campaign": "Campaign:", - "remaining": "{time} remaining", - "drop_progress": "Progress:", - "campaign_progress": "Progress:", - }, - "channels": { - "name": "Channels", - "switch": "Switch", - "load_points": "Load Points", - "online": "ONLINE ✔", - "pending": "OFFLINE ⏳", - "offline": "OFFLINE ❌", - "headings": { - "channel": "Channel", - "status": "Status", - "game": "Game", - "viewers": "Viewers", - "points": "Points", - }, - }, - "inventory": { - "filter": { - "name": "Filter", - "show": "Show:", - "not_linked": "Not linked", - "upcoming": "Upcoming", - "expired": "Expired", - "excluded": "Excluded", - "finished": "Finished", - "refresh": "Refresh", - }, - "status": { - "linked": "Linked ✔", - "not_linked": "Not Linked ❌", - "active": "Active ✔", - "upcoming": "Upcoming ⏳", - "expired": "Expired ❌", - "claimed": "Claimed ✔", - "ready_to_claim": "Ready to claim ⏳", - }, - "starts": "Starts: {time}", - "ends": "Ends: {time}", - "allowed_channels": "Allowed Channels:", - "all_channels": "All", - "and_more": "and {amount} more...", - "percent_progress": "{percent} of {minutes} minutes", - "minutes_progress": "{minutes} minutes", - }, - "settings": { - "general": { - "name": "General", - "dark_theme": "Dark theme: ", - "autostart": "Autostart: ", - "tray": "Autostart into tray: ", - "tray_notifications": "Tray notifications: ", - "priority_only": "Priority Only: ", - "prioritize_by_ending_soonest": "Prioritize by ending soonest: ", - "proxy": "Proxy (requires restart):", - }, - "game_name": "Game name", - "priority": "Priority", - "exclude": "Exclude", - "reload": "Reload", - "reload_text": "Most changes require a reload to take an immediate effect: ", - }, - "help": { - "links": { - "name": "Useful Links", - "inventory": "See Twitch inventory", - "campaigns": "See all campaigns and manage account links", - }, - "how_it_works": "How It Works", - "how_it_works_text": ( - "Every ~20 seconds, the application asks Twitch for a URL to the raw stream data of the channel currently being watched. " - "It then fetches the metadata of this data stream - this is enough " - "to advance the drops. Note that this completely bypasses the need to download " - "any actual stream video and sound. " - "To keep the status (ONLINE or OFFLINE) of the channels up-to-date, " - "there's a websocket connection estabilished that receives events about streams " - "going up or down, or updates regarding the current amount of viewers." - ), - "getting_started": "Getting Started", - "getting_started_text": ( - "1. Login into the application.\n" - "2. Ensure your Twitch account is linked to all campaigns " - "you're interested in mining.\n" - "3. If you're interested in just mining everything, " - "uncheck \"Priority only\" and press on \"Reload\".\n" - "4. If you want to mine specific games first, use the \"Priority\" list " - "to setup an ordered list of games of your choice. Games from the top of the list " - "will be attempted to be mined first, before the ones lower down the list.\n" - "5. Keep the \"Priority only\" option checked, to avoid mining games " - "that are not on the priority list. Or not - it's up to you.\n" - "6. Use the \"Exclude\" list to tell the application " - "which games should never be mined.\n" - "7. Changing the contents of either of the lists, or changing the state " - "of the \"Priority only\" option, requires you to press on \"Reload\" " - "for the changes to take an effect." - ), - }, - }, -} -""" - - - - - - - - - - - class Translator: def __init__(self) -> None: self._langs: list[str] = [] From e00187f3d85d766b92739527a38c15bac2c29aa8 Mon Sep 17 00:00:00 2001 From: KK2-5 <120592920+KK2-5@users.noreply.github.com> Date: Sat, 1 Jun 2024 00:51:41 -0300 Subject: [PATCH 113/122] Update twitch.py Fix UnboundLocalError --- twitch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twitch.py b/twitch.py index d6ee64d8..9affacaa 100644 --- a/twitch.py +++ b/twitch.py @@ -1111,7 +1111,7 @@ async def _watch_loop(self) -> NoReturn: f"{drop.name} ({drop.campaign.game}, " f"{drop.current_minutes}/{drop.required_minutes})" ) - logger.log(CALL, f"Drop progress from active search: {drop_text}") + logger.log(CALL, f"Drop progress from active search: {drop_text}") else: logger.log(CALL, "No active drop could be determined") await self._watch_sleep(last_watch + interval - time()) From 1c1a950ab4f5f06e79e71e58efae9f6f58e9cb88 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 1 Jun 2024 13:10:02 +0200 Subject: [PATCH 114/122] fixed tray title exceeding 128 causing crash --- gui.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gui.py b/gui.py index d001bf59..addf2d44 100644 --- a/gui.py +++ b/gui.py @@ -1049,12 +1049,34 @@ def get_title(self, drop: TimedDrop | None) -> str: if drop is None: return self.TITLE campaign = drop.campaign - return ( + title = ( f"{self.TITLE}\n" f"{campaign.game.name}\n" f"{drop.rewards_text()} " f"{drop.progress:.1%} ({campaign.claimed_drops}/{campaign.total_drops})" ) + if len(title) > 128: # ValueError: string too long (x, maximum length 128) + min_length = 30 + diff = len(title) - 128 + if (len(drop.rewards_text()) - diff) >= min_length + 1: # If we can trim the drop name to 20 chars + new_length = len(drop.rewards_text()) - diff - 1 # Length - Diff - Ellipse (…) + title = ( + f"{self.TITLE}\n" + f"{campaign.game.name}\n" + f"{drop.rewards_text()[:new_length]}… " + f"{drop.progress:.1%} ({campaign.claimed_drops}/{campaign.total_drops})" + ) + else: # Trimming both + new_length = len(campaign.game.name) - (diff - len(drop.rewards_text()) + min_length + 1) - 1 # Campaign name - (Remaining diff from trimmed drop name) - Ellipse + title = ( + f"{self.TITLE}\n" + f"{campaign.game.name[:new_length]}…\n" + f"{drop.rewards_text()[:min_length]}… " + f"{drop.progress:.1%} ({campaign.claimed_drops}/{campaign.total_drops})" + ) + print(f"len after: {len(title)}") + print(title) + return title def _start(self): loop = asyncio.get_running_loop() From 9cda8cb2336560895290a75542536fda0d5d2a49 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 1 Jun 2024 13:31:14 +0200 Subject: [PATCH 115/122] attempt at fixing scrolling for linux --- gui.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gui.py b/gui.py index addf2d44..fb506237 100644 --- a/gui.py +++ b/gui.py @@ -1233,6 +1233,7 @@ def __init__(self, manager: GUIManager, master: ttk.Widget): ).grid(column=(icolumn := icolumn + 1), row=0) # Inventory view self._canvas = tk.Canvas(master, scrollregion=(0, 0, 0, 0)) + self._canvas.configure(scrollregion=self._canvas.bbox("all")) # Fix scrolling for linux self._canvas.grid(column=0, row=1, sticky="nsew") master.rowconfigure(1, weight=1) master.columnconfigure(0, weight=1) From 442bf89068af07e41df486314b1bf91452c985ec Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 1 Jun 2024 13:36:18 +0200 Subject: [PATCH 116/122] The scroll fix for linux didn't work --- gui.py | 1 - 1 file changed, 1 deletion(-) diff --git a/gui.py b/gui.py index fb506237..addf2d44 100644 --- a/gui.py +++ b/gui.py @@ -1233,7 +1233,6 @@ def __init__(self, manager: GUIManager, master: ttk.Widget): ).grid(column=(icolumn := icolumn + 1), row=0) # Inventory view self._canvas = tk.Canvas(master, scrollregion=(0, 0, 0, 0)) - self._canvas.configure(scrollregion=self._canvas.bbox("all")) # Fix scrolling for linux self._canvas.grid(column=0, row=1, sticky="nsew") master.rowconfigure(1, weight=1) master.columnconfigure(0, weight=1) From 6fa5e7fd508166a2ac45460c423b8e1f530427c4 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 1 Jun 2024 17:18:05 +0200 Subject: [PATCH 117/122] removed debug print statements --- gui.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/gui.py b/gui.py index addf2d44..bc86506e 100644 --- a/gui.py +++ b/gui.py @@ -1074,8 +1074,6 @@ def get_title(self, drop: TimedDrop | None) -> str: f"{drop.rewards_text()[:min_length]}… " f"{drop.progress:.1%} ({campaign.claimed_drops}/{campaign.total_drops})" ) - print(f"len after: {len(title)}") - print(title) return title def _start(self): From 8d2a34c752853b43f70af374661c10333f737345 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 1 Jun 2024 17:26:35 +0200 Subject: [PATCH 118/122] shorter taskbar title: allows 128, but shows 127 --- gui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui.py b/gui.py index bc86506e..dec6de56 100644 --- a/gui.py +++ b/gui.py @@ -1055,9 +1055,9 @@ def get_title(self, drop: TimedDrop | None) -> str: f"{drop.rewards_text()} " f"{drop.progress:.1%} ({campaign.claimed_drops}/{campaign.total_drops})" ) - if len(title) > 128: # ValueError: string too long (x, maximum length 128) + if len(title) > 127: # ValueError: string too long (x, maximum length 128), but it only shows 127 min_length = 30 - diff = len(title) - 128 + diff = len(title) - 127 if (len(drop.rewards_text()) - diff) >= min_length + 1: # If we can trim the drop name to 20 chars new_length = len(drop.rewards_text()) - diff - 1 # Length - Diff - Ellipse (…) title = ( From 2115fe986d4bd559e6e7447baa334f4d9f44e706 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sat, 1 Jun 2024 18:04:57 +0200 Subject: [PATCH 119/122] fixed comment spelling --- gui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui.py b/gui.py index dec6de56..72d825f7 100644 --- a/gui.py +++ b/gui.py @@ -1059,7 +1059,7 @@ def get_title(self, drop: TimedDrop | None) -> str: min_length = 30 diff = len(title) - 127 if (len(drop.rewards_text()) - diff) >= min_length + 1: # If we can trim the drop name to 20 chars - new_length = len(drop.rewards_text()) - diff - 1 # Length - Diff - Ellipse (…) + new_length = len(drop.rewards_text()) - diff - 1 # Length - Diff - Ellipsis (…) title = ( f"{self.TITLE}\n" f"{campaign.game.name}\n" @@ -1067,7 +1067,7 @@ def get_title(self, drop: TimedDrop | None) -> str: f"{drop.progress:.1%} ({campaign.claimed_drops}/{campaign.total_drops})" ) else: # Trimming both - new_length = len(campaign.game.name) - (diff - len(drop.rewards_text()) + min_length + 1) - 1 # Campaign name - (Remaining diff from trimmed drop name) - Ellipse + new_length = len(campaign.game.name) - (diff - len(drop.rewards_text()) + min_length + 1) - 1 # Campaign name - (Remaining diff from trimmed drop name) - Ellipsis title = ( f"{self.TITLE}\n" f"{campaign.game.name[:new_length]}…\n" From 679e4dafa7459707ae4e87b465fd39663ddfb304 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Mon, 3 Jun 2024 16:03:16 +0200 Subject: [PATCH 120/122] changed theme logic to use if-else, not of match --- gui.py | 173 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 86 insertions(+), 87 deletions(-) diff --git a/gui.py b/gui.py index 72d825f7..9afb401b 100644 --- a/gui.py +++ b/gui.py @@ -2049,7 +2049,7 @@ def __init__(self, twitch: Twitch): if self._twitch.settings.dark_theme: set_theme(root, self, "dark") else: - set_theme(root, self, "light") + set_theme(root, self, "default") # # https://stackoverflow.com/questions/56329342/tkinter-treeview-background-tag-not-working def _fixed_map(self, option): @@ -2208,92 +2208,91 @@ def configure_combobox_list(combobox, flag, value): combobox.tk.call(listbox, "configure", flag, value) # Style options, !!!"background" and "bg" is not interchangable for some reason!!! - match name: - case "dark": - bg_grey = "#181818" - active_grey = "#2b2b2b" - # General - style.theme_use('alt') # We have to switch the theme, because OS-defaults ("vista") don't support certain customisations, like Treeview-fieldbackground etc. - style.configure('.', background=bg_grey, foreground="white") - style.configure("Link.TLabel", font=link_font, foreground="#00aaff") - # Buttons - style.map("TButton", - background=[("active", active_grey)]) - # Tabs - style.configure("TNotebook.Tab", background=bg_grey) - style.map("TNotebook.Tab", - background=[("selected", active_grey)]) - # Checkboxes - style.configure("TCheckbutton", foreground="black") # The checkbox has to be white since it's an image, so the tick has to be black - style.map("TCheckbutton", - background=[('active', active_grey)]) - # Output field - manager.output._text.configure(bg=bg_grey, fg="white", selectbackground=active_grey) - # Include/Exclude lists - manager.settings._exclude_list.configure(bg=bg_grey, fg="white") - manager.settings._priority_list.configure(bg=bg_grey, fg="white") - # Channel list - style.configure('Treeview', background=bg_grey, fieldbackground=bg_grey) - manager.channels._table - # Inventory - manager.inv._canvas.configure(bg=bg_grey) - # Scroll bars - style.configure("TScrollbar", foreground="white", troughcolor=bg_grey, bordercolor=bg_grey, arrowcolor="white") - style.map("TScrollbar", - background=[("active", bg_grey), ("!active", bg_grey)]) - # Language selection box _select_menu - manager.settings._select_menu.configure(bg=bg_grey, fg="white", activebackground=active_grey, activeforeground="white") # Couldn't figure out how to change the border, so it stays black - for index in range(manager.settings._select_menu.menu.index("end")+1): - manager.settings._select_menu.menu.entryconfig(index, background=bg_grey, activebackground=active_grey, foreground="white") - # Proxy field - style.configure("TEntry", foreground="white", selectbackground=active_grey, fieldbackground=bg_grey) - # Include/Exclude box - style.configure("TCombobox", foreground="white", selectbackground=active_grey, fieldbackground=bg_grey, arrowcolor="white") - style.map("TCombobox", background=[("active", active_grey), ("disabled", bg_grey)]) - # Include list - configure_combobox_list(manager.settings._priority_entry, "-background", bg_grey) - configure_combobox_list(manager.settings._priority_entry, "-foreground", "white") - configure_combobox_list(manager.settings._priority_entry, "-selectbackground", active_grey) - # Exclude list - configure_combobox_list(manager.settings._exclude_entry, "-background", bg_grey) - configure_combobox_list(manager.settings._exclude_entry, "-foreground", "white") - configure_combobox_list(manager.settings._exclude_entry, "-selectbackground", active_grey) - - case "light" | "default" | _ : # When creating a new theme, additional values might need to be set, so the default theme remains consistent - # General - style.theme_use(set_theme.default_style) - style.configure('.', background="#f0f0f0", foreground="#000000") - # Buttons - style.map("TButton", - background=[("active", "#ffffff")]) - # Tabs - style.configure("TNotebook.Tab", background="#f0f0f0") - style.map("TNotebook.Tab", - background=[("selected", "#ffffff")]) - # Checkboxes don't need to be reverted - # Output field - manager.output._text.configure(bg="#ffffff", fg="#000000") - # Include/Exclude lists - manager.settings._exclude_list.configure(bg="#ffffff", fg="#000000") - manager.settings._priority_list.configure(bg="#ffffff", fg="#000000") - # Channel list doesn't need to be reverted - # Inventory - manager.inv._canvas.configure(bg="#f0f0f0") - # Scroll bars don't need to be reverted - # Language selection box _select_menu - manager.settings._select_menu.configure(bg="#ffffff", fg="black", activebackground="#f0f0f0", activeforeground="black") # Couldn't figure out how to change the border, so it stays black - for index in range(manager.settings._select_menu.menu.index("end")+1): - manager.settings._select_menu.menu.entryconfig(index, background="#f0f0f0", activebackground="#0078d7", foreground="black") - # Proxy field doesn't need to be reverted - # Include/Exclude dropdown - Only the lists have to be reverted - # Include list - configure_combobox_list(manager.settings._priority_entry, "-background", "white") - configure_combobox_list(manager.settings._priority_entry, "-foreground", "black") - configure_combobox_list(manager.settings._priority_entry, "-selectbackground", "#0078d7") - # Exclude list - configure_combobox_list(manager.settings._exclude_entry, "-background", "white") - configure_combobox_list(manager.settings._exclude_entry, "-foreground", "black") - configure_combobox_list(manager.settings._exclude_entry, "-selectbackground", "#0078d7") + if name == "dark": + bg_grey = "#181818" + active_grey = "#2b2b2b" + # General + style.theme_use('alt') # We have to switch the theme, because OS-defaults ("vista") don't support certain customisations, like Treeview-fieldbackground etc. + style.configure('.', background=bg_grey, foreground="white") + style.configure("Link.TLabel", font=link_font, foreground="#00aaff") + # Buttons + style.map("TButton", + background=[("active", active_grey)]) + # Tabs + style.configure("TNotebook.Tab", background=bg_grey) + style.map("TNotebook.Tab", + background=[("selected", active_grey)]) + # Checkboxes + style.configure("TCheckbutton", foreground="black") # The checkbox has to be white since it's an image, so the tick has to be black + style.map("TCheckbutton", + background=[('active', active_grey)]) + # Output field + manager.output._text.configure(bg=bg_grey, fg="white", selectbackground=active_grey) + # Include/Exclude lists + manager.settings._exclude_list.configure(bg=bg_grey, fg="white") + manager.settings._priority_list.configure(bg=bg_grey, fg="white") + # Channel list + style.configure('Treeview', background=bg_grey, fieldbackground=bg_grey) + manager.channels._table + # Inventory + manager.inv._canvas.configure(bg=bg_grey) + # Scroll bars + style.configure("TScrollbar", foreground="white", troughcolor=bg_grey, bordercolor=bg_grey, arrowcolor="white") + style.map("TScrollbar", + background=[("active", bg_grey), ("!active", bg_grey)]) + # Language selection box _select_menu + manager.settings._select_menu.configure(bg=bg_grey, fg="white", activebackground=active_grey, activeforeground="white") # Couldn't figure out how to change the border, so it stays black + for index in range(manager.settings._select_menu.menu.index("end")+1): + manager.settings._select_menu.menu.entryconfig(index, background=bg_grey, activebackground=active_grey, foreground="white") + # Proxy field + style.configure("TEntry", foreground="white", selectbackground=active_grey, fieldbackground=bg_grey) + # Include/Exclude box + style.configure("TCombobox", foreground="white", selectbackground=active_grey, fieldbackground=bg_grey, arrowcolor="white") + style.map("TCombobox", background=[("active", active_grey), ("disabled", bg_grey)]) + # Include list + configure_combobox_list(manager.settings._priority_entry, "-background", bg_grey) + configure_combobox_list(manager.settings._priority_entry, "-foreground", "white") + configure_combobox_list(manager.settings._priority_entry, "-selectbackground", active_grey) + # Exclude list + configure_combobox_list(manager.settings._exclude_entry, "-background", bg_grey) + configure_combobox_list(manager.settings._exclude_entry, "-foreground", "white") + configure_combobox_list(manager.settings._exclude_entry, "-selectbackground", active_grey) + + else: # When creating a new theme, additional values might need to be set, so the default theme remains consistent + # General + style.theme_use(set_theme.default_style) + style.configure('.', background="#f0f0f0", foreground="#000000") + # Buttons + style.map("TButton", + background=[("active", "#ffffff")]) + # Tabs + style.configure("TNotebook.Tab", background="#f0f0f0") + style.map("TNotebook.Tab", + background=[("selected", "#ffffff")]) + # Checkboxes don't need to be reverted + # Output field + manager.output._text.configure(bg="#ffffff", fg="#000000") + # Include/Exclude lists + manager.settings._exclude_list.configure(bg="#ffffff", fg="#000000") + manager.settings._priority_list.configure(bg="#ffffff", fg="#000000") + # Channel list doesn't need to be reverted + # Inventory + manager.inv._canvas.configure(bg="#f0f0f0") + # Scroll bars don't need to be reverted + # Language selection box _select_menu + manager.settings._select_menu.configure(bg="#ffffff", fg="black", activebackground="#f0f0f0", activeforeground="black") # Couldn't figure out how to change the border, so it stays black + for index in range(manager.settings._select_menu.menu.index("end")+1): + manager.settings._select_menu.menu.entryconfig(index, background="#f0f0f0", activebackground="#0078d7", foreground="black") + # Proxy field doesn't need to be reverted + # Include/Exclude dropdown - Only the lists have to be reverted + # Include list + configure_combobox_list(manager.settings._priority_entry, "-background", "white") + configure_combobox_list(manager.settings._priority_entry, "-foreground", "black") + configure_combobox_list(manager.settings._priority_entry, "-selectbackground", "#0078d7") + # Exclude list + configure_combobox_list(manager.settings._exclude_entry, "-background", "white") + configure_combobox_list(manager.settings._exclude_entry, "-foreground", "black") + configure_combobox_list(manager.settings._exclude_entry, "-selectbackground", "#0078d7") ################### From 1db7ce68a7e6a70470c6ba88992b205de4ec9fd9 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Mon, 3 Jun 2024 16:22:47 +0200 Subject: [PATCH 121/122] remove unnecessary can_earn_within_next_hour() --- inventory.py | 4 ---- twitch.py | 9 ++++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/inventory.py b/inventory.py index eb1f048e..c830ccd9 100644 --- a/inventory.py +++ b/inventory.py @@ -354,7 +354,3 @@ def can_earn_within(self, stamp: datetime) -> bool: and self.starts_at < stamp and any(drop.can_earn_within(stamp) for drop in self.drops) ) - - def can_earn_within_next_hour(self): - next_hour = datetime.now(timezone.utc) + timedelta(hours=1) - return self.can_earn_within(next_hour) diff --git a/twitch.py b/twitch.py index 9affacaa..505cd59d 100644 --- a/twitch.py +++ b/twitch.py @@ -898,10 +898,11 @@ async def _run(self): # NOTE: we use another set so that we can set them online separately no_acl: set[Game] = set() acl_channels: OrderedSet[Channel] = OrderedSet() + next_hour = datetime.now(timezone.utc) + timedelta(hours=1) for campaign in self.inventory: if ( campaign.game in self.wanted_games - and campaign.can_earn_within_next_hour() + and campaign.can_earn_within(next_hour) ): if campaign.allowed_channels: acl_channels.update(campaign.allowed_channels) @@ -1623,13 +1624,14 @@ def filter_campaigns(self, campaign: list[DropsCampaign]): priority = self.settings.priority priority_only = self.settings.priority_only game = campaign.game + next_hour = datetime.now(timezone.utc) + timedelta(hours=1) if ( game not in self.wanted_games # isn't already there and game.name not in exclude # and isn't excluded # and isn't excluded by priority_only and (not priority_only or game.name in priority) # and can be progressed within the next hour - and campaign.can_earn_within_next_hour() + and campaign.can_earn_within(next_hour) ): return True return False @@ -1680,12 +1682,13 @@ async def fetch_inventory(self) -> None: self.gui.inv.clear() self.inventory.clear() switch_triggers: set[datetime] = set() + next_hour = datetime.now(timezone.utc) + timedelta(hours=1) for i, campaign in enumerate(campaigns, start=1): status_update( _("gui", "status", "adding_campaigns").format(counter=f"({i}/{len(campaigns)})") ) self._drops.update({drop.id: drop for drop in campaign.drops}) - if campaign.can_earn_within_next_hour(): + if campaign.can_earn_within(next_hour): switch_triggers.update(campaign.time_triggers) # NOTE: this fetches pictures from the CDN, so might be slow without a cache await self.gui.inv.add_campaign(campaign) From 87b3128d80cf625b923a15ed93b9132d7205ff9a Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Wed, 5 Jun 2024 17:32:28 +0200 Subject: [PATCH 122/122] updated patch notes for next release --- patch_notes.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/patch_notes.txt b/patch_notes.txt index 15a4e16d..d9c35b31 100644 --- a/patch_notes.txt +++ b/patch_notes.txt @@ -1,5 +1,9 @@ ## v15.6.0 +1.6.2024 +- Fixed bug where long cmapaign names caused a crash when trying to update tray description +- Fixed `UnboundLocalError` crash due to wrong indentation + 30.5.2024 - updated **Arabic**, **Turkish**, **Simplified Chinese** and **English** translation as well as corresponding credits