From 2f235adadfbb45cbb70ccf62779a664f003eba25 Mon Sep 17 00:00:00 2001 From: TheFrenchGhosty Date: Tue, 2 Nov 2021 18:58:22 +0100 Subject: [PATCH 01/17] Enhance some stuff in the README --- README.md | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 8beb4380..5c8367c7 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@
Invidious logo -

Invidious

+

Invidious

License: AGPLv3 Build Status + + + GitHub commits GitHub issues @@ -14,6 +17,9 @@ GitHub pull requests + + GitHub stars + Translation Status @@ -23,13 +29,15 @@

An open source alternative front-end to YouTube

+ Website +  •  Instances list  •  - Documentation + Documentation  •  Contribute  •  - Donate + Donate
Chat with us:
@@ -133,18 +141,7 @@ Weblate also allows you to log-in with major SSO providers like Github, Gitlab, - [CloudTube](https://sr.ht/~cadence/tube/): A JavaScript-rich alternate YouTube player. - [PeerTubeify](https://gitlab.com/Cha_deL/peertubeify): On YouTube, displays a link to the same video on PeerTube, if it exists. - [MusicPiped](https://github.com/deep-gaurav/MusicPiped): A material design music player that streams music from YouTube. -- [HoloPlay](https://github.com/stephane-r/HoloPlay): Funny Android application connecting on Invidious API's with search, playlists and favoris. - - -## Donate - -Bitcoin (BTC): [bc1qfhe7rq3lqzuayzjxzyt9waz9ytrs09kla3tsgr](bitcoin:bc1qfhe7rq3lqzuayzjxzyt9waz9ytrs09kla3tsgr) - -Monero (XMR): [41nMCtek197boJtiUvGnTFYMatrLEpnpkQDmUECqx5Es2uX3sTKKWVhSL76suXsG3LXqkEJBrCZBgPTwJrDp1FrZJfycGPR](monero:41nMCtek197boJtiUvGnTFYMatrLEpnpkQDmUECqx5Es2uX3sTKKWVhSL76suXsG3LXqkEJBrCZBgPTwJrDp1FrZJfycGPR) - -Ethereum (ETH): [0xD1F7E3Bfb19Ee5a52baED396Ad34717aF18d995B](ethereum:0xD1F7E3Bfb19Ee5a52baED396Ad34717aF18d995B) - -Litecoin (LTC): [ltc1q8787aq2xrseq5yx52axx8c4fqks88zj5vr0zx9](litecoin:ltc1q8787aq2xrseq5yx52axx8c4fqks88zj5vr0zx9) +- [HoloPlay](https://github.com/stephane-r/HoloPlay): Funny Android application connecting on Invidious API's with search, playlists and favorites. ## Liability From 19bb26a789c24bed153c9575277b4d80b320cc59 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Mon, 15 Nov 2021 23:08:48 +0100 Subject: [PATCH 02/17] Add a makefile --- Makefile | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..c14dfc6e --- /dev/null +++ b/Makefile @@ -0,0 +1,118 @@ +# ----------------------- +# Compilation options +# ----------------------- + +RELEASE := 1 +STATIC := 0 + +DISABLE_LSQUIC := 0 +NO_DBG_SYMBOLS := 0 + + +FLAGS ?= + + +ifeq ($(RELEASE), 1) + FLAGS += --release +endif + +ifeq ($(STATIC), 1) + FLAGS += --static +endif + + +ifeq ($(NO_DBG_SYMBOLS), 1) + FLAGS += --no-debug +else + FLAGS += --debug +endif + +ifeq ($(DISABLE_LSQUIC), 1) + FLAGS += -Ddisable_lsquic +endif + + +# ----------------------- +# Main +# ----------------------- + +all: invidious + +get-libs: + shards install --production + +# TODO: add support for ARM64 via cross-compilation +invidious: get-libs + crystal build src/invidious.cr $(FLAGS) --progress --stats --error-trace + + +run: invidious + ./invidious + + +# ----------------------- +# Development +# ----------------------- + + +format: + crystal tool format + +test: + crystal spec + +verify: + crystal build src/invidious.cr --no-codegen --progress --stats --error-trace + + +# ----------------------- +# (Un)Install +# ----------------------- + +# TODO + + +# ----------------------- +# Cleaning +# ----------------------- + +clean: + rm invidious + +distclean: clean + rm -rf libs + + +# ----------------------- +# Help page +# ----------------------- + +help: + echo "Targets available in this Makefile:" + echo "" + echo "get-libs Fetch Crystal libraries" + echo "invidious Build Invidious" + echo "run Launch Invidious" + echo "" + echo "format Run the Crystal formatter" + echo "test Run tests" + echo "verify Just make sure that the code compiles, but without" + echo " generating any binaries. Useful to search for errors" + echo "" + echo "clean Remove build artifacts" + echo "distclean Remove build artifacts and libraries" + echo "" + echo "" + echo "Build options available for this Makefile:" + echo "" + echo "RELEASE Make a release build (Default: 1)" + echo "STATIC Link librariess tatically (Default: 1)" + echo "" + echo "DISABLE_LSQUIC Don't use lsquic (Default: 0)" + echo "NO_DBG_SYMBOLS Strip debug symbols (Default: 0)" + + + +# No targets generates an output named after themselves +.PHONY all get-libs build amd64 run +.PHONY format test verify clean distclean help From 6a204753c03ae4743d5355110c54ba42b2faee72 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Mon, 15 Nov 2021 23:36:52 +0100 Subject: [PATCH 03/17] Fix typo --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c14dfc6e..7271d9bd 100644 --- a/Makefile +++ b/Makefile @@ -114,5 +114,5 @@ help: # No targets generates an output named after themselves -.PHONY all get-libs build amd64 run -.PHONY format test verify clean distclean help +.PHONY: all get-libs build amd64 run +.PHONY: format test verify clean distclean help From 2eac23a0b37082eebbfa1436c2e6200210b6e0a9 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Tue, 16 Nov 2021 13:24:13 +0100 Subject: [PATCH 04/17] Temporary fix for #2612 Don't rely on the auto compression/decompression provided by the crystal stdlib. --- src/invidious/yt_backend/youtube_api.cr | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index 27f25036..0403cb56 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -404,19 +404,10 @@ module YoutubeAPI url = "#{endpoint}?key=#{client_config.api_key}" headers = HTTP::Headers{ - "Content-Type" => "application/json; charset=UTF-8", + "Content-Type" => "application/json; charset=UTF-8", + "Accept-Encoding" => "gzip, deflate", } - # The normal HTTP client automatically applies accept-encoding: gzip, - # and decompresses. However, explicitly applying it will remove this functionality. - # - # https://github.com/crystal-lang/crystal/issues/11252#issuecomment-929594741 - {% unless flag?(:disable_quic) %} - if CONFIG.use_quic - headers["Accept-Encoding"] = "gzip" - end - {% end %} - # Logging LOGGER.debug("YoutubeAPI: Using endpoint: \"#{endpoint}\"") LOGGER.trace("YoutubeAPI: ClientConfig: #{client_config}") @@ -434,8 +425,23 @@ module YoutubeAPI ) end + # Decompress the body ourselves, given that auto-decompress is + # broken in the Crystal stdlib. + # Read more: + # - https://github.com/iv-org/invidious/issues/2612 + # - https://github.com/crystal-lang/crystal/issues/11354 + # + case headers["Content-Encoding"]? + when "gzip" + body = Compress::Gzip::Reader.new(response.body_io, sync_close: true) + when "deflate" + body = Compress::Deflate::Reader.new(response.body_io, sync_close: true) + else + body = response.body + end + # Convert result to Hash - initial_data = JSON.parse(response.body).as_h + initial_data = JSON.parse(body).as_h # Error handling if initial_data.has_key?("error") From dad8f9a0ce576ce3e938fbaa578d12179ca63553 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Tue, 16 Nov 2021 20:39:26 +0100 Subject: [PATCH 05/17] Fix typo Should be checking the returned headers, not the sent ones. --- src/invidious/yt_backend/youtube_api.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index 0403cb56..4973e4de 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -431,7 +431,7 @@ module YoutubeAPI # - https://github.com/iv-org/invidious/issues/2612 # - https://github.com/crystal-lang/crystal/issues/11354 # - case headers["Content-Encoding"]? + case response.headers["Content-Encoding"]? when "gzip" body = Compress::Gzip::Reader.new(response.body_io, sync_close: true) when "deflate" From 2c447a42f29a05b8067444338248e344b3705cd0 Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Tue, 16 Nov 2021 21:40:35 +0100 Subject: [PATCH 06/17] Make sure to only apply fix if QUIC is disabled --- src/invidious/yt_backend/youtube_api.cr | 28 ++++++++++++++----------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index 4973e4de..b26af8d1 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -425,19 +425,23 @@ module YoutubeAPI ) end - # Decompress the body ourselves, given that auto-decompress is - # broken in the Crystal stdlib. - # Read more: - # - https://github.com/iv-org/invidious/issues/2612 - # - https://github.com/crystal-lang/crystal/issues/11354 - # - case response.headers["Content-Encoding"]? - when "gzip" - body = Compress::Gzip::Reader.new(response.body_io, sync_close: true) - when "deflate" - body = Compress::Deflate::Reader.new(response.body_io, sync_close: true) - else + if {{ !flag?(:disable_quic) }} && CONFIG.use_quic body = response.body + else + # Decompress the body ourselves, when using HTTP::Client given that + # auto-decompress is broken in the Crystal stdlib. + # Read more: + # - https://github.com/iv-org/invidious/issues/2612 + # - https://github.com/crystal-lang/crystal/issues/11354 + # + case response.headers["Content-Encoding"]? + when "gzip" + body = Compress::Gzip::Reader.new(response.body_io, sync_close: true) + when "deflate" + body = Compress::Deflate::Reader.new(response.body_io, sync_close: true) + else + body = response.body + end end # Convert result to Hash From 319587e2f11abe53c507d2363ca551d8321b203f Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Sun, 21 Nov 2021 17:34:17 +0100 Subject: [PATCH 07/17] extract_video_info: make sure that the Android player response is valid --- src/invidious/videos.cr | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index d3e5800c..4406284f 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -857,8 +857,16 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_ else client_config.client_type = YoutubeAPI::ClientType::Android end - stream_data = YoutubeAPI.player(video_id: video_id, params: "", client_config: client_config) - params["streamingData"] = stream_data["streamingData"]? || JSON::Any.new("") + android_player = YoutubeAPI.player(video_id: video_id, params: "", client_config: client_config) + + # Sometime, the video is available from the web client, but not on Android, so check + # that here, and fallback to the streaming data from the web client if needed. + # See: https://github.com/iv-org/invidious/issues/2549 + if android_player["playabilityStatus"]["status"] == "OK" + params["streamingData"] = android_player["streamingData"]? || JSON::Any.new("") + else + params["streamingData"] = player_response["streamingData"]? || JSON::Any.new("") + end end {"captions", "microformat", "playabilityStatus", "storyboards", "videoDetails"}.each do |f| From ba48f68fc30990437331791848efe896559f49cd Mon Sep 17 00:00:00 2001 From: Samantaz Fox Date: Sun, 21 Nov 2021 18:16:05 +0100 Subject: [PATCH 08/17] allow multiple, successive content-encodings --- src/invidious/yt_backend/youtube_api.cr | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index b26af8d1..977aea04 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -434,11 +434,22 @@ module YoutubeAPI # - https://github.com/iv-org/invidious/issues/2612 # - https://github.com/crystal-lang/crystal/issues/11354 # - case response.headers["Content-Encoding"]? - when "gzip" - body = Compress::Gzip::Reader.new(response.body_io, sync_close: true) - when "deflate" - body = Compress::Deflate::Reader.new(response.body_io, sync_close: true) + if encodings = response.headers["Content-Encoding"]? + io = response.body_io + + # Multiple encodings can be combined, and are listed in the order + # in which they were applied. E.g: "deflate, gzip" means that the + # content must be first "gunzipped", then "defated". + encodings.split(',').reverse.each do |enc| + case enc.strip(' ') + when "gzip" + io = Compress::Gzip::Reader.new(io, sync_close: true) + when "deflate" + io = Compress::Deflate::Reader.new(io, sync_close: true) + end + end + + body = io.gets_to_end else body = response.body end From 2d8964d37d2cb2ac71fc74010282b884df58a188 Mon Sep 17 00:00:00 2001 From: TheFrenchGhosty Date: Fri, 26 Nov 2021 19:51:55 +0100 Subject: [PATCH 09/17] Apply the suggestions --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 5c8367c7..35f9745c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
Invidious logo -

Invidious

+

Invidious

License: AGPLv3 @@ -17,9 +17,6 @@ GitHub pull requests - - GitHub stars - Translation Status From de153ece4eb887768514f45bf201b373fe40d2df Mon Sep 17 00:00:00 2001 From: TheFrenchGhosty Date: Fri, 26 Nov 2021 19:52:36 +0100 Subject: [PATCH 10/17] Move the Awesome-Humane-Tech to its own line --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 35f9745c..3a330274 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Translation Status + Awesome Humane Tech From 5eca7a8a30ff93dfa771056c8ad26f47c447763d Mon Sep 17 00:00:00 2001 From: TheFrenchGhosty <47571719+TheFrenchGhosty@users.noreply.github.com> Date: Fri, 26 Nov 2021 19:18:12 +0000 Subject: [PATCH 11/17] Fix indenting Co-authored-by: Samantaz Fox --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a330274..29b8397a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Build Status - + GitHub commits From 325a67155d1737bd28d77bb8e840b8a10179cc59 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 26 Nov 2021 20:24:47 +0100 Subject: [PATCH 12/17] Update Catalan translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update Catalan translation Add Catalan translation Co-authored-by: Alfonso Montero López Co-authored-by: Hosted Weblate --- locales/ca.json | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 locales/ca.json diff --git a/locales/ca.json b/locales/ca.json new file mode 100644 index 00000000..1fa7cc1f --- /dev/null +++ b/locales/ca.json @@ -0,0 +1,103 @@ +{ + "oldest": "més antic", + "Yes": "Sí", + "preferences_quality_label": "Qualitat de vídeo preferida: ", + "newest": "més nou", + "No": "No", + "Google verification code": "Codi de verificació de Google", + "User ID": "ID d'usuari", + "Preferences": "Preferències", + "Dark mode: ": "Mode fosc: ", + "dark": "fosc", + "light": "clar", + "published": "publicat", + "published - reverse": "publicat - invers", + "alphabetically": "alfabèticament", + "alphabetically - reverse": "alfabèticament - invers", + "channel name - reverse": "nom del canal - invers", + "preferences_category_data": "Preferències de dades", + "Delete account": "Elimina compte", + "Save preferences": "Guarda preferències", + "Private": "Privat", + "Show more": "Mostra'n més", + "Show less": "Mostra'n menys", + "Hide replies": "Amaga respostes", + "Arabic": "Àrab", + "Armenian": "Armeni", + "Basque": "Basc", + "Filipino": "Filipí", + "Finnish": "Finès", + "German": "Alemany", + "Greek": "Grec", + "Hungarian": "Hongarès", + "Icelandic": "Islandès", + "Italian": "Italià", + "Japanese": "Japonès", + "Korean": "Coreà", + "Kurdish": "Kurd", + "Lithuanian": "Lituà", + "Luxembourgish": "Luxemburguès", + "Macedonian": "Macedoni", + "Polish": "Polonès", + "Portuguese": "Portuguès", + "Romanian": "Romanès", + "Russian": "Rus", + "Serbian": "Serbi", + "Spanish (Latin America)": "Castellà (Amèrica llatina)", + "Turkish": "Turc", + "Ukrainian": "Ucraïnès", + "preferences_locale_label": "Idioma: ", + "Gaming": "Jocs", + "Movies": "Películes", + "Download": "Descarrega", + "Download as: ": "Descarrega com: ", + "Videos": "Vídeos", + "content_type": "Tipus", + "duration": "Duració", + "sort": "Ordena per", + "week": "Aquesta setmana", + "month": "Aquest mes", + "year": "Aquest any", + "video": "Vídeo", + "channel": "Canal", + "short": "Curt (< 4 minuts)", + "long": "Llarg (> 20 minuts)", + "Current version: ": "Versió actual: ", + "Malay": "Malai", + "Persian": "Persa", + "Slovak": "Eslovac", + "Search": "Busca", + "Show annotations": "Mostra anotacions", + "preferences_region_label": "País del contingut: ", + "preferences_sort_label": "Ordena vídeos per: ", + "Import/export": "Importa/exporta", + "channel name": "nom del canal", + "Title": "Títol", + "Belarusian": "Bielorús", + "Enable web notifications": "Activa notificacions web", + "search": "busca", + "Catalan": "Català", + "Croatian": "Croat", + "preferences_category_admin": "Preferències d'administrador", + "Hide annotations": "Amaga anotacions", + "Show replies": "Mostra respostes", + "Bulgarian": "Búlgar", + "Albanian": "Albanès", + "French": "Francès", + "Irish": "Irlandès", + "Maltese": "Maltès", + "Danish": "Danès", + "Galician": "Gallec", + "Hebrew": "Hebreu", + "Indonesian": "Indonesi", + "Spanish": "Castellà", + "Vietnamese": "Vietnamita", + "News": "Notícies", + "show": "Mostra", + "footer_documentation": "Documentació", + "Thai": "Tailandès", + "Music": "Música", + "relevance": "Rellevància", + "hour": "Última hora", + "today": "Avui" +} From 33431844b7f7864a1824557c87cb27a6eb35c855 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 26 Nov 2021 20:24:48 +0100 Subject: [PATCH 13/17] Update French translation Co-authored-by: Bundy01 --- locales/fr.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/locales/fr.json b/locales/fr.json index 2332594a..00971576 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -423,5 +423,15 @@ "Current version: ": "Version actuelle : ", "next_steps_error_message": "Vous pouvez essayer de : ", "next_steps_error_message_refresh": "Rafraîchir la page", - "next_steps_error_message_go_to_youtube": "Aller sur YouTube" + "next_steps_error_message_go_to_youtube": "Aller sur YouTube", + "preferences_quality_dash_label": "Qualité préférée de la vidéo du tableau de bord : ", + "footer_source_code": "Code source", + "preferences_region_label": "Pays du contenu : ", + "footer_donate_page": "Faire un don", + "footer_modfied_source_code": "Code source modifié", + "short": "Courte (< 4 minutes)", + "long": "Longue (> 20 minutes)", + "adminprefs_modified_source_code_url_label": "URL du dépôt du code source modifié", + "footer_documentation": "Documentation", + "footer_original_source_code": "Code source original" } From 65b5183f01a37e688232ca349931bba8d198c21f Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 26 Nov 2021 20:24:48 +0100 Subject: [PATCH 14/17] Update Portuguese (Brazil) translation Co-authored-by: Hosted Weblate Co-authored-by: Vinicius --- locales/pt-BR.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/pt-BR.json b/locales/pt-BR.json index 072deff2..6baa2c0d 100644 --- a/locales/pt-BR.json +++ b/locales/pt-BR.json @@ -431,5 +431,7 @@ "footer_documentation": "Documentação", "footer_source_code": "Código fonte", "footer_original_source_code": "Código fonte original", - "footer_modfied_source_code": "Código Fonte Modificado" + "footer_modfied_source_code": "Código Fonte Modificado", + "preferences_quality_dash_label": "Qualidade de vídeo do painel preferida: ", + "preferences_region_label": "País do conteúdo: " } From b030d822f1f555de3917fc13de9a7ca32d835178 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 26 Nov 2021 20:24:48 +0100 Subject: [PATCH 15/17] Update Serbian translation Co-authored-by: Anon Anonimovic Co-authored-by: Hosted Weblate --- locales/sr.json | 371 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 369 insertions(+), 2 deletions(-) diff --git a/locales/sr.json b/locales/sr.json index 0082bd66..e0713b43 100644 --- a/locales/sr.json +++ b/locales/sr.json @@ -19,7 +19,7 @@ "View playlist on YouTube": "Погледај списак извођења на YouTube-у", "newest": "најновије", "oldest": "најстарије", - "popular": "гласовито", + "popular": "популарно", "last": "последње", "Next page": "Следећа страница", "Previous page": "Претходна страница", @@ -66,5 +66,372 @@ "preferences_continue_label": "Увек подразумевано пуштај следеће: ", "preferences_continue_autoplay_label": "Самопуштање следећег видео записа: ", "preferences_listen_label": "Увек подразумевано укључен само звук: ", - "preferences_local_label": "Приказ видео записа преко посредника: " + "preferences_local_label": "Приказ видео записа преко посредника: ", + "Playlist privacy": "Подешавања приватности плеј листе", + "Editing playlist `x`": "Измена плеј листе `x`", + "Please sign in using 'Log in with Google'": "Молимо Вас да се пријавите помоћу 'Log in with Google'", + "Playlist does not exist.": "Непостојећа плеј листа.", + "Erroneous challenge": "Погрешан изазов", + "Maltese": "Малтешки", + "Download": "Преузми", + "Download as: ": "Преузми као: ", + "Quota exceeded, try again in a few hours": "Квота је премашена, молимо Вас да покушате за пар сати", + "Bangla": "Бангла/Бенгалски", + "preferences_quality_dash_label": "Преферирани квалитет dash видео формата: ", + "Token manager": "Меначер токена", + "Token": "Токен", + "`x` tokens": { + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` токен", + "": "`x` токена" + }, + "Import/export": "Увези/Извези", + "revoke": "опозови", + "`x` unseen notifications": { + "": "`x` непрегледаних обавештења", + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` непрегледаних обавештења" + }, + "search": "претрага", + "Log out": "Одјава", + "Source available here.": "Изворни код.", + "Trending": "У тренду", + "Updated `x` ago": "Ажурирано пре `x`", + "Delete playlist `x`?": "Обриши плеј листу `x`?", + "Create playlist": "Направи плеј листу", + "Show less": "Прикажи мање", + "Switch Invidious Instance": "Промени Invidious инстанцу", + "Hide annotations": "Сакриј напомене", + "User ID is a required field": "Кориснички ID је обавезно поље", + "Wrong username or password": "Погрешно корисничко име или лозинка", + "Please log in": "Молимо Вас да се пријавите", + "channel:`x`": "канал:`x`", + "Could not fetch comments": "Узимање коментара није успело", + "`x` points": { + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` поен", + "": "`x` поена" + }, + "Could not create mix.": "Прављење микса није успело.", + "Empty playlist": "Празна плеј листа", + "Not a playlist.": "Није плеј листа.", + "Could not pull trending pages.": "Учитавање 'У току' странције није успело.", + "Token is expired, please try again": "Токен је истекао, молимо Вас да покушате поново", + "English (auto-generated)": "Енглески (аутоматски генерисано)", + "Afrikaans": "Африканс", + "Albanian": "Албански", + "Armenian": "Јерменски", + "Azerbaijani": "Азербејџански", + "Basque": "Баскијски", + "Bosnian": "Српски (Босна и Херцеговина)", + "Bulgarian": "Бугарски", + "Burmese": "Бурмански", + "Catalan": "Каталонски", + "Cebuano": "Cebuano", + "Chinese (Traditional)": "Кинески (Традиционални)", + "Corsican": "Корзикански", + "Danish": "Дански", + "Kannada": "Канада (Језик)", + "Kazakh": "Казашки", + "Russian": "Руски", + "Scottish Gaelic": "Шкотски Гелски", + "Sinhala": "Синхалешки", + "Slovak": "Словачки", + "Spanish": "Шпански", + "Spanish (Latin America)": "Шпански (Јужна Америка)", + "Sundanese": "Сундски", + "Swedish": "Шведски", + "Tajik": "Таџички", + "Telugu": "Телугу", + "Turkish": "Турски", + "Ukrainian": "Украјински", + "Urdu": "Урду", + "Uzbek": "Узбечки", + "Vietnamese": "Вијетнамски", + "`x` minutes": { + "": "`x` минута", + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` минут" + }, + "`x` seconds": { + "": "`x` секунди", + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` секунда" + }, + "Rating: ": "Оцена/е: ", + "View as playlist": "Погледај као плеј листу", + "Default": "Подразумеван/о", + "Gaming": "Гејминг", + "Movies": "Филмови", + "%A %B %-d, %Y": "%A %B %-d, %Y", + "(edited)": "(измењено)", + "YouTube comment permalink": "YouTube коментар трајна веза", + "Audio mode": "Аудио мод", + "Playlists": "Плеј листе", + "relevance": "Ревелантно", + "rating": "Оцене", + "date": "Датум отпремања", + "views": "Број прегледа", + "`x` marked it with a ❤": "`x` је означио/ла ово са ❤", + "duration": "Трајање", + "features": "Карактеристике", + "hour": "Последњи сат", + "week": "Ове недеље", + "month": "Овај месец", + "year": "Ове године", + "video": "Видео", + "playlist": "Плеј листа", + "movie": "Филм", + "long": "Дуг (> 20 минута)", + "hd": "HD", + "creative_commons": "Creative Commons (Лиценца)", + "3d": "3Д", + "hdr": "Видео високе резолуције", + "filter": "Филтер", + "next_steps_error_message": "Можете урадити нешта од следећег: ", + "next_steps_error_message_go_to_youtube": "Иди на YouTube", + "footer_documentation": "Документација", + "preferences_region_label": "Држава порекла садржаја: ", + "preferences_player_style_label": "Стил плејера: ", + "preferences_dark_mode_label": "Изглед/Тема: ", + "light": "светла", + "preferences_thin_mode_label": "Компактни режим: ", + "preferences_category_misc": "Остала подешавања", + "preferences_automatic_instance_redirect_label": "Аутоматско пребацивање на другу инстанцу у случају отказивања (пређи на redirect.invidious.io): ", + "alphabetically - reverse": "по алфабету - обрнуто", + "Enable web notifications": "Омогући обавештења у веб претраживачу", + "`x` is live": "`x` преноси уживо", + "Manage tokens": "Управљај токенима", + "Watch history": "Историја гледања", + "preferences_feed_menu_label": "Feed мени: ", + "preferences_show_nick_label": "Прикажи надимке на врху: ", + "CAPTCHA enabled: ": "CAPTCHA омогућена: ", + "Registration enabled: ": "Регистрација омогућена: ", + "Subscription manager": "Менаџер претплата", + "Wilson score: ": "Wilson скор: ", + "Engagement: ": "Ангажовање: ", + "Whitelisted regions: ": "Дозвољени региони: ", + "Shared `x`": "Подељено `x`", + "`x` views": { + "": "`x` прегледа", + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` преглед" + }, + "Premieres in `x`": "Премијера у `x`", + "Premieres `x`": "Премијере у `x`", + "Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.": "Хеј! Изгледа да сте онемогућили JavaScript. Кликните овде да видите коментаре, имајте на уму да ово може да потраје дуже док се не учитају.", + "View `x` comments": { + "([^.,0-9]|^)1([^.,0-9]|$)": "Прикажи `x` коментар", + "": "Прикажи `x` коментара" + }, + "View Reddit comments": "Прикажи Reddit коментаре", + "Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.": "Неуспешна пријава, проверите да ли сте упалили двофакторну аутентикацију (Аутентикатор или СМС).", + "CAPTCHA is a required field": "CAPTCHA је обавезно поље", + "Croatian": "Хрватски", + "Estonian": "Естонски", + "Filipino": "Филипино", + "French": "Француски", + "Galician": "Галицијски", + "German": "Немачки", + "Greek": "Грчки", + "Hausa": "Хауса", + "Italian": "Италијански", + "Khmer": "Кмерски", + "Kurdish": "Курдски", + "Kyrgyz": "Киргиски", + "Latvian": "Летонски", + "Lithuanian": "Литвански", + "Macedonian": "Македонски", + "Malagasy": "Малгашки", + "Malay": "Малајски", + "Marathi": "Маратхи", + "Mongolian": "Монголски", + "Norwegian Bokmål": "Норвешки Бокмал", + "Nyanja": "Чева", + "Pashto": "Паштунски", + "Persian": "Персијски", + "Punjabi": "Пунџаби", + "Romanian": "Румунски", + "Welsh": "Велшки", + "Western Frisian": "Западнофризијски", + "`x` years": { + "": "`x` година", + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` година" + }, + "`x` weeks": { + "": "`x` недеља", + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` недеља" + }, + "`x` days": { + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` дан", + "": "`x` дана" + }, + "`x` hours": { + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` сат", + "": "`x` сати" + }, + "Fallback comments: ": "Коментари у случају отказивања: ", + "Popular": "Популарно", + "Search": "Претрага", + "About": "О програму", + "footer_source_code": "Изворни Код", + "footer_original_source_code": "Оригинални изворни код", + "preferences_related_videos_label": "Прикажи сличне видео клипове: ", + "preferences_annotations_label": "Прикажи напомене подразумевано: ", + "preferences_extend_desc_label": "Аутоматски прикажи цео опис видеа: ", + "preferences_vr_mode_label": "Интерактивни видео клипови у 360 степени: ", + "preferences_category_visual": "Визуелне преференце", + "preferences_captions_label": "Подразумевани титл: ", + "Music": "Музика", + "content_type": "Тип", + "Broken? Try another Invidious Instance": "Не функционише исправно? Пробајте другу Invidious инстанцу", + "Tamil": "Тамилски", + "Save preferences": "Сачувај подешавања", + "Only show latest unwatched video from channel: ": "Прикажи само последње видео клипове који нису погледани са канала: ", + "Xhosa": "Коса (Језик)", + "channel": "Канал", + "Hungarian": "Мађарски", + "Maori": "Маори (Језик)", + "Manage subscriptions": "Управљај претплатама", + "Hindi": "Хинди", + "`x` ago": "пре `x`", + "Import/export data": "Увези/Извези податке", + "`x` uploaded a video": "`x` је отпремио/ла видео клип", + "View `x` replies": { + "([^.,0-9]|^)1([^.,0-9]|$)": "Погледај `x` одоговор", + "": "Погледај `x` одоговора" + }, + "Delete account": "Обриши налог", + "preferences_default_home_label": "Подразумевана почетна страница: ", + "Serbian": "Српски", + "License: ": "Лиценца: ", + "live": "Уживо", + "Report statistics: ": "Извештавај о статистици: ", + "Only show latest video from channel: ": "Приказуј последње видео клипове само са канала: ", + "channel name - reverse": "име канала - обрнуто", + "Could not get channel info.": "Узимање података о каналу није успело.", + "View privacy policy.": "Погледај политику приватности.", + "Change password": "Промени лозинку", + "Malayalam": "Малајалам", + "View more comments on Reddit": "Прикажи више коментара на Reddit-у", + "Portuguese": "Португалски", + "View YouTube comments": "Прикажи YouTube коментаре", + "published - reverse": "објављено - обрнуто", + "Dutch": "Белгијски", + "preferences_volume_label": "Јачина звука: ", + "preferences_locale_label": "Језик: ", + "`x` subscriptions": { + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` пратиоц", + "": "`x` пратилаца" + }, + "adminprefs_modified_source_code_url_label": "URL веза до репозиторијума са измењеним изворним кодом", + "Community": "Заједница", + "Video mode": "Видео мод", + "Fallback captions: ": "Титл у случају да главни није доступан: ", + "Private": "Приватно", + "alphabetically": "по алфабету", + "No such user": "Непостојећи корисник", + "Subscriptions": "Праћења", + "today": "Данас", + "Finnish": "Фински", + "Lao": "Лаоски", + "Login enabled: ": "Пријава омогућена: ", + "Shona": "Шона", + "location": "Локација", + "Load more": "Учитај више", + "Released under the AGPLv3 on Github.": "Избачено под лиценцом AGPLv3 на Github-у.", + "Slovenian": "Словеначки", + "View JavaScript license information.": "Погледај информације лиценце везане за JavaScript.", + "Chinese (Simplified)": "Кинески (Поједностављени)", + "preferences_comments_label": "Подразумевани коментари: ", + "Incorrect password": "Нетачна лозинка", + "Show replies": "Прикажи одговоре", + "Invidious Private Feed for `x`": "Invidious приватни Feed за `x`", + "Watch on YouTube": "Гледај на YouTube-у", + "Wrong answer": "Погрешан одговор", + "preferences_quality_label": "Преферирани видео квалитет: ", + "Hide replies": "Сакриј одговоре", + "Invalid TFA code": "Неважећи TFA код", + "Login failed. This may be because two-factor authentication is not turned on for your account.": "Неуспешна пријава! Ово се можда дешава јер двофакторна аутентикација није омогућена на Вашем налогу.", + "Erroneous CAPTCHA": "Погрешна CAPTCHA", + "Erroneous token": "Погрешан токен", + "Czech": "Чешки", + "Latin": "Латински", + "Videos": "Видео клипови", + "4k": "4К", + "footer_donate_page": "Донирај", + "English": "Енглески", + "Arabic": "Арапски", + "Unlisted": "Ненаведено", + "Hidden field \"challenge\" is a required field": "Сакривено \"challenge\" поље је обавезно", + "Hidden field \"token\" is a required field": "Сакривено \"token\" поље је обавезно", + "Georgian": "Грузијски", + "Hawaiian": "Хавајски", + "Hebrew": "Хебрејски", + "Icelandic": "Исландски", + "Igbo": "Игбо", + "Japanese": "Јапански", + "Javanese": "Јавански", + "Sindhi": "Синди", + "Swahili": "Свахили", + "Yiddish": "Јидиш", + "Zulu": "Зулу", + "subtitles": "Титл", + "Password cannot be longer than 55 characters": "Лозинка не може бити дужа од 55 карактера", + "This channel does not exist.": "Овај канал не постоји.", + "Belarusian": "Белоруски", + "Gujarati": "Гуџарати", + "Haitian Creole": "Хаићански Креолски", + "Somali": "Сомалијски", + "Top": "Врх", + "footer_modfied_source_code": "Измењени изворни код", + "preferences_category_subscription": "Подешавања праћења", + "preferences_annotations_subscribed_label": "Подразумевано приказати напомене за канале које пратите? ", + "preferences_max_results_label": "Број видео клипова приказаних у листи (feed-у): ", + "preferences_sort_label": "Сортирај видео клипове по: ", + "preferences_unseen_only_label": "Прикажи само видео клипове који нису погледани: ", + "preferences_notifications_only_label": "Прикажи само обавештења (ако их уопште има): ", + "preferences_category_data": "Подешавања података", + "Clear watch history": "Обриши историју гледања", + "preferences_category_admin": "Администраторска подешавања", + "published": "објављено", + "sort": "Сортирај према", + "show": "Шоу", + "short": "Кратак (< 4 минута)", + "Current version: ": "Тренутна верзија: ", + "Top enabled: ": "Врх омогућен: ", + "Public": "Јавно", + "Delete playlist": "Обриши плеј листу", + "Title": "Наслов", + "Show annotations": "Прикажи напомене", + "Password cannot be empty": "Лозинка не може бити празна", + "Deleted or invalid channel": "Обрисан или непостојећи канал", + "Esperanto": "Есперанто", + "Hmong": "Хмонг", + "Luxembourgish": "Луксембуршки", + "Nepali": "Непалски", + "Samoan": "Самоански", + "News": "Вести", + "permalink": "трајна веза", + "Password is a required field": "Лозинка је обавезно поље", + "Amharic": "Амхарски", + "Indonesian": "Индонежански", + "Irish": "Ирски", + "Korean": "Корејски", + "Southern Sotho": "Сото", + "Thai": "Тајски", + "`x` months": { + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` месец", + "": "`x` месеци" + }, + "preferences_speed_label": "Подразумевана брзина: ", + "Dark mode: ": "Тамни режим: ", + "dark": "тамна", + "Redirect homepage to feed: ": "Пребаци са почетне странице на листу (feed): ", + "channel name": "име канала", + "View all playlists": "Прегледај све плеј листе", + "Show more": "Прикажи више", + "Genre: ": "Жанр: ", + "Family friendly? ": "Погодно за породицу? ", + "next_steps_error_message_refresh": "Освежи страницу", + "youtube": "YouTube", + "reddit": "Reddit", + "unsubscribe": "прекини са праћењем", + "Blacklisted regions: ": "Блокирани региони: ", + "Polish": "Пољски", + "Yoruba": "Јоруба" } From 2ca23c714d0dc0fa0ff83b03d7531c70a0352140 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 26 Nov 2021 20:24:48 +0100 Subject: [PATCH 16/17] Update Indonesian translation Co-authored-by: Hosted Weblate Co-authored-by: I. Musthafa --- locales/id.json | 70 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/locales/id.json b/locales/id.json index ca4c1e0f..054a2557 100644 --- a/locales/id.json +++ b/locales/id.json @@ -14,7 +14,7 @@ "LIVE": "SIARAN LANGSUNG", "Shared `x` ago": "Dibagikan `x` yang lalu", "Unsubscribe": "Batal Langganan", - "Subscribe": "Berangganan", + "Subscribe": "Berlangganan", "View channel on YouTube": "Lihat kanal di YouTube", "View playlist on YouTube": "Lihat daftar putar di YouTube", "newest": "terbaru", @@ -209,7 +209,7 @@ "Please log in": "Harap masuk", "Invidious Private Feed for `x`": "Umpan pribadi Invidious untuk`x`", "channel:`x`": "kanal:`x`", - "Deleted or invalid channel": "Kanal terhapus atau invalid", + "Deleted or invalid channel": "Kanal terhapus atau tidak valid", "This channel does not exist.": "Kanal ini tidak ada.", "Could not get channel info.": "Tidak bisa mendapatkan info kanal.", "Could not fetch comments": "Tidak dapat memuat komentar", @@ -220,8 +220,8 @@ "`x` ago": "`x` lalu", "Load more": "Muat lebih banyak", "`x` points": { - "([^.,0-9]|^)1([^.,0-9]|$)": "`x` titik", - "": "`x` titik" + "([^.,0-9]|^)1([^.,0-9]|$)": "`x` poin", + "": "`x` poin" }, "Could not create mix.": "Tidak dapat membuat mix.", "Empty playlist": "Daftar putar kosong", @@ -372,10 +372,10 @@ "Popular": "Populer", "Search": "Cari", "Top": "Teratas", - "About": "Ihwal", - "Rating: ": "Peringkat: ", + "About": "Tentang", + "Rating: ": "Rating: ", "preferences_locale_label": "Bahasa: ", - "View as playlist": "Tampilkan sebagai daftar putar", + "View as playlist": "Lihat sebagai daftar putar", "Default": "Baku", "Music": "Musik", "Gaming": "Permainan", @@ -385,7 +385,7 @@ "Download as: ": "Unduh sebagai: ", "%A %B %-d, %Y": "%A %B %-d, %Y", "(edited)": "(disunting)", - "YouTube comment permalink": "Komentar YouTube permalink", + "YouTube comment permalink": "Tautan permanen komentar YouTube", "permalink": "tautan permanen", "`x` marked it with a ❤": "`x` telah ditandai dengan ❤", "Audio mode": "Mode audio", @@ -393,33 +393,33 @@ "Videos": "Video", "Playlists": "Daftar putar", "Community": "Komunitas", - "relevance": "Relevan", - "rating": "peringkat", - "date": "tanggal", - "views": "ditonton", - "content_type": "tipe_konten", - "duration": "durasi", - "features": "fitur", - "sort": "urut", - "hour": "jam", - "today": "hari ini", - "week": "minggu", - "month": "bulan", - "year": "tahun", - "video": "video", - "channel": "kanal", - "playlist": "daftar putar", - "movie": "film", - "show": "tampilkan", - "hd": "hd", - "subtitles": "subtitel", - "creative_commons": "creative_commons", - "3d": "3d", - "live": "siaran langsung", - "4k": "4k", - "location": "lokasi", - "hdr": "hdr", - "filter": "saring", + "relevance": "Relevansi", + "rating": "Rating", + "date": "Tanggal unggah", + "views": "Jumlah ditonton", + "content_type": "Tipe", + "duration": "Durasi", + "features": "Fitur", + "sort": "Urut Berdasarkan", + "hour": "Jam Terakhir", + "today": "Hari Ini", + "week": "Pekan Ini", + "month": "Bulan Ini", + "year": "Tahun Ini", + "video": "Video", + "channel": "Kanal", + "playlist": "Daftar Putar", + "movie": "Film", + "show": "Pertunjukan/Acara", + "hd": "HD", + "subtitles": "Takarir", + "creative_commons": "Creative Commons", + "3d": "3D", + "live": "Siaran Langsung", + "4k": "4K", + "location": "Lokasi", + "hdr": "HDR", + "filter": "Saring", "Current version: ": "Versi saat ini: ", "next_steps_error_message": "Setelah itu Anda harus mencoba: ", "next_steps_error_message_refresh": "Segarkan", From c6e086c6fff9699a32465da0ce5e4784c981e886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milien=20Devos?= Date: Sun, 28 Nov 2021 08:41:16 +0000 Subject: [PATCH 17/17] Revert "Temporarily fix for #2612" (#2673) --- src/invidious/yt_backend/youtube_api.cr | 45 +++++++------------------ 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/src/invidious/yt_backend/youtube_api.cr b/src/invidious/yt_backend/youtube_api.cr index 977aea04..27f25036 100644 --- a/src/invidious/yt_backend/youtube_api.cr +++ b/src/invidious/yt_backend/youtube_api.cr @@ -404,10 +404,19 @@ module YoutubeAPI url = "#{endpoint}?key=#{client_config.api_key}" headers = HTTP::Headers{ - "Content-Type" => "application/json; charset=UTF-8", - "Accept-Encoding" => "gzip, deflate", + "Content-Type" => "application/json; charset=UTF-8", } + # The normal HTTP client automatically applies accept-encoding: gzip, + # and decompresses. However, explicitly applying it will remove this functionality. + # + # https://github.com/crystal-lang/crystal/issues/11252#issuecomment-929594741 + {% unless flag?(:disable_quic) %} + if CONFIG.use_quic + headers["Accept-Encoding"] = "gzip" + end + {% end %} + # Logging LOGGER.debug("YoutubeAPI: Using endpoint: \"#{endpoint}\"") LOGGER.trace("YoutubeAPI: ClientConfig: #{client_config}") @@ -425,38 +434,8 @@ module YoutubeAPI ) end - if {{ !flag?(:disable_quic) }} && CONFIG.use_quic - body = response.body - else - # Decompress the body ourselves, when using HTTP::Client given that - # auto-decompress is broken in the Crystal stdlib. - # Read more: - # - https://github.com/iv-org/invidious/issues/2612 - # - https://github.com/crystal-lang/crystal/issues/11354 - # - if encodings = response.headers["Content-Encoding"]? - io = response.body_io - - # Multiple encodings can be combined, and are listed in the order - # in which they were applied. E.g: "deflate, gzip" means that the - # content must be first "gunzipped", then "defated". - encodings.split(',').reverse.each do |enc| - case enc.strip(' ') - when "gzip" - io = Compress::Gzip::Reader.new(io, sync_close: true) - when "deflate" - io = Compress::Deflate::Reader.new(io, sync_close: true) - end - end - - body = io.gets_to_end - else - body = response.body - end - end - # Convert result to Hash - initial_data = JSON.parse(body).as_h + initial_data = JSON.parse(response.body).as_h # Error handling if initial_data.has_key?("error")