From 95fa970fc1f11e2e8ac8cf5137b545b77f6cf0f9 Mon Sep 17 00:00:00 2001 From: Arne Weber Date: Sun, 26 May 2024 00:01:12 +0200 Subject: [PATCH 01/39] 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 02/39] 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 03/39] 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 04/39] 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 05/39] 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 06/39] =?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 07/39] =?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 08/39] =?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 09/39] =?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 10/39] =?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 11/39] 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 12/39] 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 13/39] 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 14/39] 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 15/39] 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 16/39] 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 17/39] =?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 18/39] 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 19/39] 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 20/39] 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 21/39] 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 22/39] 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 23/39] 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 24/39] 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 25/39] 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 26/39] 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 27/39] 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 28/39] 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 29/39] 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 30/39] 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 31/39] 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 32/39] 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 33/39] 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 34/39] 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 35/39] 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 36/39] 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 37/39] 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 38/39] 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 39/39] 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