From fc4a2b812e5e66b92fdfacd348afb908d2744c72 Mon Sep 17 00:00:00 2001 From: Adam Crowder Date: Sat, 29 Dec 2018 04:25:07 -0800 Subject: [PATCH 001/108] update readme for required ubuntu dependencies --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1746704..34a5dbbd 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ $ crystal build src/invidious.cr --release # Install dependencies $ curl -sSL https://dist.crystal-lang.org/apt/setup.sh | sudo bash $ sudo apt update -$ sudo apt install crystal libssl-dev libxml2-dev libyaml-dev libgmp-dev libreadline-dev librsvg2-dev postgresql imagemagick +$ sudo apt install crystal libssl-dev libxml2-dev libyaml-dev libgmp-dev libreadline-dev librsvg2-dev postgresql imagemagick libsqlite3-dev # Setup PostgreSQL $ sudo systemctl enable postgresql From 7951d4c8aa271d8123a2ab3b8aface9ebb2c6aa4 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 2 Jan 2019 14:20:57 -0600 Subject: [PATCH 002/108] Add length_seconds to subscription search --- src/invidious.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious.cr b/src/invidious.cr index 6688e4a0..58dcd81f 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -633,7 +633,7 @@ get "/search" do |env| count, videos = channel_search(search_query, page, channel) elsif subscriptions if view_name - videos = PG_DB.query_all("SELECT id,title,published,updated,ucid,author FROM ( + videos = PG_DB.query_all("SELECT id,title,published,updated,ucid,author,length_seconds FROM ( SELECT *, to_tsvector(#{view_name}.title) || to_tsvector(#{view_name}.author) From c2c224b16f9ee11e5bebeed8901aedbc0e15bfae Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 2 Jan 2019 19:28:01 -0600 Subject: [PATCH 003/108] Use fibers to try to speed up importing of channels --- src/invidious.cr | 37 +++++-------------------------------- src/invidious/channels.cr | 27 +++++++++++++++++++++++++++ src/invidious/users.cr | 17 +++++++---------- 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 58dcd81f..4be9ee7e 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -1355,7 +1355,7 @@ get "/subscription_manager" do |env| subscriptions = [] of InvidiousChannel user.subscriptions.each do |ucid| begin - subscriptions << get_channel(ucid, PG_DB, false) + subscriptions << get_channel(ucid, PG_DB, false, false) rescue ex next end @@ -1475,14 +1475,7 @@ post "/data_control" do |env| end user.subscriptions.uniq! - user.subscriptions.select! do |ucid| - begin - get_channel(ucid, PG_DB, false, false) - true - rescue ex - false - end - end + user.subscriptions = get_batch_channels(user.subscriptions, PG_DB, false, false) PG_DB.exec("UPDATE users SET subscriptions = $1 WHERE email = $2", user.subscriptions, user.email) when "import_freetube" @@ -1491,14 +1484,7 @@ post "/data_control" do |env| end user.subscriptions.uniq! - user.subscriptions.select! do |ucid| - begin - get_channel(ucid, PG_DB, false, false) - true - rescue ex - false - end - end + user.subscriptions = get_batch_channels(user.subscriptions, PG_DB, false, false) PG_DB.exec("UPDATE users SET subscriptions = $1 WHERE email = $2", user.subscriptions, user.email) when "import_newpipe_subscriptions" @@ -1508,13 +1494,7 @@ post "/data_control" do |env| end user.subscriptions.uniq! - user.subscriptions.each do |ucid| - begin - get_channel(ucid, PG_DB, false, false) - rescue ex - next - end - end + user.subscriptions = get_batch_channels(user.subscriptions, PG_DB, false, false) PG_DB.exec("UPDATE users SET subscriptions = $1 WHERE email = $2", user.subscriptions, user.email) when "import_newpipe" @@ -1533,14 +1513,7 @@ post "/data_control" do |env| user.subscriptions += db.query_all("SELECT url FROM subscriptions", as: String).map { |url| url.lchop("https://www.youtube.com/channel/") } user.subscriptions.uniq! - user.subscriptions.select! do |ucid| - begin - get_channel(ucid, PG_DB, false, false) - true - rescue ex - false - end - end + user.subscriptions = get_batch_channels(user.subscriptions, PG_DB, false, false) PG_DB.exec("UPDATE users SET subscriptions = $1 WHERE email = $2", user.subscriptions, user.email) diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr index ba17ff07..c1915a10 100644 --- a/src/invidious/channels.cr +++ b/src/invidious/channels.cr @@ -21,6 +21,33 @@ class ChannelVideo }) end +def get_batch_channels(channels, db, refresh = false, pull_all_videos = true, max_threads = 10) + active_threads = 0 + active_channel = Channel(String | Nil).new + + final = [] of String + channels.map do |ucid| + if active_threads >= max_threads + if response = active_channel.receive + active_threads -= 1 + final << response + end + end + + active_threads += 1 + spawn do + begin + get_channel(ucid, db, refresh, pull_all_videos) + active_channel.send(ucid) + rescue ex + active_channel.send(nil) + end + end + end + + return final +end + def get_channel(id, db, refresh = true, pull_all_videos = true) client = make_client(YT_URL) diff --git a/src/invidious/users.cr b/src/invidious/users.cr index 38799a74..dbbe87f8 100644 --- a/src/invidious/users.cr +++ b/src/invidious/users.cr @@ -177,19 +177,16 @@ def fetch_user(sid, headers, db) feed = XML.parse_html(feed.body) channels = [] of String - feed.xpath_nodes(%q(//ul[@id="guide-channels"]/li/a)).each do |channel| - if !{"Popular on YouTube", "Music", "Sports", "Gaming"}.includes? channel["title"] - channel_id = channel["href"].lstrip("/channel/") - - begin - channel = get_channel(channel_id, db, false, false) - channels << channel.id - rescue ex - next - end + channels = feed.xpath_nodes(%q(//ul[@id="guide-channels"]/li/a)).compact_map do |channel| + if {"Popular on YouTube", "Music", "Sports", "Gaming"}.includes? channel["title"] + nil + else + channel["href"].lstrip("/channel/") end end + channels = get_batch_channels(channels, db, false, false) + email = feed.xpath_node(%q(//a[@class="yt-masthead-picker-header yt-masthead-picker-active-account"])) if email email = email.content.strip From 0832fa9bdb81d81f55ab981d39ca5f5e6ae01db2 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 2 Jan 2019 20:09:00 -0600 Subject: [PATCH 004/108] Filter paid videos from RSS and channel list --- src/invidious.cr | 2 ++ src/invidious/helpers/helpers.cr | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 4be9ee7e..1d85a0bf 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -1909,6 +1909,7 @@ get "/feed/channel/:ucid" do |env| page = 1 videos, count = get_60_videos(ucid, page, auto_generated) + videos.select! { |video| !video.paid } host_url = make_host_url(Kemal.config.ssl || CONFIG.https_only, env.request.headers["Host"]?) path = env.request.path @@ -2173,6 +2174,7 @@ get "/channel/:ucid" do |env| end videos, count = get_60_videos(ucid, page, auto_generated, sort_by) + videos.select! { |video| !video.paid } templated "channel" end diff --git a/src/invidious/helpers/helpers.cr b/src/invidious/helpers/helpers.cr index 94250a21..4af924c0 100644 --- a/src/invidious/helpers/helpers.cr +++ b/src/invidious/helpers/helpers.cr @@ -317,10 +317,10 @@ def extract_items(nodeset, ucid = nil) premium = false end - if node.xpath_node(%q(.//span[contains(text(), "Get YouTube Premium")])) - paid = true - else + if !premium || node.xpath_node(%q(.//span[contains(text(), "Free episode")])) paid = false + else + paid = true end items << SearchVideo.new( From 2fdf3d24e3443da9888b7fc4ddd33d4072edcdcb Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 2 Jan 2019 20:14:31 -0600 Subject: [PATCH 005/108] Redirect to home page on empty search --- src/invidious.cr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/invidious.cr b/src/invidious.cr index 1d85a0bf..ba47fab4 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -588,6 +588,10 @@ get "/search" do |env| query ||= env.params.query["q"]? query ||= "" + if query.empty? + next env.redirect "/" + end + page = env.params.query["page"]?.try &.to_i? page ||= 1 From a1d442d1e3589d1f973472071dda9855347da263 Mon Sep 17 00:00:00 2001 From: dimqua Date: Wed, 26 Dec 2018 16:18:39 +0000 Subject: [PATCH 006/108] Update Russian translation --- locales/ru.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/locales/ru.json b/locales/ru.json index f52fc034..e7b659b7 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -102,7 +102,7 @@ "Watch video on Youtube": "Смотреть на YouTube", "Genre: ": "Жанр: ", "License: ": "Лицензия: ", - "Family friendly? ": "Для семейного просмотра: ", + "Family friendly? ": "Семейный просмотр: ", "Wilson score: ": "Рейтинг Вильсона: ", "Engagement: ": "Вовлеченность: ", "Whitelisted regions: ": "Доступно для: ", @@ -145,9 +145,9 @@ "Invalid playlist.": "Некорректный плейлист.", "Playlist does not exist.": "Плейлист не существует.", "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".", - "Hidden field \"challenge\" is a required field": "", + "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"", "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"", - "Invalid challenge": "", + "Invalid challenge": "Неправильный ответ в \"challenge\"", "Invalid token": "Неправильный токен", "Invalid user": "Недопустимое имя пользователя", "Token is expired, please try again": "Срок действия токена истек, попробуйте позже", @@ -257,17 +257,17 @@ "Yiddish": "", "Yoruba": "", "Zulu": "", - "`x` years": "`x` `y`", - "`x` months": "`x` месяц`y`", - "`x` weeks": "`x` недел`y`", - "`x` days": "`x` д`y`", - "`x` hours": "`x` час`y`", - "`x` minutes": "`x` минут`y`", - "`x` seconds": "`x` секунд`y`", + "`x` years": "`x` лет", + "`x` months": "`x` месяцев", + "`x` weeks": "`x` недель", + "`x` days": "`x` дней", + "`x` hours": "`x` часов", + "`x` minutes": "`x` минут", + "`x` seconds": "`x` секунд", "Fallback comments: ": "Резервные комментарии: ", "Popular": "Популярное", "Top": "Топ", - "About": "", + "About": "О сайте", "Rating: ": "Рейтинг: ", "Language: ": "Язык: " } From cc00beb1db7b122d4ec32a43bd2d16afb61c107b Mon Sep 17 00:00:00 2001 From: kniddl Date: Sat, 29 Dec 2018 17:28:43 +0000 Subject: [PATCH 007/108] Update German translation --- locales/de.json | 542 ++++++++++++++++++++++++------------------------ 1 file changed, 271 insertions(+), 271 deletions(-) diff --git a/locales/de.json b/locales/de.json index d069581c..039b1564 100644 --- a/locales/de.json +++ b/locales/de.json @@ -1,273 +1,273 @@ { - "`x` subscribers": "`x` Abonenten", - "`x` videos": "`x` Videos", - "LIVE": "LIVE", - "Shared `x` ago": "Vor `x` geteilt", - "Unsubscribe": "Abbestellen", - "Subscribe": "Abbonieren", - "Login to subscribe to `x`": "Einloggen um `x` zu abonnieren", - "View channel on YouTube": "Kanal auf YouTube anzeigen", - "newest": "neueste", - "oldest": "älteste", - "popular": "beliebt", - "Preview page": "Vorschau Seite", - "Next page": "Nächste Seite", - "Clear watch history?": "Verlauf löschen?", - "Yes": "Ja", - "No": "Nein", - "Import and Export Data": "Import und Export Daten", - "Import": "Importieren", - "Import Invidious data": "Invidious Daten importieren", - "Import YouTube subscriptions": "YouTube Abonnements importieren", - "Import FreeTube subscriptions (.db)": "FreeTube Abonnements importieren (.db)", - "Import NewPipe subscriptions (.json)": "NewPipe Abonnements importieren (.json)", - "Import NewPipe data (.zip)": "NewPipe Daten importieren (.zip)", - "Export": "Exportieren", - "Export subscriptions as OPML": "Abonnements als OPML exportieren", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportieren (für NewPipe & FreeTube)", - "Export data as JSON": "Daten als JSON exportieren", - "Delete account?": "Account löschen?", - "History": "Verlauf", - "Previous page": "Vorherige Seite", - "An alternative front-end to YouTube": "Eine alternative Oberfläche für YouTube", - "JavaScript license information": "JavaScript Lizenzinformationen", - "source": "Quelle", - "Login": "Einloggen", - "Login/Register": "Einloggen/Registrieren", - "Login to Google": "In Google einloggen", - "User ID:": "Benutzer ID:", - "Password:": "Passwort:", - "Time (h:mm:ss):": "Zeit (h:mm:ss):", - "Text CAPTCHA": "Text CAPTCHA", - "Image CAPTCHA": "Image CAPTCHA", - "Sign In": "Einloggen", - "Register": "Registrieren", - "Email:": "Email:", - "Google verification code:": "Google Bestätigungscode:", - "Preferences": "Einstellungen", - "Player preferences": "Playereinstellungen", - "Always loop: ": "Immer wiederholen: ", - "Autoplay: ": "Automatisch abspielen: ", - "Autoplay next video: ": "nächstes Video automatisch abspielen: ", - "Listen by default: ": "Nur Ton als Standard: ", - "Default speed: ": "Standardgeschwindigkeit: ", - "Preferred video quality: ": "Bevorzugte Videoqualität: ", - "Player volume: ": "Playerlautstärke: ", - "Default comments: ": "Standardkommentare: ", - "youtube": "youtube", - "reddit": "reddit", - "Default captions: ": "Standarduntertitel: ", - "Fallback captions: ": "Ersatzuntertitel: ", - "Show related videos? ": "Ähnliche Videos anzeigen? ", - "Visual preferences": "Anzeigeeinstellungen", - "Dark mode: ": "Nachtmodus: ", - "Thin mode: ": "Schlanker Modus: ", - "Subscription preferences": "Abonnementeinstellungen", - "Redirect homepage to feed: ": "Startseite zu Feed umleiten: ", - "Number of videos shown in feed: ": "Anzahl von Videos die im Feed angezeigt werden: ", - "Sort videos by: ": "Videos sortieren nach: ", - "published": "veröffentlicht", - "published - reverse": "veröffentlicht - invertiert", - "alphabetically": "alphabetisch", - "alphabetically - reverse": "alphabetisch - invertiert", - "channel name": "Kanalname", - "channel name - reverse": "Kanalname - invertiert", - "Only show latest video from channel: ": "Nur neueste Videos des Kanals anzeigen: ", - "Only show latest unwatched video from channel: ": "Nur neueste ungesehene Videos des Kanals anzeigen: ", - "Only show unwatched: ": "Nur ungesehene anzeigen: ", - "Only show notifications (if there are any): ": "Nur Benachrichtigungen anzeigen (wenn es welche gibt): ", - "Data preferences": "Dateneinstellungen", - "Clear watch history": "Verlauf löschen", - "Import/Export data": "Daten im- exportieren", - "Manage subscriptions": "Abonnements verwalten", - "Watch history": "Verlauf", - "Delete account": "Account löschen", - "Save preferences": "Einstellungen speichern", - "Subscription manager": "Abonnementverwaltung", - "`x` subscriptions": "`x` Abonnements", - "Import/Export": "Importieren/Exportieren", - "unsubscribe": "abbestellen", - "Subscriptions": "Abonnements", - "`x` unseen notifications": "`x` ungesehene Benachrichtigungen", - "search": "Suchen", - "Sign out": "Abmelden", - "Released under the AGPLv3 by Omar Roth.": "Veröffentlicht unter AGPLv3 von Omar Roth.", - "Source available here.": "Quellcode verfügbar hier.", - "Liberapay: ": "Liberapay: ", - "Patreon: ": "Patreon: ", - "BTC: ": "BTC: ", - "BCH: ": "BCH: ", - "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.", - "Trending": "Trending", - "Watch video on Youtube": "Video auf Youtube ansehen", - "Genre: ": "Genre: ", - "License: ": "Lizenz: ", - "Family friendly? ": "Familienfreundlich? ", - "Wilson score: ": "Wilson-Score: ", - "Engagement: ": "Engagement: ", - "Whitelisted regions: ": "Erlaubte Regionen: ", - "Blacklisted regions: ": "Unerlaubte Regionen: ", - "Shared `x`": "Geteilt `x`", - "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.", - "View YouTube comments": "YouTube Kommentare anzeigen", - "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen", - "View `x` comments": "`x` Kommentare anzeigen", - "View Reddit comments": "Reddit Kommentare anzeigen", - "Hide replies": "Antworten verstecken", - "Show replies": "Antworten anzeigen", - "Incorrect password": "Falsches Passwort", - "Quota exceeded, try again in a few hours": "Kontingent überschritten, versuche es in ein paar Stunden erneut", - "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Login nicht möglich, stellen Sie sicher dass two-factor Authentifikation (Authentifizierung oder SMS) aktiviert ist.", - "Invalid TFA code": "Ungültiger TFA Code", - "Login failed. This may be because two-factor authentication is not enabled on your account.": "Login fehlgeschlagen. Das kann daran liegen dass two-factor Authentifizierung in ihrem Account nicht aktiviert ist.", - "Invalid answer": "Ungültige Antwort", - "Invalid CAPTCHA": "Ungültiges CAPTCHA", - "CAPTCHA is a required field": "CAPTCHA ist eine erforderliche Eingabe", - "User ID is a required field": "Benutzer ID ist eine erforderliche Eingabe", - "Password is a required field": "Passwort ist eine erforderliche Eingabe", - "Invalid username or password": "Ungültiger Benutzername oder Passwort", - "Please sign in using 'Sign in with Google'": "Bitte melden sie sich mit 'Mit Google anmelden' an", - "Password cannot be empty": "Passwort darf nicht leer sein", - "Password cannot be longer than 55 characters": "Passwort darf nicht länger als 55 Zeichen sein", - "Please sign in": "Bitte anmelden", - "Invidious Private Feed for `x`": "Invidious Persönlicher Feed für `x`", - "channel:`x`": "Kanal:`x`", - "Deleted or invalid channel": "Gelöschter oder ungültiger Kanal", - "This channel does not exist.": "Dieser Kanal existiert nicht.", - "Could not get channel info.": "Kanalinformationen konnten nicht geladen werden.", - "Could not fetch comments": "Kommentare konnten nicht geladen werden", - "View `x` replies": "Zeige `x` Antworten", - "`x` ago": "vor `x`", - "Load more": "Mehr laden", - "`x` points": "`x` Punkte", - "Could not create mix.": "Mix konnte nicht erstellt werden.", - "Playlist is empty": "Playlist ist leer", - "Invalid playlist.": "Ungültige Playlist.", - "Playlist does not exist.": "Playlist existiert nicht.", - "Could not pull trending pages.": "Trending Seiten konnten nicht geladen werden.", - "Hidden field \"challenge\" is a required field": "Verstecktes Feld \"challenge\" ist eine erforderliche Eingabe", - "Hidden field \"token\" is a required field": "Verstecktes Feld \"token\" ist eine erforderliche Eingabe", - "Invalid challenge": "Ungültiger Test", - "Invalid token": "Ungöltige Marke", - "Invalid user": "Ungültiger Benutzer", - "Token is expired, please try again": "Marke ist abgelaufen, bitte erneut versuchen", - "English": "Englisch", - "English (auto-generated)": "Englisch (automatisch erzeugt)", - "Afrikaans": "Afrikaans", - "Albanian": "Albanisch", - "Amharic": "Amharisch", - "Arabic": "Arabisch", - "Armenian": "Armenisch", - "Azerbaijani": "Aserbaidschanisch", - "Bangla": "Bengalisch", - "Basque": "Baskisch", - "Belarusian": "Weißrussisch", - "Bosnian": "Bosnisch", - "Bulgarian": "Bulgarisch", - "Burmese": "Burmesisch", - "Catalan": "Katalanisch", - "Cebuano": "", - "Chinese (Simplified)": "Chinesisch (vereinfacht)", - "Chinese (Traditional)": "Chinesisch (traditionell)", - "Corsican": "Korsisch", - "Croatian": "Kroatisch", - "Czech": "Tschechisch", - "Danish": "Dänisch", - "Dutch": "Niederländisch", - "Esperanto": "Esperanto", - "Estonian": "Estnisch", - "Filipino": "Philippinisch", - "Finnish": "Finnisch", - "French": "Französisch", - "Galician": "Galizisch", - "Georgian": "Georgisch", - "German": "Deutsch", - "Greek": "Griechisch", - "Gujarati": "", - "Haitian Creole": "Haitianisches Kreolisch", - "Hausa": "", - "Hawaiian": "Hawaiianisch", - "Hebrew": "Hebräisch", - "Hindi": "Hindi", - "Hmong": "", - "Hungarian": "Ungarisch", - "Icelandic": "Isländisch", - "Igbo": "", - "Indonesian": "Indonesisch", - "Irish": "Irisch", - "Italian": "Italienisch", - "Japanese": "Japanisch", - "Javanese": "", - "Kannada": "Kannada", - "Kazakh": "Kasachisch", - "Khmer": "Khmer", - "Korean": "Koreanisch", - "Kurdish": "Kurdisch", - "Kyrgyz": "Kirgisisch", - "Lao": "Laotisch", - "Latin": "Lateinisch", - "Latvian": "Lettisch", - "Lithuanian": "Litauisch", - "Luxembourgish": "Luxemburgisch", - "Macedonian": "Mazedonisch", - "Malagasy": "Madagassisch", - "Malay": "Malaiisch", - "Malayalam": "", - "Maltese": "Maltesisch", - "Maori": "Maori", - "Marathi": "", - "Mongolian": "Mongolisch", - "Nepali": "Nepalesisch", - "Norwegian": "Norwegisch", - "Nyanja": "Nyanja", - "Pashto": "Paschtunisch", - "Persian": "Persisch", - "Polish": "Polnisch", - "Portuguese": "Portugiesisch", - "Punjabi": "Pandschabi", - "Romanian": "Rumänisch", - "Russian": "Russisch", - "Samoan": "Samoanisch", - "Scottish Gaelic": "Schottisches Gälisch", - "Serbian": "Serbisch", - "Shona": "Schona", - "Sindhi": "Sindhi", - "Sinhala": "Singhalesisch", - "Slovak": "Slowakisch", - "Slovenian": "Slowenisch", - "Somali": "", - "Southern Sotho": "Südliches Sotho", - "Spanish": "Spanisch", - "Spanish (Latin America)": "Spanisch (Lateinamerika)", - "Sundanese": "Sundanesisch", - "Swahili": "Suaheli", - "Swedish": "Schwedisch", - "Tajik": "Tadschikisch", - "Tamil": "Tamilisch", - "Telugu": "Telugu", - "Thai": "Thailändisch", - "Turkish": "Türkisch", - "Ukrainian": "Ukrainisch", - "Urdu": "", - "Uzbek": "Usbekisch", - "Vietnamese": "Vietnamesisch", - "Welsh": "Walisisch", - "Western Frisian": "Westfriesisch", - "Xhosa": "", - "Yiddish": "Jiddisch", - "Yoruba": "Joruba", - "Zulu": "Zulu", - "`x` years": "`x` Jahre", - "`x` months": "`x` Monate", - "`x` weeks": "`x` Wochen", - "`x` days": "`x` Tage", - "`x` hours": "`x` Stunden", - "`x` minutes": "`x` Minuten", - "`x` seconds": "`x` Sekunden", - "Fallback comments: ": "", - "Popular": "", - "Top": "", - "About": "", - "Rating: ": "", - "Language: ": "" + "`x` subscribers": "`x` Abonnenten", + "`x` videos": "`x` Videos", + "LIVE": "LIVE", + "Shared `x` ago": "Vor `x` geteilt", + "Unsubscribe": "Abbestellen", + "Subscribe": "Abonnieren", + "Login to subscribe to `x`": "Einloggen um `x` zu abonnieren", + "View channel on YouTube": "Kanal auf YouTube anzeigen", + "newest": "neueste", + "oldest": "älteste", + "popular": "beliebt", + "Preview page": "Vorschau Seite", + "Next page": "Nächste Seite", + "Clear watch history?": "Verlauf löschen?", + "Yes": "Ja", + "No": "Nein", + "Import and Export Data": "Import und Export Daten", + "Import": "Importieren", + "Import Invidious data": "Invidious Daten importieren", + "Import YouTube subscriptions": "YouTube Abonnements importieren", + "Import FreeTube subscriptions (.db)": "FreeTube Abonnements importieren (.db)", + "Import NewPipe subscriptions (.json)": "NewPipe Abonnements importieren (.json)", + "Import NewPipe data (.zip)": "NewPipe Daten importieren (.zip)", + "Export": "Exportieren", + "Export subscriptions as OPML": "Abonnements als OPML exportieren", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportieren (für NewPipe & FreeTube)", + "Export data as JSON": "Daten als JSON exportieren", + "Delete account?": "Account löschen?", + "History": "Verlauf", + "Previous page": "Vorherige Seite", + "An alternative front-end to YouTube": "Eine alternative Oberfläche für YouTube", + "JavaScript license information": "JavaScript Lizenzinformationen", + "source": "Quelle", + "Login": "Einloggen", + "Login/Register": "Einloggen/Registrieren", + "Login to Google": "In Google einloggen", + "User ID:": "Benutzer ID:", + "Password:": "Passwort:", + "Time (h:mm:ss):": "Zeit (h:mm:ss):", + "Text CAPTCHA": "Text CAPTCHA", + "Image CAPTCHA": "Image CAPTCHA", + "Sign In": "Einloggen", + "Register": "Registrieren", + "Email:": "Email:", + "Google verification code:": "Google Bestätigungscode:", + "Preferences": "Einstellungen", + "Player preferences": "Playereinstellungen", + "Always loop: ": "Immer wiederholen: ", + "Autoplay: ": "Automatisch abspielen: ", + "Autoplay next video: ": "nächstes Video automatisch abspielen: ", + "Listen by default: ": "Nur Ton als Standard: ", + "Default speed: ": "Standardgeschwindigkeit: ", + "Preferred video quality: ": "Bevorzugte Videoqualität: ", + "Player volume: ": "Playerlautstärke: ", + "Default comments: ": "Standardkommentare: ", + "youtube": "youtube", + "reddit": "reddit", + "Default captions: ": "Standarduntertitel: ", + "Fallback captions: ": "Ersatzuntertitel: ", + "Show related videos? ": "Ähnliche Videos anzeigen? ", + "Visual preferences": "Anzeigeeinstellungen", + "Dark mode: ": "Nachtmodus: ", + "Thin mode: ": "Schlanker Modus: ", + "Subscription preferences": "Abonnementeinstellungen", + "Redirect homepage to feed: ": "Startseite zu Feed umleiten: ", + "Number of videos shown in feed: ": "Anzahl von Videos die im Feed angezeigt werden: ", + "Sort videos by: ": "Videos sortieren nach: ", + "published": "veröffentlicht", + "published - reverse": "veröffentlicht - invertiert", + "alphabetically": "alphabetisch", + "alphabetically - reverse": "alphabetisch - invertiert", + "channel name": "Kanalname", + "channel name - reverse": "Kanalname - invertiert", + "Only show latest video from channel: ": "Nur neueste Videos des Kanals anzeigen: ", + "Only show latest unwatched video from channel: ": "Nur neueste ungesehene Videos des Kanals anzeigen: ", + "Only show unwatched: ": "Nur ungesehene anzeigen: ", + "Only show notifications (if there are any): ": "Nur Benachrichtigungen anzeigen (wenn es welche gibt): ", + "Data preferences": "Dateneinstellungen", + "Clear watch history": "Verlauf löschen", + "Import/Export data": "Daten im- exportieren", + "Manage subscriptions": "Abonnements verwalten", + "Watch history": "Verlauf", + "Delete account": "Account löschen", + "Save preferences": "Einstellungen speichern", + "Subscription manager": "Abonnementverwaltung", + "`x` subscriptions": "`x` Abonnements", + "Import/Export": "Importieren/Exportieren", + "unsubscribe": "abbestellen", + "Subscriptions": "Abonnements", + "`x` unseen notifications": "`x` ungesehene Benachrichtigungen", + "search": "Suchen", + "Sign out": "Abmelden", + "Released under the AGPLv3 by Omar Roth.": "Veröffentlicht unter AGPLv3 von Omar Roth.", + "Source available here.": "Quellcode verfügbar hier.", + "Liberapay: ": "Liberapay: ", + "Patreon: ": "Patreon: ", + "BTC: ": "BTC: ", + "BCH: ": "BCH: ", + "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.", + "Trending": "Trending", + "Watch video on Youtube": "Video auf YouTube ansehen", + "Genre: ": "Genre: ", + "License: ": "Lizenz: ", + "Family friendly? ": "Familienfreundlich? ", + "Wilson score: ": "Wilson-Score: ", + "Engagement: ": "Engagement: ", + "Whitelisted regions: ": "Erlaubte Regionen: ", + "Blacklisted regions: ": "Unerlaubte Regionen: ", + "Shared `x`": "Geteilt `x`", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.", + "View YouTube comments": "YouTube Kommentare anzeigen", + "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen", + "View `x` comments": "`x` Kommentare anzeigen", + "View Reddit comments": "Reddit Kommentare anzeigen", + "Hide replies": "Antworten verstecken", + "Show replies": "Antworten anzeigen", + "Incorrect password": "Falsches Passwort", + "Quota exceeded, try again in a few hours": "Kontingent überschritten, versuche es in ein paar Stunden erneut", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Login nicht möglich, stellen Sie sicher dass two-factor Authentifikation (Authentifizierung oder SMS) aktiviert ist.", + "Invalid TFA code": "Ungültiger TFA Code", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "Login fehlgeschlagen. Das kann daran liegen dass two-factor Authentifizierung in ihrem Account nicht aktiviert ist.", + "Invalid answer": "Ungültige Antwort", + "Invalid CAPTCHA": "Ungültiges CAPTCHA", + "CAPTCHA is a required field": "CAPTCHA ist eine erforderliche Eingabe", + "User ID is a required field": "Benutzer ID ist eine erforderliche Eingabe", + "Password is a required field": "Passwort ist eine erforderliche Eingabe", + "Invalid username or password": "Ungültiger Benutzername oder Passwort", + "Please sign in using 'Sign in with Google'": "Bitte melden sie sich mit 'Mit Google anmelden' an", + "Password cannot be empty": "Passwort darf nicht leer sein", + "Password cannot be longer than 55 characters": "Passwort darf nicht länger als 55 Zeichen sein", + "Please sign in": "Bitte anmelden", + "Invidious Private Feed for `x`": "Invidious Persönlicher Feed für `x`", + "channel:`x`": "Kanal:`x`", + "Deleted or invalid channel": "Gelöschter oder ungültiger Kanal", + "This channel does not exist.": "Dieser Kanal existiert nicht.", + "Could not get channel info.": "Kanalinformationen konnten nicht geladen werden.", + "Could not fetch comments": "Kommentare konnten nicht geladen werden", + "View `x` replies": "Zeige `x` Antworten", + "`x` ago": "vor `x`", + "Load more": "Mehr laden", + "`x` points": "`x` Punkte", + "Could not create mix.": "Mix konnte nicht erstellt werden.", + "Playlist is empty": "Playlist ist leer", + "Invalid playlist.": "Ungültige Playlist.", + "Playlist does not exist.": "Playlist existiert nicht.", + "Could not pull trending pages.": "Trending Seiten konnten nicht geladen werden.", + "Hidden field \"challenge\" is a required field": "Verstecktes Feld \"challenge\" ist eine erforderliche Eingabe", + "Hidden field \"token\" is a required field": "Verstecktes Feld \"token\" ist eine erforderliche Eingabe", + "Invalid challenge": "Ungültiger Test", + "Invalid token": "Ungöltige Marke", + "Invalid user": "Ungültiger Benutzer", + "Token is expired, please try again": "Marke ist abgelaufen, bitte erneut versuchen", + "English": "Englisch", + "English (auto-generated)": "Englisch (automatisch erzeugt)", + "Afrikaans": "Afrikaans", + "Albanian": "Albanisch", + "Amharic": "Amharisch", + "Arabic": "Arabisch", + "Armenian": "Armenisch", + "Azerbaijani": "Aserbaidschanisch", + "Bangla": "Bengalisch", + "Basque": "Baskisch", + "Belarusian": "Weißrussisch", + "Bosnian": "Bosnisch", + "Bulgarian": "Bulgarisch", + "Burmese": "Burmesisch", + "Catalan": "Katalanisch", + "Cebuano": "Cebuano", + "Chinese (Simplified)": "Chinesisch (vereinfacht)", + "Chinese (Traditional)": "Chinesisch (traditionell)", + "Corsican": "Korsisch", + "Croatian": "Kroatisch", + "Czech": "Tschechisch", + "Danish": "Dänisch", + "Dutch": "Niederländisch", + "Esperanto": "Esperanto", + "Estonian": "Estnisch", + "Filipino": "Philippinisch", + "Finnish": "Finnisch", + "French": "Französisch", + "Galician": "Galizisch", + "Georgian": "Georgisch", + "German": "Deutsch", + "Greek": "Griechisch", + "Gujarati": "Gujarati", + "Haitian Creole": "Haitianisches Kreolisch", + "Hausa": "Hausa", + "Hawaiian": "Hawaiianisch", + "Hebrew": "Hebräisch", + "Hindi": "Hindi", + "Hmong": "Hmong", + "Hungarian": "Ungarisch", + "Icelandic": "Isländisch", + "Igbo": "Igbo", + "Indonesian": "Indonesisch", + "Irish": "Irisch", + "Italian": "Italienisch", + "Japanese": "Japanisch", + "Javanese": "Javanisch", + "Kannada": "Kannada", + "Kazakh": "Kasachisch", + "Khmer": "Khmer", + "Korean": "Koreanisch", + "Kurdish": "Kurdisch", + "Kyrgyz": "Kirgisisch", + "Lao": "Laotisch", + "Latin": "Lateinisch", + "Latvian": "Lettisch", + "Lithuanian": "Litauisch", + "Luxembourgish": "Luxemburgisch", + "Macedonian": "Mazedonisch", + "Malagasy": "Madagassisch", + "Malay": "Malaiisch", + "Malayalam": "Malayalam", + "Maltese": "Maltesisch", + "Maori": "Maori", + "Marathi": "Marathi", + "Mongolian": "Mongolisch", + "Nepali": "Nepalesisch", + "Norwegian": "Norwegisch", + "Nyanja": "Nyanja", + "Pashto": "Paschtunisch", + "Persian": "Persisch", + "Polish": "Polnisch", + "Portuguese": "Portugiesisch", + "Punjabi": "Pandschabi", + "Romanian": "Rumänisch", + "Russian": "Russisch", + "Samoan": "Samoanisch", + "Scottish Gaelic": "Schottisches Gälisch", + "Serbian": "Serbisch", + "Shona": "Schona", + "Sindhi": "Sindhi", + "Sinhala": "Singhalesisch", + "Slovak": "Slowakisch", + "Slovenian": "Slowenisch", + "Somali": "Somali", + "Southern Sotho": "Südliches Sotho", + "Spanish": "Spanisch", + "Spanish (Latin America)": "Spanisch (Lateinamerika)", + "Sundanese": "Sundanesisch", + "Swahili": "Suaheli", + "Swedish": "Schwedisch", + "Tajik": "Tadschikisch", + "Tamil": "Tamilisch", + "Telugu": "Telugu", + "Thai": "Thailändisch", + "Turkish": "Türkisch", + "Ukrainian": "Ukrainisch", + "Urdu": "Urdu", + "Uzbek": "Usbekisch", + "Vietnamese": "Vietnamesisch", + "Welsh": "Walisisch", + "Western Frisian": "Westfriesisch", + "Xhosa": "Xhosa", + "Yiddish": "Jiddisch", + "Yoruba": "Joruba", + "Zulu": "Zulu", + "`x` years": "`x` Jahre", + "`x` months": "`x` Monate", + "`x` weeks": "`x` Wochen", + "`x` days": "`x` Tage", + "`x` hours": "`x` Stunden", + "`x` minutes": "`x` Minuten", + "`x` seconds": "`x` Sekunden", + "Fallback comments: ": "", + "Popular": "Populär", + "Top": "", + "About": "Über", + "Rating: ": "Bewertung: ", + "Language: ": "Sprache: " } From 4ae57cb475ef64730a13982f94f4810d901bc6b5 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Fri, 4 Jan 2019 22:48:00 -0600 Subject: [PATCH 008/108] Improve playlist description extractor --- src/invidious/playlists.cr | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr index 0f74b37a..6e48bacf 100644 --- a/src/invidious/playlists.cr +++ b/src/invidious/playlists.cr @@ -168,10 +168,7 @@ def fetch_playlist(plid, locale) raise translate(locale, "Invalid playlist.") end - body = response.body.gsub(%( - - ), "") + body = response.body.gsub(/]+>]+>\s*less\s*]+>\n<\/span><\/button>/, "") document = XML.parse_html(body) title = document.xpath_node(%q(//h1[@class="pl-header-title"])) From 7f8349d4b13b371821f73839bf9bf2edff2d5b15 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 5 Jan 2019 15:23:22 -0600 Subject: [PATCH 009/108] Escape function names in signature extractor --- src/invidious/signatures.cr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/invidious/signatures.cr b/src/invidious/signatures.cr index eaf91902..b2ed89d2 100644 --- a/src/invidious/signatures.cr +++ b/src/invidious/signatures.cr @@ -1,15 +1,15 @@ def fetch_decrypt_function(id = "CvFH_6DNRCY") client = make_client(YT_URL) - document = client.get("/watch?v=#{id}").body - url = document.match(/src="(?\/yts\/jsbin\/player-.{9}\/en_US\/base.js)"/).not_nil!["url"] + document = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1").body + url = document.match(/src="(?\/yts\/jsbin\/player_ias-.{9}\/en_US\/base.js)"/).not_nil!["url"] player = client.get(url).body function_name = player.match(/^(?[^=]+)=function\(a\){a=a\.split\(""\)/m).not_nil!["name"] - function_body = player.match(/^#{function_name}=function\(a\){(?[^}]+)}/m).not_nil!["body"] + function_body = player.match(/^#{Regex.escape(function_name)}=function\(a\){(?[^}]+)}/m).not_nil!["body"] function_body = function_body.split(";")[1..-2] var_name = function_body[0][0, 2] - var_body = player.delete("\n").match(/var #{var_name}={(?(.*?))};/).not_nil!["body"] + var_body = player.delete("\n").match(/var #{Regex.escape(var_name)}={(?(.*?))};/).not_nil!["body"] operations = {} of String => String var_body.split("},").each do |operation| From a16f967085415d7ddc2173be012fee783b4da6d9 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 5 Jan 2019 15:25:31 -0600 Subject: [PATCH 010/108] Add popular, top, trending bar --- src/invidious/views/index.ecr | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/invidious/views/index.ecr b/src/invidious/views/index.ecr index ca5d3ae8..a12455b0 100644 --- a/src/invidious/views/index.ecr +++ b/src/invidious/views/index.ecr @@ -3,6 +3,30 @@ Invidious <% end %> + +
<% top_videos.each_slice(4) do |slice| %> <% slice.each do |item| %> From 7abe5dc845322f561917ea86680b156d0f160b48 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 5 Jan 2019 21:51:08 -0600 Subject: [PATCH 011/108] Add onion links to README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 34a5dbbd..01ab9e6c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,11 @@ Patreon: https://patreon.com/omarroth BTC: 356DpZyMXu6rYd55Yqzjs29n79kGKWcYrY BCH: qq4ptclkzej5eza6a50et5ggc58hxsq5aylqut2npk +Onion links: + +- kgg2m7yk5aybusll.onion +- axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4bzzsg2ii4fv2iid.onion + ## Installation ### Docker: From 81c2ecc788d2510050a2d13fda420601043d4047 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 5 Jan 2019 21:54:23 -0600 Subject: [PATCH 012/108] Bump version and update CHANGELOG --- CHANGELOG.md | 71 +++++++++++++++++++++++++++++++++++++++ shard.yml | 2 +- src/invidious/comments.cr | 2 +- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a74222a9..99b4adf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,74 @@ +# 0.13.0 (2019-01-06) + +## Version 0.13.0: Translations, Annotations, and Tor + +I hope everyone had a happy New Year! There's been a couple new additions since last release, with [44 commits](https://github.com/omarroth/invidious/compare/0.12.0...0.13.0) from 9 contributors. It's been quite a year for the project, and I hope to continue improving the project into 2019! Starting off the new year: + +## Translations + +I'm happy to announce support for translations has been added with [`a160c64`](https://github.com/omarroth/invidious/a160c64). Currently, there is support for: + +- Arabic (`ar`) +- Dutch (`nl`) +- English (`en-US`) +- German (`de`) +- Norwegian Bokmål (`nb_NO`) +- Polish (`pl`) +- Russian (`ru`) + +Which you can change in your preferences under `Language`. You can also add `&hl=LANGUAGE` to the end of any request to translate it to your preferred language, for example https://invidio.us/?hl=ru. I'd like to say thank you again to everyone who has helped translate the site! I've mentioned this before, but I'm delighted that so many people find the project useful. + +## Annotations + +Recently, [YouTube announced that all annotations will be deleted on January 15th, 2019](https://support.google.com/youtube/answer/7342737). I believe that annotations have a very important place in YouTube's history, and [announced a project to archive them](https://www.reddit.com/r/DataHoarder/comments/aa6czg/youtube_annotation_archive/). + +I expect annotations to be supported in the Invidious player once archiving is complete (see [#110](https://github.com/omarroth/invidious/issues/110) for details), and would also like to host them for other developers to use in their projects. + +The code is available [here](https://github.com/omarroth/archive), and contains instructions for running a worker if you would like to contribute. There's much more information available in the announcement as well for anyone who is interested. + +## Tor + +I unfortunately missed the chance to mention this in the previous release, but I'm now happy to announce that you can now view Invidious through Tor at the following links: + +kgg2m7yk5aybusll.onion +axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4bzzsg2ii4fv2iid.onion + +Invidious is well suited to use through Tor, as it does not require any JS and is fairly lightweight. I'd recommend looking [here](https://diasp.org/posts/10965196) and [here](https://www.reddit.com/r/TOR/comments/a3c1ak/you_can_now_watch_youtube_videos_anonymously_with/) for more details on how to use the onion links, and would like to say thank you to [/u/whonix-os](https://www.reddit.com/user/whonix-os) for suggesting it and providing support setting setting them up. + +## Popular and Trending + +You can now easily view videos trending on YouTube with [`a16f967`](https://github.com/omarroth/invidious/a16f967). It also provides support for viewing YouTube's various categories categories, such as `News`, `Gaming`, and `Music`. You can also change the `region` parameter to view trending in different countries, which should be made easier to use in the coming weeks. + +A link to `/feed/popular` has also been added, which provides a list of videos sorted using the algorithm described [here](https://github.com/omarroth/invidious/issues/217#issuecomment-436503761). I think it better reflects what users watch on the site, but I'd like to hear peoples' thoughts on this and on how it could be improved. + +## Finances + +### Donations + +- [Patreon](https://www.patreon.com/omarroth): \$64.63 +- [Liberapay](https://liberapay.com/omarroth) : \$30.05 +- Crypto : ~\$28.74 (converted from BCH, BTC) +- Total : \$123.42 + +### Expenses + +- invidious-load1 (nyc1) : \$10.00 (load balancer) +- invidious-update1 (s-1vcpu-1gb) : \$5.00 (updates feeds) +- invidious-node1 (s-1vcpu-1gb) : \$5.00 (web server) +- invidious-node2 (s-1vcpu-1gb) : \$5.00 (web server) +- invidious-node3 (s-1vcpu-1gb) : \$5.00 (web server) +- invidious-node4 (s-1vcpu-1gb) : \$5.00 (web server) +- invidious-db1 (s-4vcpu-8gb) : \$40.00 (database) +- Total : \$75.00 + +### What will happen with what's left over? + +I believe this is the first month that all expenses have been fully paid for by donations. Thank you! I expect to allocate the current amount for hardware to improve performance and for hosting annotation data, as mentioned above. + +Anything that is left over is kept to continue hosting the project for as long as possible. Thank you again everyone! + +I think that's everything for 2018. There's lots still planned, and I'm very excited for the future of this project! + # 0.12.0 (2018-12-06) ## Version 0.12.0: Accessibility, Privacy, Transparency diff --git a/shard.yml b/shard.yml index 9d9181df..6ed680f2 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: invidious -version: 0.12.0 +version: 0.13.0 authors: - Omar Roth diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr index ad759468..86dbb6b5 100644 --- a/src/invidious/comments.cr +++ b/src/invidious/comments.cr @@ -270,7 +270,7 @@ end def fetch_reddit_comments(id) client = make_client(REDDIT_URL) - headers = HTTP::Headers{"User-Agent" => "web:invidio.us:v0.12.0 (by /u/omarroth)"} + headers = HTTP::Headers{"User-Agent" => "web:invidio.us:v0.13.0 (by /u/omarroth)"} query = "(url:3D#{id}%20OR%20url:#{id})%20(site:youtube.com%20OR%20site:youtu.be)" search_results = client.get("/search.json?q=#{query}", headers) From c6ec8317acd1ade048809c110fee2703be541134 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 5 Jan 2019 23:02:03 -0600 Subject: [PATCH 013/108] Use location.assign instead of window.location.replace --- src/invidious/views/watch.ecr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index ad25e5d7..832d13d1 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -179,7 +179,7 @@ -<% if env.get?("user") && env.get("user").as(User).preferences.quality == "dash" %> +<% if params[:quality] == "dash" %> From 8f1b65de59326280f01ea2c05d8f39c767a3f828 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 23 Jan 2019 22:45:31 -0600 Subject: [PATCH 047/108] Add missing text to en-US.json --- locales/en-US.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/en-US.json b/locales/en-US.json index 10e04598..4dcf036c 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -263,5 +263,7 @@ "Top": "Top", "About": "About", "Rating: ": "Rating: ", - "Language: ": "Language: " + "Language: ": "Language: ", + "Download": "Download", + "Download as: ": "Download as: " } From 30f08ae48c1edc7beb2406bc18140e0b7b5254da Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 23 Jan 2019 22:54:04 -0600 Subject: [PATCH 048/108] Add missing text to locales --- locales/ar.json | 4 +- locales/de.json | 549 +++++++++++++++++++++++---------------------- locales/en-US.json | 5 + locales/fr.json | 9 +- locales/nb_NO.json | 537 ++++++++++++++++++++++---------------------- locales/nl.json | 9 +- locales/pl.json | 9 +- locales/ru.json | 549 +++++++++++++++++++++++---------------------- 8 files changed, 860 insertions(+), 811 deletions(-) diff --git a/locales/ar.json b/locales/ar.json index 268be9df..6284043a 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -274,5 +274,7 @@ "Music": "الاغانى", "Gaming": "الألعاب", "News": "الأخبار", - "Movies": "الأفلام" + "Movies": "الأفلام", + "Download": "", + "Download as: ": "" } diff --git a/locales/de.json b/locales/de.json index 039b1564..e176da76 100644 --- a/locales/de.json +++ b/locales/de.json @@ -1,273 +1,280 @@ { - "`x` subscribers": "`x` Abonnenten", - "`x` videos": "`x` Videos", - "LIVE": "LIVE", - "Shared `x` ago": "Vor `x` geteilt", - "Unsubscribe": "Abbestellen", - "Subscribe": "Abonnieren", - "Login to subscribe to `x`": "Einloggen um `x` zu abonnieren", - "View channel on YouTube": "Kanal auf YouTube anzeigen", - "newest": "neueste", - "oldest": "älteste", - "popular": "beliebt", - "Preview page": "Vorschau Seite", - "Next page": "Nächste Seite", - "Clear watch history?": "Verlauf löschen?", - "Yes": "Ja", - "No": "Nein", - "Import and Export Data": "Import und Export Daten", - "Import": "Importieren", - "Import Invidious data": "Invidious Daten importieren", - "Import YouTube subscriptions": "YouTube Abonnements importieren", - "Import FreeTube subscriptions (.db)": "FreeTube Abonnements importieren (.db)", - "Import NewPipe subscriptions (.json)": "NewPipe Abonnements importieren (.json)", - "Import NewPipe data (.zip)": "NewPipe Daten importieren (.zip)", - "Export": "Exportieren", - "Export subscriptions as OPML": "Abonnements als OPML exportieren", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportieren (für NewPipe & FreeTube)", - "Export data as JSON": "Daten als JSON exportieren", - "Delete account?": "Account löschen?", - "History": "Verlauf", - "Previous page": "Vorherige Seite", - "An alternative front-end to YouTube": "Eine alternative Oberfläche für YouTube", - "JavaScript license information": "JavaScript Lizenzinformationen", - "source": "Quelle", - "Login": "Einloggen", - "Login/Register": "Einloggen/Registrieren", - "Login to Google": "In Google einloggen", - "User ID:": "Benutzer ID:", - "Password:": "Passwort:", - "Time (h:mm:ss):": "Zeit (h:mm:ss):", - "Text CAPTCHA": "Text CAPTCHA", - "Image CAPTCHA": "Image CAPTCHA", - "Sign In": "Einloggen", - "Register": "Registrieren", - "Email:": "Email:", - "Google verification code:": "Google Bestätigungscode:", - "Preferences": "Einstellungen", - "Player preferences": "Playereinstellungen", - "Always loop: ": "Immer wiederholen: ", - "Autoplay: ": "Automatisch abspielen: ", - "Autoplay next video: ": "nächstes Video automatisch abspielen: ", - "Listen by default: ": "Nur Ton als Standard: ", - "Default speed: ": "Standardgeschwindigkeit: ", - "Preferred video quality: ": "Bevorzugte Videoqualität: ", - "Player volume: ": "Playerlautstärke: ", - "Default comments: ": "Standardkommentare: ", - "youtube": "youtube", - "reddit": "reddit", - "Default captions: ": "Standarduntertitel: ", - "Fallback captions: ": "Ersatzuntertitel: ", - "Show related videos? ": "Ähnliche Videos anzeigen? ", - "Visual preferences": "Anzeigeeinstellungen", - "Dark mode: ": "Nachtmodus: ", - "Thin mode: ": "Schlanker Modus: ", - "Subscription preferences": "Abonnementeinstellungen", - "Redirect homepage to feed: ": "Startseite zu Feed umleiten: ", - "Number of videos shown in feed: ": "Anzahl von Videos die im Feed angezeigt werden: ", - "Sort videos by: ": "Videos sortieren nach: ", - "published": "veröffentlicht", - "published - reverse": "veröffentlicht - invertiert", - "alphabetically": "alphabetisch", - "alphabetically - reverse": "alphabetisch - invertiert", - "channel name": "Kanalname", - "channel name - reverse": "Kanalname - invertiert", - "Only show latest video from channel: ": "Nur neueste Videos des Kanals anzeigen: ", - "Only show latest unwatched video from channel: ": "Nur neueste ungesehene Videos des Kanals anzeigen: ", - "Only show unwatched: ": "Nur ungesehene anzeigen: ", - "Only show notifications (if there are any): ": "Nur Benachrichtigungen anzeigen (wenn es welche gibt): ", - "Data preferences": "Dateneinstellungen", - "Clear watch history": "Verlauf löschen", - "Import/Export data": "Daten im- exportieren", - "Manage subscriptions": "Abonnements verwalten", - "Watch history": "Verlauf", - "Delete account": "Account löschen", - "Save preferences": "Einstellungen speichern", - "Subscription manager": "Abonnementverwaltung", - "`x` subscriptions": "`x` Abonnements", - "Import/Export": "Importieren/Exportieren", - "unsubscribe": "abbestellen", - "Subscriptions": "Abonnements", - "`x` unseen notifications": "`x` ungesehene Benachrichtigungen", - "search": "Suchen", - "Sign out": "Abmelden", - "Released under the AGPLv3 by Omar Roth.": "Veröffentlicht unter AGPLv3 von Omar Roth.", - "Source available here.": "Quellcode verfügbar hier.", - "Liberapay: ": "Liberapay: ", - "Patreon: ": "Patreon: ", - "BTC: ": "BTC: ", - "BCH: ": "BCH: ", - "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.", - "Trending": "Trending", - "Watch video on Youtube": "Video auf YouTube ansehen", - "Genre: ": "Genre: ", - "License: ": "Lizenz: ", - "Family friendly? ": "Familienfreundlich? ", - "Wilson score: ": "Wilson-Score: ", - "Engagement: ": "Engagement: ", - "Whitelisted regions: ": "Erlaubte Regionen: ", - "Blacklisted regions: ": "Unerlaubte Regionen: ", - "Shared `x`": "Geteilt `x`", - "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.", - "View YouTube comments": "YouTube Kommentare anzeigen", - "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen", - "View `x` comments": "`x` Kommentare anzeigen", - "View Reddit comments": "Reddit Kommentare anzeigen", - "Hide replies": "Antworten verstecken", - "Show replies": "Antworten anzeigen", - "Incorrect password": "Falsches Passwort", - "Quota exceeded, try again in a few hours": "Kontingent überschritten, versuche es in ein paar Stunden erneut", - "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Login nicht möglich, stellen Sie sicher dass two-factor Authentifikation (Authentifizierung oder SMS) aktiviert ist.", - "Invalid TFA code": "Ungültiger TFA Code", - "Login failed. This may be because two-factor authentication is not enabled on your account.": "Login fehlgeschlagen. Das kann daran liegen dass two-factor Authentifizierung in ihrem Account nicht aktiviert ist.", - "Invalid answer": "Ungültige Antwort", - "Invalid CAPTCHA": "Ungültiges CAPTCHA", - "CAPTCHA is a required field": "CAPTCHA ist eine erforderliche Eingabe", - "User ID is a required field": "Benutzer ID ist eine erforderliche Eingabe", - "Password is a required field": "Passwort ist eine erforderliche Eingabe", - "Invalid username or password": "Ungültiger Benutzername oder Passwort", - "Please sign in using 'Sign in with Google'": "Bitte melden sie sich mit 'Mit Google anmelden' an", - "Password cannot be empty": "Passwort darf nicht leer sein", - "Password cannot be longer than 55 characters": "Passwort darf nicht länger als 55 Zeichen sein", - "Please sign in": "Bitte anmelden", - "Invidious Private Feed for `x`": "Invidious Persönlicher Feed für `x`", - "channel:`x`": "Kanal:`x`", - "Deleted or invalid channel": "Gelöschter oder ungültiger Kanal", - "This channel does not exist.": "Dieser Kanal existiert nicht.", - "Could not get channel info.": "Kanalinformationen konnten nicht geladen werden.", - "Could not fetch comments": "Kommentare konnten nicht geladen werden", - "View `x` replies": "Zeige `x` Antworten", - "`x` ago": "vor `x`", - "Load more": "Mehr laden", - "`x` points": "`x` Punkte", - "Could not create mix.": "Mix konnte nicht erstellt werden.", - "Playlist is empty": "Playlist ist leer", - "Invalid playlist.": "Ungültige Playlist.", - "Playlist does not exist.": "Playlist existiert nicht.", - "Could not pull trending pages.": "Trending Seiten konnten nicht geladen werden.", - "Hidden field \"challenge\" is a required field": "Verstecktes Feld \"challenge\" ist eine erforderliche Eingabe", - "Hidden field \"token\" is a required field": "Verstecktes Feld \"token\" ist eine erforderliche Eingabe", - "Invalid challenge": "Ungültiger Test", - "Invalid token": "Ungöltige Marke", - "Invalid user": "Ungültiger Benutzer", - "Token is expired, please try again": "Marke ist abgelaufen, bitte erneut versuchen", - "English": "Englisch", - "English (auto-generated)": "Englisch (automatisch erzeugt)", - "Afrikaans": "Afrikaans", - "Albanian": "Albanisch", - "Amharic": "Amharisch", - "Arabic": "Arabisch", - "Armenian": "Armenisch", - "Azerbaijani": "Aserbaidschanisch", - "Bangla": "Bengalisch", - "Basque": "Baskisch", - "Belarusian": "Weißrussisch", - "Bosnian": "Bosnisch", - "Bulgarian": "Bulgarisch", - "Burmese": "Burmesisch", - "Catalan": "Katalanisch", - "Cebuano": "Cebuano", - "Chinese (Simplified)": "Chinesisch (vereinfacht)", - "Chinese (Traditional)": "Chinesisch (traditionell)", - "Corsican": "Korsisch", - "Croatian": "Kroatisch", - "Czech": "Tschechisch", - "Danish": "Dänisch", - "Dutch": "Niederländisch", - "Esperanto": "Esperanto", - "Estonian": "Estnisch", - "Filipino": "Philippinisch", - "Finnish": "Finnisch", - "French": "Französisch", - "Galician": "Galizisch", - "Georgian": "Georgisch", - "German": "Deutsch", - "Greek": "Griechisch", - "Gujarati": "Gujarati", - "Haitian Creole": "Haitianisches Kreolisch", - "Hausa": "Hausa", - "Hawaiian": "Hawaiianisch", - "Hebrew": "Hebräisch", - "Hindi": "Hindi", - "Hmong": "Hmong", - "Hungarian": "Ungarisch", - "Icelandic": "Isländisch", - "Igbo": "Igbo", - "Indonesian": "Indonesisch", - "Irish": "Irisch", - "Italian": "Italienisch", - "Japanese": "Japanisch", - "Javanese": "Javanisch", - "Kannada": "Kannada", - "Kazakh": "Kasachisch", - "Khmer": "Khmer", - "Korean": "Koreanisch", - "Kurdish": "Kurdisch", - "Kyrgyz": "Kirgisisch", - "Lao": "Laotisch", - "Latin": "Lateinisch", - "Latvian": "Lettisch", - "Lithuanian": "Litauisch", - "Luxembourgish": "Luxemburgisch", - "Macedonian": "Mazedonisch", - "Malagasy": "Madagassisch", - "Malay": "Malaiisch", - "Malayalam": "Malayalam", - "Maltese": "Maltesisch", - "Maori": "Maori", - "Marathi": "Marathi", - "Mongolian": "Mongolisch", - "Nepali": "Nepalesisch", - "Norwegian": "Norwegisch", - "Nyanja": "Nyanja", - "Pashto": "Paschtunisch", - "Persian": "Persisch", - "Polish": "Polnisch", - "Portuguese": "Portugiesisch", - "Punjabi": "Pandschabi", - "Romanian": "Rumänisch", - "Russian": "Russisch", - "Samoan": "Samoanisch", - "Scottish Gaelic": "Schottisches Gälisch", - "Serbian": "Serbisch", - "Shona": "Schona", - "Sindhi": "Sindhi", - "Sinhala": "Singhalesisch", - "Slovak": "Slowakisch", - "Slovenian": "Slowenisch", - "Somali": "Somali", - "Southern Sotho": "Südliches Sotho", - "Spanish": "Spanisch", - "Spanish (Latin America)": "Spanisch (Lateinamerika)", - "Sundanese": "Sundanesisch", - "Swahili": "Suaheli", - "Swedish": "Schwedisch", - "Tajik": "Tadschikisch", - "Tamil": "Tamilisch", - "Telugu": "Telugu", - "Thai": "Thailändisch", - "Turkish": "Türkisch", - "Ukrainian": "Ukrainisch", - "Urdu": "Urdu", - "Uzbek": "Usbekisch", - "Vietnamese": "Vietnamesisch", - "Welsh": "Walisisch", - "Western Frisian": "Westfriesisch", - "Xhosa": "Xhosa", - "Yiddish": "Jiddisch", - "Yoruba": "Joruba", - "Zulu": "Zulu", - "`x` years": "`x` Jahre", - "`x` months": "`x` Monate", - "`x` weeks": "`x` Wochen", - "`x` days": "`x` Tage", - "`x` hours": "`x` Stunden", - "`x` minutes": "`x` Minuten", - "`x` seconds": "`x` Sekunden", - "Fallback comments: ": "", - "Popular": "Populär", - "Top": "", - "About": "Über", - "Rating: ": "Bewertung: ", - "Language: ": "Sprache: " + "`x` subscribers": "`x` Abonnenten", + "`x` videos": "`x` Videos", + "LIVE": "LIVE", + "Shared `x` ago": "Vor `x` geteilt", + "Unsubscribe": "Abbestellen", + "Subscribe": "Abonnieren", + "Login to subscribe to `x`": "Einloggen um `x` zu abonnieren", + "View channel on YouTube": "Kanal auf YouTube anzeigen", + "newest": "neueste", + "oldest": "älteste", + "popular": "beliebt", + "Preview page": "Vorschau Seite", + "Next page": "Nächste Seite", + "Clear watch history?": "Verlauf löschen?", + "Yes": "Ja", + "No": "Nein", + "Import and Export Data": "Import und Export Daten", + "Import": "Importieren", + "Import Invidious data": "Invidious Daten importieren", + "Import YouTube subscriptions": "YouTube Abonnements importieren", + "Import FreeTube subscriptions (.db)": "FreeTube Abonnements importieren (.db)", + "Import NewPipe subscriptions (.json)": "NewPipe Abonnements importieren (.json)", + "Import NewPipe data (.zip)": "NewPipe Daten importieren (.zip)", + "Export": "Exportieren", + "Export subscriptions as OPML": "Abonnements als OPML exportieren", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Abonnements als OPML exportieren (für NewPipe & FreeTube)", + "Export data as JSON": "Daten als JSON exportieren", + "Delete account?": "Account löschen?", + "History": "Verlauf", + "Previous page": "Vorherige Seite", + "An alternative front-end to YouTube": "Eine alternative Oberfläche für YouTube", + "JavaScript license information": "JavaScript Lizenzinformationen", + "source": "Quelle", + "Login": "Einloggen", + "Login/Register": "Einloggen/Registrieren", + "Login to Google": "In Google einloggen", + "User ID:": "Benutzer ID:", + "Password:": "Passwort:", + "Time (h:mm:ss):": "Zeit (h:mm:ss):", + "Text CAPTCHA": "Text CAPTCHA", + "Image CAPTCHA": "Image CAPTCHA", + "Sign In": "Einloggen", + "Register": "Registrieren", + "Email:": "Email:", + "Google verification code:": "Google Bestätigungscode:", + "Preferences": "Einstellungen", + "Player preferences": "Playereinstellungen", + "Always loop: ": "Immer wiederholen: ", + "Autoplay: ": "Automatisch abspielen: ", + "Autoplay next video: ": "nächstes Video automatisch abspielen: ", + "Listen by default: ": "Nur Ton als Standard: ", + "Default speed: ": "Standardgeschwindigkeit: ", + "Preferred video quality: ": "Bevorzugte Videoqualität: ", + "Player volume: ": "Playerlautstärke: ", + "Default comments: ": "Standardkommentare: ", + "youtube": "youtube", + "reddit": "reddit", + "Default captions: ": "Standarduntertitel: ", + "Fallback captions: ": "Ersatzuntertitel: ", + "Show related videos? ": "Ähnliche Videos anzeigen? ", + "Visual preferences": "Anzeigeeinstellungen", + "Dark mode: ": "Nachtmodus: ", + "Thin mode: ": "Schlanker Modus: ", + "Subscription preferences": "Abonnementeinstellungen", + "Redirect homepage to feed: ": "Startseite zu Feed umleiten: ", + "Number of videos shown in feed: ": "Anzahl von Videos die im Feed angezeigt werden: ", + "Sort videos by: ": "Videos sortieren nach: ", + "published": "veröffentlicht", + "published - reverse": "veröffentlicht - invertiert", + "alphabetically": "alphabetisch", + "alphabetically - reverse": "alphabetisch - invertiert", + "channel name": "Kanalname", + "channel name - reverse": "Kanalname - invertiert", + "Only show latest video from channel: ": "Nur neueste Videos des Kanals anzeigen: ", + "Only show latest unwatched video from channel: ": "Nur neueste ungesehene Videos des Kanals anzeigen: ", + "Only show unwatched: ": "Nur ungesehene anzeigen: ", + "Only show notifications (if there are any): ": "Nur Benachrichtigungen anzeigen (wenn es welche gibt): ", + "Data preferences": "Dateneinstellungen", + "Clear watch history": "Verlauf löschen", + "Import/Export data": "Daten im- exportieren", + "Manage subscriptions": "Abonnements verwalten", + "Watch history": "Verlauf", + "Delete account": "Account löschen", + "Save preferences": "Einstellungen speichern", + "Subscription manager": "Abonnementverwaltung", + "`x` subscriptions": "`x` Abonnements", + "Import/Export": "Importieren/Exportieren", + "unsubscribe": "abbestellen", + "Subscriptions": "Abonnements", + "`x` unseen notifications": "`x` ungesehene Benachrichtigungen", + "search": "Suchen", + "Sign out": "Abmelden", + "Released under the AGPLv3 by Omar Roth.": "Veröffentlicht unter AGPLv3 von Omar Roth.", + "Source available here.": "Quellcode verfügbar hier.", + "Liberapay: ": "Liberapay: ", + "Patreon: ": "Patreon: ", + "BTC: ": "BTC: ", + "BCH: ": "BCH: ", + "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.", + "Trending": "Trending", + "Watch video on Youtube": "Video auf YouTube ansehen", + "Genre: ": "Genre: ", + "License: ": "Lizenz: ", + "Family friendly? ": "Familienfreundlich? ", + "Wilson score: ": "Wilson-Score: ", + "Engagement: ": "Engagement: ", + "Whitelisted regions: ": "Erlaubte Regionen: ", + "Blacklisted regions: ": "Unerlaubte Regionen: ", + "Shared `x`": "Geteilt `x`", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.", + "View YouTube comments": "YouTube Kommentare anzeigen", + "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen", + "View `x` comments": "`x` Kommentare anzeigen", + "View Reddit comments": "Reddit Kommentare anzeigen", + "Hide replies": "Antworten verstecken", + "Show replies": "Antworten anzeigen", + "Incorrect password": "Falsches Passwort", + "Quota exceeded, try again in a few hours": "Kontingent überschritten, versuche es in ein paar Stunden erneut", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Login nicht möglich, stellen Sie sicher dass two-factor Authentifikation (Authentifizierung oder SMS) aktiviert ist.", + "Invalid TFA code": "Ungültiger TFA Code", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "Login fehlgeschlagen. Das kann daran liegen dass two-factor Authentifizierung in ihrem Account nicht aktiviert ist.", + "Invalid answer": "Ungültige Antwort", + "Invalid CAPTCHA": "Ungültiges CAPTCHA", + "CAPTCHA is a required field": "CAPTCHA ist eine erforderliche Eingabe", + "User ID is a required field": "Benutzer ID ist eine erforderliche Eingabe", + "Password is a required field": "Passwort ist eine erforderliche Eingabe", + "Invalid username or password": "Ungültiger Benutzername oder Passwort", + "Please sign in using 'Sign in with Google'": "Bitte melden sie sich mit 'Mit Google anmelden' an", + "Password cannot be empty": "Passwort darf nicht leer sein", + "Password cannot be longer than 55 characters": "Passwort darf nicht länger als 55 Zeichen sein", + "Please sign in": "Bitte anmelden", + "Invidious Private Feed for `x`": "Invidious Persönlicher Feed für `x`", + "channel:`x`": "Kanal:`x`", + "Deleted or invalid channel": "Gelöschter oder ungültiger Kanal", + "This channel does not exist.": "Dieser Kanal existiert nicht.", + "Could not get channel info.": "Kanalinformationen konnten nicht geladen werden.", + "Could not fetch comments": "Kommentare konnten nicht geladen werden", + "View `x` replies": "Zeige `x` Antworten", + "`x` ago": "vor `x`", + "Load more": "Mehr laden", + "`x` points": "`x` Punkte", + "Could not create mix.": "Mix konnte nicht erstellt werden.", + "Playlist is empty": "Playlist ist leer", + "Invalid playlist.": "Ungültige Playlist.", + "Playlist does not exist.": "Playlist existiert nicht.", + "Could not pull trending pages.": "Trending Seiten konnten nicht geladen werden.", + "Hidden field \"challenge\" is a required field": "Verstecktes Feld \"challenge\" ist eine erforderliche Eingabe", + "Hidden field \"token\" is a required field": "Verstecktes Feld \"token\" ist eine erforderliche Eingabe", + "Invalid challenge": "Ungültiger Test", + "Invalid token": "Ungöltige Marke", + "Invalid user": "Ungültiger Benutzer", + "Token is expired, please try again": "Marke ist abgelaufen, bitte erneut versuchen", + "English": "Englisch", + "English (auto-generated)": "Englisch (automatisch erzeugt)", + "Afrikaans": "Afrikaans", + "Albanian": "Albanisch", + "Amharic": "Amharisch", + "Arabic": "Arabisch", + "Armenian": "Armenisch", + "Azerbaijani": "Aserbaidschanisch", + "Bangla": "Bengalisch", + "Basque": "Baskisch", + "Belarusian": "Weißrussisch", + "Bosnian": "Bosnisch", + "Bulgarian": "Bulgarisch", + "Burmese": "Burmesisch", + "Catalan": "Katalanisch", + "Cebuano": "Cebuano", + "Chinese (Simplified)": "Chinesisch (vereinfacht)", + "Chinese (Traditional)": "Chinesisch (traditionell)", + "Corsican": "Korsisch", + "Croatian": "Kroatisch", + "Czech": "Tschechisch", + "Danish": "Dänisch", + "Dutch": "Niederländisch", + "Esperanto": "Esperanto", + "Estonian": "Estnisch", + "Filipino": "Philippinisch", + "Finnish": "Finnisch", + "French": "Französisch", + "Galician": "Galizisch", + "Georgian": "Georgisch", + "German": "Deutsch", + "Greek": "Griechisch", + "Gujarati": "Gujarati", + "Haitian Creole": "Haitianisches Kreolisch", + "Hausa": "Hausa", + "Hawaiian": "Hawaiianisch", + "Hebrew": "Hebräisch", + "Hindi": "Hindi", + "Hmong": "Hmong", + "Hungarian": "Ungarisch", + "Icelandic": "Isländisch", + "Igbo": "Igbo", + "Indonesian": "Indonesisch", + "Irish": "Irisch", + "Italian": "Italienisch", + "Japanese": "Japanisch", + "Javanese": "Javanisch", + "Kannada": "Kannada", + "Kazakh": "Kasachisch", + "Khmer": "Khmer", + "Korean": "Koreanisch", + "Kurdish": "Kurdisch", + "Kyrgyz": "Kirgisisch", + "Lao": "Laotisch", + "Latin": "Lateinisch", + "Latvian": "Lettisch", + "Lithuanian": "Litauisch", + "Luxembourgish": "Luxemburgisch", + "Macedonian": "Mazedonisch", + "Malagasy": "Madagassisch", + "Malay": "Malaiisch", + "Malayalam": "Malayalam", + "Maltese": "Maltesisch", + "Maori": "Maori", + "Marathi": "Marathi", + "Mongolian": "Mongolisch", + "Nepali": "Nepalesisch", + "Norwegian": "Norwegisch", + "Nyanja": "Nyanja", + "Pashto": "Paschtunisch", + "Persian": "Persisch", + "Polish": "Polnisch", + "Portuguese": "Portugiesisch", + "Punjabi": "Pandschabi", + "Romanian": "Rumänisch", + "Russian": "Russisch", + "Samoan": "Samoanisch", + "Scottish Gaelic": "Schottisches Gälisch", + "Serbian": "Serbisch", + "Shona": "Schona", + "Sindhi": "Sindhi", + "Sinhala": "Singhalesisch", + "Slovak": "Slowakisch", + "Slovenian": "Slowenisch", + "Somali": "Somali", + "Southern Sotho": "Südliches Sotho", + "Spanish": "Spanisch", + "Spanish (Latin America)": "Spanisch (Lateinamerika)", + "Sundanese": "Sundanesisch", + "Swahili": "Suaheli", + "Swedish": "Schwedisch", + "Tajik": "Tadschikisch", + "Tamil": "Tamilisch", + "Telugu": "Telugu", + "Thai": "Thailändisch", + "Turkish": "Türkisch", + "Ukrainian": "Ukrainisch", + "Urdu": "Urdu", + "Uzbek": "Usbekisch", + "Vietnamese": "Vietnamesisch", + "Welsh": "Walisisch", + "Western Frisian": "Westfriesisch", + "Xhosa": "Xhosa", + "Yiddish": "Jiddisch", + "Yoruba": "Joruba", + "Zulu": "Zulu", + "`x` years": "`x` Jahre", + "`x` months": "`x` Monate", + "`x` weeks": "`x` Wochen", + "`x` days": "`x` Tage", + "`x` hours": "`x` Stunden", + "`x` minutes": "`x` Minuten", + "`x` seconds": "`x` Sekunden", + "Fallback comments: ": "", + "Popular": "Populär", + "Top": "", + "About": "Über", + "Rating: ": "Bewertung: ", + "Language: ": "Sprache: ", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "" } diff --git a/locales/en-US.json b/locales/en-US.json index 4dcf036c..ccc01458 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -264,6 +264,11 @@ "About": "About", "Rating: ": "Rating: ", "Language: ": "Language: ", + "Default": "Default", + "Music": "Music", + "Gaming": "Gaming", + "News": "News", + "Movies": "Movies", "Download": "Download", "Download as: ": "Download as: " } diff --git a/locales/fr.json b/locales/fr.json index 4f9e3441..8d81d6cc 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -263,5 +263,12 @@ "Top": "Haut", "About": "Sur", "Rating: ": "Évaluation: ", - "Language: ": "Langue: " + "Language: ": "Langue: ", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "" } diff --git a/locales/nb_NO.json b/locales/nb_NO.json index a64e61b7..7fe3e6a8 100644 --- a/locales/nb_NO.json +++ b/locales/nb_NO.json @@ -1,267 +1,274 @@ { - "`x` subscribers": "`x` abonnenter", - "`x` videos": "`x` videoer", - "LIVE": "SANNTIDSVISNING", - "Shared `x` ago": "Delt for `x` siden", - "Unsubscribe": "Opphev abonnement", - "Subscribe": "Abonner", - "Login to subscribe to `x`": "Logg inn for å abonnere på `x`", - "View channel on YouTube": "Vis kanal på YouTube", - "newest": "nyeste", - "oldest": "eldste", - "popular": "populært", - "Preview page": "Forhåndsvis side", - "Next page": "Neste side", - "Clear watch history?": "Tøm visningshistorikk?", - "Yes": "Ja", - "No": "Nei", - "Import and Export Data": "Importer- og eksporter data", - "Import": "Importer", - "Import Invidious data": "Importer Invidious-data", - "Import YouTube subscriptions": "Importer YouTube-abonnenter", - "Import FreeTube subscriptions (.db)": "Importer FreeTube-abonnenter (.db)", - "Import NewPipe subscriptions (.json)": "Importer NewPipe-abonnenter (.json)", - "Import NewPipe data (.zip)": "Importer NewPipe-data (.zip)", - "Export": "Eksporter", - "Export subscriptions as OPML": "Eksporter abonnenter som OPML", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "Eksporter abonnenter som OPML (for NewPipe og FreeTube)", - "Export data as JSON": "Eksporter data som JSON", - "Delete account?": "Slett konto?", - "History": "Historikk", - "Previous page": "Forrige side", - "An alternative front-end to YouTube": "En alternativ grenseflate for YouTube", - "JavaScript license information": "JavaScript-lisensinformasjon", - "source": "kilde", - "Login": "Logg inn", - "Login/Register": "Logg inn/registrer", - "Login to Google": "Logg inn med Google", - "User ID:": "Bruker-ID:", - "Password:": "Passord:", - "Time (h:mm:ss):": "Tid (h:mm:ss):", - "Text CAPTCHA": "Tekst-CAPTCHA", - "Image CAPTCHA": "Bilde-CAPTCHA", - "Sign In": "Innlogging", - "Register": "Registrer", - "Email:": "E-post:", - "Google verification code:": "Google-bekreftelseskode:", - "Preferences": "Innstillinger", - "Player preferences": "Avspillerinnstillinger", - "Always loop: ": "Alltid gjenta: ", - "Autoplay: ": "Autoavspilling: ", - "Autoplay next video: ": "Autospill neste video: ", - "Listen by default: ": "Lytt som forvalg: ", - "Default speed: ": "Forvalgt hastighet: ", - "Preferred video quality: ": "Foretrukket videokvalitet: ", - "Player volume: ": "Avspillerlydstyrke: ", - "Default comments: ": "Forvalgte kommentarer: ", - "Default captions: ": "Forvalgte undertitler: ", - "Fallback captions: ": "Tilbakefallsundertitler: ", - "Show related videos? ": "Vis relaterte videoer? ", - "Visual preferences": "Visuelle innstillinger", - "Dark mode: ": "Mørk drakt: ", - "Thin mode: ": "Tynt modus: ", - "Subscription preferences": "Abonnementsinnstillinger", - "Redirect homepage to feed: ": "Videresend hjemmeside til flyt: ", - "Number of videos shown in feed: ": "Antall videoer å vise i flyt: ", - "Sort videos by: ": "Sorter videoer etter: ", - "published": "publisert", - "published - reverse": "publisert - motsatt", - "alphabetically": "alfabetisk", - "alphabetically - reverse": "alfabetisk - motsatt", - "channel name": "kanalnavn", - "channel name - reverse": "kanalnavn - motsatt", - "Only show latest video from channel: ": "Kun vis siste video fra kanal: ", - "Only show latest unwatched video from channel: ": "Kun vis siste usette video fra kanal: ", - "Only show unwatched: ": "Kun vis usette: ", - "Only show notifications (if there are any): ": "Kun vis merknader (hvis det er noen): ", - "Data preferences": "Datainnstillinger", - "Clear watch history": "Tøm visningshistorikk", - "Import/Export data": "Importer/eksporter data", - "Manage subscriptions": "Behandle abonnementer", - "Watch history": "Visningshistorikk", - "Delete account": "Slett konto", - "Save preferences": "Lagre innstillinger", - "Subscription manager": "Abonnementsbehandler", - "`x` subscriptions": "`x` abonnementer", - "Import/Export": "Importer/eksporter", - "unsubscribe": "opphev abonnement", - "Subscriptions": "Abonnement", - "`x` unseen notifications": "`x` usette merknader", - "search": "søk", - "Sign out": "Logg ut", - "Released under the AGPLv3 by Omar Roth.": "Utgitt med AGPLv3+lisens av Omar Roth.", - "Source available here.": "Kildekode tilgjengelig her.", - "View JavaScript license information.": "Vis JavaScript-lisensinfo.", - "Trending": "Trendsettende", - "Watch video on Youtube": "Vis video på YouTube", - "Genre: ": "Sjanger: ", - "License: ": "Lisens: ", - "Family friendly? ": "Familievennlig? ", - "Wilson score: ": "Wilson-poengsum: ", - "Engagement: ": "Engasjement: ", - "Whitelisted regions: ": "Hvitlistede regioner: ", - "Blacklisted regions: ": "Svartelistede regioner: ", - "Shared `x`": "Delt `x`", - "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hei. Det ser ut til at du har JavaScript avslått. Klikk her for å vise kommentarer, ha i minnet at innlasting tar lengre tid.", - "View YouTube comments": "Vis YouTube-kommentarer", - "View more comments on Reddit": "Vis flere kommenterer på Reddit", - "View `x` comments": "Vis `x` kommentarer", - "View Reddit comments": "Vis Reddit-kommentarer", - "Hide replies": "Skjul svar", - "Show replies": "Vis svar", - "Incorrect password": "Feil passord", - "Quota exceeded, try again in a few hours": "Kvote overskredet, prøv igjen om et par timer", - "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Kunne ikke logge inn, forsikre deg om at tofaktor-identitetsbekreftelse (Authenticator eller SMS) er skrudd på.", - "Invalid TFA code": "Ugyldig tofaktorkode", - "Login failed. This may be because two-factor authentication is not enabled on your account.": "Innlogging mislyktes. Dette kan være fordi tofaktor-identitetsbekreftelse er skrudd av på kontoen din.", - "Invalid answer": "Ugyldig svar", - "Invalid CAPTCHA": "Ugyldig CAPTCHA", - "CAPTCHA is a required field": "CAPTCHA er et påkrevd felt", - "User ID is a required field": "Bruker-ID er et påkrevd felt", - "Password is a required field": "Passord er et påkrevd felt", - "Invalid username or password": "Ugyldig brukernavn eller passord", - "Please sign in using 'Sign in with Google'": "Logg inn ved bruk av \"Google-innlogging\"", - "Password cannot be empty": "Passordet kan ikke være tomt", - "Password cannot be longer than 55 characters": "Passordet kan ikke være lengre enn 55 tegn", - "Please sign in": "Logg inn", - "Invidious Private Feed for `x`": "Ugyldig privat flyt for `x`", - "channel:`x`": "kanal `x`", - "Deleted or invalid channel": "Slettet eller ugyldig kanal", - "This channel does not exist.": "Denne kanalen finnes ikke.", - "Could not get channel info.": "Kunne ikke innhente kanalinfo.", - "Could not fetch comments": "Kunne ikke hente kommentarer", - "View `x` replies": "Vis `x` svar", - "`x` ago": "`x` siden", - "Load more": "Last inn flere", - "`x` points": "`x` poeng", - "Could not create mix.": "Kunne ikke opprette miks.", - "Playlist is empty": "Spillelisten er tom", - "Invalid playlist.": "Ugyldig spilleliste.", - "Playlist does not exist.": "Spillelisten finnes ikke.", - "Could not pull trending pages.": "Kunne ikke hente trendsettende sider.", - "Hidden field \"challenge\" is a required field": "Skjult felt \"utfordring\" er et påkrevd felt", - "Hidden field \"token\" is a required field": "Skjult felt \"symbol\" er et påkrevd felt", - "Invalid challenge": "Ugyldig utfordring", - "Invalid token": "Ugyldig symbol", - "Invalid user": "Ugyldig bruker", - "Token is expired, please try again": "Symbol utløpt, prøv igjen", - "English": "Engelsk", - "English (auto-generated)": "Engelsk (auto-generert)", - "Afrikaans": "", - "Albanian": "Albansk", - "Amharic": "", - "Arabic": "Arabisk", - "Armenian": "Armensk", - "Azerbaijani": "", - "Bangla": "", - "Basque": "", - "Belarusian": "Hviterussisk", - "Bosnian": "Bosnisk", - "Bulgarian": "Bulgarsk", - "Burmese": "Burmesisk", - "Catalan": "Katalansk", - "Cebuano": "", - "Chinese (Simplified)": "", - "Chinese (Traditional)": "", - "Corsican": "", - "Croatian": "", - "Czech": "Tsjekkisk", - "Danish": "Dansk", - "Dutch": "", - "Esperanto": "Esperanto", - "Estonian": "", - "Filipino": "", - "Finnish": "Finsk", - "French": "Fransk", - "Galician": "", - "Georgian": "", - "German": "", - "Greek": "", - "Gujarati": "", - "Haitian Creole": "", - "Hausa": "", - "Hawaiian": "", - "Hebrew": "", - "Hindi": "", - "Hmong": "", - "Hungarian": "Ungarsk", - "Icelandic": "Islandsk", - "Igbo": "", - "Indonesian": "Indonesisk", - "Irish": "Irsk", - "Italian": "Italiensk", - "Japanese": "Japansk", - "Javanese": "", - "Kannada": "", - "Kazakh": "", - "Khmer": "", - "Korean": "", - "Kurdish": "", - "Kyrgyz": "", - "Lao": "", - "Latin": "", - "Latvian": "", - "Lithuanian": "", - "Luxembourgish": "", - "Macedonian": "", - "Malagasy": "", - "Malay": "", - "Malayalam": "", - "Maltese": "", - "Maori": "", - "Marathi": "", - "Mongolian": "", - "Nepali": "", - "Norwegian": "Norsk bokmål", - "Nyanja": "", - "Pashto": "", - "Persian": "", - "Polish": "", - "Portuguese": "", - "Punjabi": "", - "Romanian": "", - "Russian": "Russisk", - "Samoan": "", - "Scottish Gaelic": "", - "Serbian": "Serbisk", - "Shona": "", - "Sindhi": "", - "Sinhala": "", - "Slovak": "Slovakisk", - "Slovenian": "Slovensk", - "Somali": "Somali", - "Southern Sotho": "", - "Spanish": "Spansk", - "Spanish (Latin America)": "", - "Sundanese": "", - "Swahili": "", - "Swedish": "Svensk", - "Tajik": "", - "Tamil": "", - "Telugu": "", - "Thai": "", - "Turkish": "Tyrkisk", - "Ukrainian": "Ukrainsk", - "Urdu": "", - "Uzbek": "", - "Vietnamese": "Vietnamesisk", - "Welsh": "", - "Western Frisian": "", - "Xhosa": "", - "Yiddish": "", - "Yoruba": "", - "Zulu": "", - "`x` years": "`x` år", - "`x` months": "`x` måneder", - "`x` weeks": "`x` uker", - "`x` days": "`x` dager", - "`x` hours": "`x` timer", - "`x` minutes": "`x` minutter", - "`x` seconds": "`x` sekunder", - "Fallback comments: ": "Tilbakefallskommentarer: ", - "Popular": "Pupulært", - "Top": "Topp", - "About": "Om", - "Rating: ": "Vurdering: ", - "Language: ": "Språk: " + "`x` subscribers": "`x` abonnenter", + "`x` videos": "`x` videoer", + "LIVE": "SANNTIDSVISNING", + "Shared `x` ago": "Delt for `x` siden", + "Unsubscribe": "Opphev abonnement", + "Subscribe": "Abonner", + "Login to subscribe to `x`": "Logg inn for å abonnere på `x`", + "View channel on YouTube": "Vis kanal på YouTube", + "newest": "nyeste", + "oldest": "eldste", + "popular": "populært", + "Preview page": "Forhåndsvis side", + "Next page": "Neste side", + "Clear watch history?": "Tøm visningshistorikk?", + "Yes": "Ja", + "No": "Nei", + "Import and Export Data": "Importer- og eksporter data", + "Import": "Importer", + "Import Invidious data": "Importer Invidious-data", + "Import YouTube subscriptions": "Importer YouTube-abonnenter", + "Import FreeTube subscriptions (.db)": "Importer FreeTube-abonnenter (.db)", + "Import NewPipe subscriptions (.json)": "Importer NewPipe-abonnenter (.json)", + "Import NewPipe data (.zip)": "Importer NewPipe-data (.zip)", + "Export": "Eksporter", + "Export subscriptions as OPML": "Eksporter abonnenter som OPML", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Eksporter abonnenter som OPML (for NewPipe og FreeTube)", + "Export data as JSON": "Eksporter data som JSON", + "Delete account?": "Slett konto?", + "History": "Historikk", + "Previous page": "Forrige side", + "An alternative front-end to YouTube": "En alternativ grenseflate for YouTube", + "JavaScript license information": "JavaScript-lisensinformasjon", + "source": "kilde", + "Login": "Logg inn", + "Login/Register": "Logg inn/registrer", + "Login to Google": "Logg inn med Google", + "User ID:": "Bruker-ID:", + "Password:": "Passord:", + "Time (h:mm:ss):": "Tid (h:mm:ss):", + "Text CAPTCHA": "Tekst-CAPTCHA", + "Image CAPTCHA": "Bilde-CAPTCHA", + "Sign In": "Innlogging", + "Register": "Registrer", + "Email:": "E-post:", + "Google verification code:": "Google-bekreftelseskode:", + "Preferences": "Innstillinger", + "Player preferences": "Avspillerinnstillinger", + "Always loop: ": "Alltid gjenta: ", + "Autoplay: ": "Autoavspilling: ", + "Autoplay next video: ": "Autospill neste video: ", + "Listen by default: ": "Lytt som forvalg: ", + "Default speed: ": "Forvalgt hastighet: ", + "Preferred video quality: ": "Foretrukket videokvalitet: ", + "Player volume: ": "Avspillerlydstyrke: ", + "Default comments: ": "Forvalgte kommentarer: ", + "Default captions: ": "Forvalgte undertitler: ", + "Fallback captions: ": "Tilbakefallsundertitler: ", + "Show related videos? ": "Vis relaterte videoer? ", + "Visual preferences": "Visuelle innstillinger", + "Dark mode: ": "Mørk drakt: ", + "Thin mode: ": "Tynt modus: ", + "Subscription preferences": "Abonnementsinnstillinger", + "Redirect homepage to feed: ": "Videresend hjemmeside til flyt: ", + "Number of videos shown in feed: ": "Antall videoer å vise i flyt: ", + "Sort videos by: ": "Sorter videoer etter: ", + "published": "publisert", + "published - reverse": "publisert - motsatt", + "alphabetically": "alfabetisk", + "alphabetically - reverse": "alfabetisk - motsatt", + "channel name": "kanalnavn", + "channel name - reverse": "kanalnavn - motsatt", + "Only show latest video from channel: ": "Kun vis siste video fra kanal: ", + "Only show latest unwatched video from channel: ": "Kun vis siste usette video fra kanal: ", + "Only show unwatched: ": "Kun vis usette: ", + "Only show notifications (if there are any): ": "Kun vis merknader (hvis det er noen): ", + "Data preferences": "Datainnstillinger", + "Clear watch history": "Tøm visningshistorikk", + "Import/Export data": "Importer/eksporter data", + "Manage subscriptions": "Behandle abonnementer", + "Watch history": "Visningshistorikk", + "Delete account": "Slett konto", + "Save preferences": "Lagre innstillinger", + "Subscription manager": "Abonnementsbehandler", + "`x` subscriptions": "`x` abonnementer", + "Import/Export": "Importer/eksporter", + "unsubscribe": "opphev abonnement", + "Subscriptions": "Abonnement", + "`x` unseen notifications": "`x` usette merknader", + "search": "søk", + "Sign out": "Logg ut", + "Released under the AGPLv3 by Omar Roth.": "Utgitt med AGPLv3+lisens av Omar Roth.", + "Source available here.": "Kildekode tilgjengelig her.", + "View JavaScript license information.": "Vis JavaScript-lisensinfo.", + "Trending": "Trendsettende", + "Watch video on Youtube": "Vis video på YouTube", + "Genre: ": "Sjanger: ", + "License: ": "Lisens: ", + "Family friendly? ": "Familievennlig? ", + "Wilson score: ": "Wilson-poengsum: ", + "Engagement: ": "Engasjement: ", + "Whitelisted regions: ": "Hvitlistede regioner: ", + "Blacklisted regions: ": "Svartelistede regioner: ", + "Shared `x`": "Delt `x`", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hei. Det ser ut til at du har JavaScript avslått. Klikk her for å vise kommentarer, ha i minnet at innlasting tar lengre tid.", + "View YouTube comments": "Vis YouTube-kommentarer", + "View more comments on Reddit": "Vis flere kommenterer på Reddit", + "View `x` comments": "Vis `x` kommentarer", + "View Reddit comments": "Vis Reddit-kommentarer", + "Hide replies": "Skjul svar", + "Show replies": "Vis svar", + "Incorrect password": "Feil passord", + "Quota exceeded, try again in a few hours": "Kvote overskredet, prøv igjen om et par timer", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Kunne ikke logge inn, forsikre deg om at tofaktor-identitetsbekreftelse (Authenticator eller SMS) er skrudd på.", + "Invalid TFA code": "Ugyldig tofaktorkode", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "Innlogging mislyktes. Dette kan være fordi tofaktor-identitetsbekreftelse er skrudd av på kontoen din.", + "Invalid answer": "Ugyldig svar", + "Invalid CAPTCHA": "Ugyldig CAPTCHA", + "CAPTCHA is a required field": "CAPTCHA er et påkrevd felt", + "User ID is a required field": "Bruker-ID er et påkrevd felt", + "Password is a required field": "Passord er et påkrevd felt", + "Invalid username or password": "Ugyldig brukernavn eller passord", + "Please sign in using 'Sign in with Google'": "Logg inn ved bruk av \"Google-innlogging\"", + "Password cannot be empty": "Passordet kan ikke være tomt", + "Password cannot be longer than 55 characters": "Passordet kan ikke være lengre enn 55 tegn", + "Please sign in": "Logg inn", + "Invidious Private Feed for `x`": "Ugyldig privat flyt for `x`", + "channel:`x`": "kanal `x`", + "Deleted or invalid channel": "Slettet eller ugyldig kanal", + "This channel does not exist.": "Denne kanalen finnes ikke.", + "Could not get channel info.": "Kunne ikke innhente kanalinfo.", + "Could not fetch comments": "Kunne ikke hente kommentarer", + "View `x` replies": "Vis `x` svar", + "`x` ago": "`x` siden", + "Load more": "Last inn flere", + "`x` points": "`x` poeng", + "Could not create mix.": "Kunne ikke opprette miks.", + "Playlist is empty": "Spillelisten er tom", + "Invalid playlist.": "Ugyldig spilleliste.", + "Playlist does not exist.": "Spillelisten finnes ikke.", + "Could not pull trending pages.": "Kunne ikke hente trendsettende sider.", + "Hidden field \"challenge\" is a required field": "Skjult felt \"utfordring\" er et påkrevd felt", + "Hidden field \"token\" is a required field": "Skjult felt \"symbol\" er et påkrevd felt", + "Invalid challenge": "Ugyldig utfordring", + "Invalid token": "Ugyldig symbol", + "Invalid user": "Ugyldig bruker", + "Token is expired, please try again": "Symbol utløpt, prøv igjen", + "English": "Engelsk", + "English (auto-generated)": "Engelsk (auto-generert)", + "Afrikaans": "", + "Albanian": "Albansk", + "Amharic": "", + "Arabic": "Arabisk", + "Armenian": "Armensk", + "Azerbaijani": "", + "Bangla": "", + "Basque": "", + "Belarusian": "Hviterussisk", + "Bosnian": "Bosnisk", + "Bulgarian": "Bulgarsk", + "Burmese": "Burmesisk", + "Catalan": "Katalansk", + "Cebuano": "", + "Chinese (Simplified)": "", + "Chinese (Traditional)": "", + "Corsican": "", + "Croatian": "", + "Czech": "Tsjekkisk", + "Danish": "Dansk", + "Dutch": "", + "Esperanto": "Esperanto", + "Estonian": "", + "Filipino": "", + "Finnish": "Finsk", + "French": "Fransk", + "Galician": "", + "Georgian": "", + "German": "", + "Greek": "", + "Gujarati": "", + "Haitian Creole": "", + "Hausa": "", + "Hawaiian": "", + "Hebrew": "", + "Hindi": "", + "Hmong": "", + "Hungarian": "Ungarsk", + "Icelandic": "Islandsk", + "Igbo": "", + "Indonesian": "Indonesisk", + "Irish": "Irsk", + "Italian": "Italiensk", + "Japanese": "Japansk", + "Javanese": "", + "Kannada": "", + "Kazakh": "", + "Khmer": "", + "Korean": "", + "Kurdish": "", + "Kyrgyz": "", + "Lao": "", + "Latin": "", + "Latvian": "", + "Lithuanian": "", + "Luxembourgish": "", + "Macedonian": "", + "Malagasy": "", + "Malay": "", + "Malayalam": "", + "Maltese": "", + "Maori": "", + "Marathi": "", + "Mongolian": "", + "Nepali": "", + "Norwegian": "Norsk bokmål", + "Nyanja": "", + "Pashto": "", + "Persian": "", + "Polish": "", + "Portuguese": "", + "Punjabi": "", + "Romanian": "", + "Russian": "Russisk", + "Samoan": "", + "Scottish Gaelic": "", + "Serbian": "Serbisk", + "Shona": "", + "Sindhi": "", + "Sinhala": "", + "Slovak": "Slovakisk", + "Slovenian": "Slovensk", + "Somali": "Somali", + "Southern Sotho": "", + "Spanish": "Spansk", + "Spanish (Latin America)": "", + "Sundanese": "", + "Swahili": "", + "Swedish": "Svensk", + "Tajik": "", + "Tamil": "", + "Telugu": "", + "Thai": "", + "Turkish": "Tyrkisk", + "Ukrainian": "Ukrainsk", + "Urdu": "", + "Uzbek": "", + "Vietnamese": "Vietnamesisk", + "Welsh": "", + "Western Frisian": "", + "Xhosa": "", + "Yiddish": "", + "Yoruba": "", + "Zulu": "", + "`x` years": "`x` år", + "`x` months": "`x` måneder", + "`x` weeks": "`x` uker", + "`x` days": "`x` dager", + "`x` hours": "`x` timer", + "`x` minutes": "`x` minutter", + "`x` seconds": "`x` sekunder", + "Fallback comments: ": "Tilbakefallskommentarer: ", + "Popular": "Pupulært", + "Top": "Topp", + "About": "Om", + "Rating: ": "Vurdering: ", + "Language: ": "Språk: ", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "" } diff --git a/locales/nl.json b/locales/nl.json index b7317e5f..de681e71 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -263,5 +263,12 @@ "Top": "", "About": "", "Rating: ": "", - "Language: ": "" + "Language: ": "", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "" } diff --git a/locales/pl.json b/locales/pl.json index d0686c72..497e098d 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -263,5 +263,12 @@ "Top": "", "About": "", "Rating: ": "", - "Language: ": "" + "Language: ": "", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "" } diff --git a/locales/ru.json b/locales/ru.json index e7b659b7..c55c63d8 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -1,273 +1,280 @@ { - "`x` subscribers": "`x` подписчиков", - "`x` videos": "`x` видео", - "LIVE": "ПРЯМОЙ ЭФИР", - "Shared `x` ago": "Опубликовано `x` назад", - "Unsubscribe": "Отписаться", - "Subscribe": "Подписаться", - "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`", - "View channel on YouTube": "Канал на YouTube", - "newest": "новые", - "oldest": "старые", - "popular": "популярные", - "Preview page": "Предварительный просмотр", - "Next page": "Следующая страница", - "Clear watch history?": "Очистить историю просмотров?", - "Yes": "Да", - "No": "Нет", - "Import and Export Data": "Импорт и экспорт данных", - "Import": "Импорт", - "Import Invidious data": "Импортировать данные Invidious", - "Import YouTube subscriptions": "Импортировать YouTube подписки", - "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)", - "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)", - "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)", - "Export": "Экспорт", - "Export subscriptions as OPML": "Экспортировать подписки в OPML", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)", - "Export data as JSON": "Экспортировать данные в JSON", - "Delete account?": "Удалить аккаунт?", - "History": "История", - "Previous page": "Предыдущая страница", - "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube", - "JavaScript license information": "Лицензии JavaScript", - "source": "источник", - "Login": "Войти", - "Login/Register": "Войти/Регистрация", - "Login to Google": "Войти через Google", - "User ID:": "ID пользователя:", - "Password:": "Пароль:", - "Time (h:mm:ss):": "Время (ч:мм:сс):", - "Text CAPTCHA": "Текст капчи", - "Image CAPTCHA": "Изображение капчи", - "Sign In": "Войти", - "Register": "Регистрация", - "Email:": "Эл. почта:", - "Google verification code:": "Код подтверждения Google:", - "Preferences": "Настройки", - "Player preferences": "Настройки проигрывателя", - "Always loop: ": "Всегда повторять: ", - "Autoplay: ": "Автовоспроизведение: ", - "Autoplay next video: ": "Автовоспроизведение следующего видео: ", - "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ", - "Default speed: ": "Скорость по-умолчанию: ", - "Preferred video quality: ": "Предпочтительное качество видео: ", - "Player volume: ": "Громкость воспроизведения: ", - "Default comments: ": "Источник комментариев: ", - "youtube": "YouTube", - "reddit": "Reddit", - "Default captions: ": "Субтитры по-умолчанию: ", - "Fallback captions: ": "Резервные субтитры: ", - "Show related videos? ": "Показывать похожие видео? ", - "Visual preferences": "Визуальные настройки", - "Dark mode: ": "Темная тема: ", - "Thin mode: ": "Облегченный режим: ", - "Subscription preferences": "Настройки подписок", - "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ", - "Number of videos shown in feed: ": "Число видео в ленте: ", - "Sort videos by: ": "Сортировать видео по: ", - "published": "дате публикации", - "published - reverse": "дате - обратный порядок", - "alphabetically": "алфавиту", - "alphabetically - reverse": "алфавиту - обратный порядок", - "channel name": "имени канала", - "channel name - reverse": "имени канала - обратный порядок", - "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ", - "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ", - "Only show unwatched: ": "Отображать только непросмотренные видео: ", - "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ", - "Data preferences": "Настройки данных", - "Clear watch history": "Очистить историю просмотра", - "Import/Export data": "Импорт/Экспорт данных", - "Manage subscriptions": "Управление подписками", - "Watch history": "История просмотров", - "Delete account": "Удалить аккаунт", - "Save preferences": "Сохранить настройки", - "Subscription manager": "Менеджер подписок", - "`x` subscriptions": "`x` подписок", - "Import/Export": "Импорт/Экспорт", - "unsubscribe": "отписаться", - "Subscriptions": "Подписки", - "`x` unseen notifications": "`x` новых оповещений", - "search": "поиск", - "Sign out": "Выйти", - "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.", - "Source available here.": "Исходный код доступен здесь.", - "Liberapay: ": "Liberapay: ", - "Patreon: ": "Patreon: ", - "BTC: ": "BTC: ", - "BCH: ": "BCH: ", - "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.", - "Trending": "В тренде", - "Watch video on Youtube": "Смотреть на YouTube", - "Genre: ": "Жанр: ", - "License: ": "Лицензия: ", - "Family friendly? ": "Семейный просмотр: ", - "Wilson score: ": "Рейтинг Вильсона: ", - "Engagement: ": "Вовлеченность: ", - "Whitelisted regions: ": "Доступно для: ", - "Blacklisted regions: ": "Недоступно для: ", - "Shared `x`": "Опубликовано `x`", - "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).", - "View YouTube comments": "Смотреть комментарии с YouTube", - "View more comments on Reddit": "Больше комментариев на Reddit", - "View `x` comments": "Показать `x` комментариев", - "View Reddit comments": "Смотреть комментарии с Reddit", - "Hide replies": "Скрыть ответы", - "Show replies": "Показать ответы", - "Incorrect password": "Неправильный пароль", - "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов", - "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.", - "Invalid TFA code": "Неправильный TFA код", - "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.", - "Invalid answer": "Неверный ответ", - "Invalid CAPTCHA": "Неверная капча", - "CAPTCHA is a required field": "Необходимо ввести капчу", - "User ID is a required field": "Необходимо ввести идентификатор пользователя", - "Password is a required field": "Необходимо ввести пароль", - "Invalid username or password": "Недопустимый пароль или имя пользователя", - "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google", - "Password cannot be empty": "Пароль не может быть пустым", - "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов", - "Please sign in": "Пожалуйста, войдите", - "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`", - "channel:`x`": "канал: `x`", - "Deleted or invalid channel": "Канал удален или не найден", - "This channel does not exist.": "Такой канал не существует.", - "Could not get channel info.": "Невозможно получить информацию о канале.", - "Could not fetch comments": "Невозможно получить комментарии", - "View `x` replies": "Показать `x` ответов", - "`x` ago": "`x` назад", - "Load more": "Загрузить больше", - "`x` points": "`x` очков", - "Could not create mix.": "Невозможно создать \"микс\".", - "Playlist is empty": "Плейлист пуст", - "Invalid playlist.": "Некорректный плейлист.", - "Playlist does not exist.": "Плейлист не существует.", - "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".", - "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"", - "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"", - "Invalid challenge": "Неправильный ответ в \"challenge\"", - "Invalid token": "Неправильный токен", - "Invalid user": "Недопустимое имя пользователя", - "Token is expired, please try again": "Срок действия токена истек, попробуйте позже", - "English": "Английский", - "English (auto-generated)": "Английский (созданы автоматически)", - "Afrikaans": "", - "Albanian": "", - "Amharic": "", - "Arabic": "", - "Armenian": "", - "Azerbaijani": "", - "Bangla": "", - "Basque": "", - "Belarusian": "", - "Bosnian": "", - "Bulgarian": "", - "Burmese": "", - "Catalan": "", - "Cebuano": "", - "Chinese (Simplified)": "", - "Chinese (Traditional)": "", - "Corsican": "", - "Croatian": "", - "Czech": "", - "Danish": "", - "Dutch": "", - "Esperanto": "", - "Estonian": "", - "Filipino": "", - "Finnish": "", - "French": "", - "Galician": "", - "Georgian": "", - "German": "", - "Greek": "", - "Gujarati": "", - "Haitian Creole": "", - "Hausa": "", - "Hawaiian": "", - "Hebrew": "", - "Hindi": "", - "Hmong": "", - "Hungarian": "", - "Icelandic": "", - "Igbo": "", - "Indonesian": "", - "Irish": "", - "Italian": "", - "Japanese": "", - "Javanese": "", - "Kannada": "", - "Kazakh": "", - "Khmer": "", - "Korean": "", - "Kurdish": "", - "Kyrgyz": "", - "Lao": "", - "Latin": "", - "Latvian": "", - "Lithuanian": "", - "Luxembourgish": "", - "Macedonian": "", - "Malagasy": "", - "Malay": "", - "Malayalam": "", - "Maltese": "", - "Maori": "", - "Marathi": "", - "Mongolian": "", - "Nepali": "", - "Norwegian": "", - "Nyanja": "", - "Pashto": "", - "Persian": "", - "Polish": "", - "Portuguese": "", - "Punjabi": "", - "Romanian": "", - "Russian": "", - "Samoan": "", - "Scottish Gaelic": "", - "Serbian": "", - "Shona": "", - "Sindhi": "", - "Sinhala": "", - "Slovak": "", - "Slovenian": "", - "Somali": "", - "Southern Sotho": "", - "Spanish": "", - "Spanish (Latin America)": "", - "Sundanese": "", - "Swahili": "", - "Swedish": "", - "Tajik": "", - "Tamil": "", - "Telugu": "", - "Thai": "", - "Turkish": "", - "Ukrainian": "", - "Urdu": "", - "Uzbek": "", - "Vietnamese": "", - "Welsh": "", - "Western Frisian": "", - "Xhosa": "", - "Yiddish": "", - "Yoruba": "", - "Zulu": "", - "`x` years": "`x` лет", - "`x` months": "`x` месяцев", - "`x` weeks": "`x` недель", - "`x` days": "`x` дней", - "`x` hours": "`x` часов", - "`x` minutes": "`x` минут", - "`x` seconds": "`x` секунд", - "Fallback comments: ": "Резервные комментарии: ", - "Popular": "Популярное", - "Top": "Топ", - "About": "О сайте", - "Rating: ": "Рейтинг: ", - "Language: ": "Язык: " + "`x` subscribers": "`x` подписчиков", + "`x` videos": "`x` видео", + "LIVE": "ПРЯМОЙ ЭФИР", + "Shared `x` ago": "Опубликовано `x` назад", + "Unsubscribe": "Отписаться", + "Subscribe": "Подписаться", + "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`", + "View channel on YouTube": "Канал на YouTube", + "newest": "новые", + "oldest": "старые", + "popular": "популярные", + "Preview page": "Предварительный просмотр", + "Next page": "Следующая страница", + "Clear watch history?": "Очистить историю просмотров?", + "Yes": "Да", + "No": "Нет", + "Import and Export Data": "Импорт и экспорт данных", + "Import": "Импорт", + "Import Invidious data": "Импортировать данные Invidious", + "Import YouTube subscriptions": "Импортировать YouTube подписки", + "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)", + "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)", + "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)", + "Export": "Экспорт", + "Export subscriptions as OPML": "Экспортировать подписки в OPML", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)", + "Export data as JSON": "Экспортировать данные в JSON", + "Delete account?": "Удалить аккаунт?", + "History": "История", + "Previous page": "Предыдущая страница", + "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube", + "JavaScript license information": "Лицензии JavaScript", + "source": "источник", + "Login": "Войти", + "Login/Register": "Войти/Регистрация", + "Login to Google": "Войти через Google", + "User ID:": "ID пользователя:", + "Password:": "Пароль:", + "Time (h:mm:ss):": "Время (ч:мм:сс):", + "Text CAPTCHA": "Текст капчи", + "Image CAPTCHA": "Изображение капчи", + "Sign In": "Войти", + "Register": "Регистрация", + "Email:": "Эл. почта:", + "Google verification code:": "Код подтверждения Google:", + "Preferences": "Настройки", + "Player preferences": "Настройки проигрывателя", + "Always loop: ": "Всегда повторять: ", + "Autoplay: ": "Автовоспроизведение: ", + "Autoplay next video: ": "Автовоспроизведение следующего видео: ", + "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ", + "Default speed: ": "Скорость по-умолчанию: ", + "Preferred video quality: ": "Предпочтительное качество видео: ", + "Player volume: ": "Громкость воспроизведения: ", + "Default comments: ": "Источник комментариев: ", + "youtube": "YouTube", + "reddit": "Reddit", + "Default captions: ": "Субтитры по-умолчанию: ", + "Fallback captions: ": "Резервные субтитры: ", + "Show related videos? ": "Показывать похожие видео? ", + "Visual preferences": "Визуальные настройки", + "Dark mode: ": "Темная тема: ", + "Thin mode: ": "Облегченный режим: ", + "Subscription preferences": "Настройки подписок", + "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ", + "Number of videos shown in feed: ": "Число видео в ленте: ", + "Sort videos by: ": "Сортировать видео по: ", + "published": "дате публикации", + "published - reverse": "дате - обратный порядок", + "alphabetically": "алфавиту", + "alphabetically - reverse": "алфавиту - обратный порядок", + "channel name": "имени канала", + "channel name - reverse": "имени канала - обратный порядок", + "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ", + "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ", + "Only show unwatched: ": "Отображать только непросмотренные видео: ", + "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ", + "Data preferences": "Настройки данных", + "Clear watch history": "Очистить историю просмотра", + "Import/Export data": "Импорт/Экспорт данных", + "Manage subscriptions": "Управление подписками", + "Watch history": "История просмотров", + "Delete account": "Удалить аккаунт", + "Save preferences": "Сохранить настройки", + "Subscription manager": "Менеджер подписок", + "`x` subscriptions": "`x` подписок", + "Import/Export": "Импорт/Экспорт", + "unsubscribe": "отписаться", + "Subscriptions": "Подписки", + "`x` unseen notifications": "`x` новых оповещений", + "search": "поиск", + "Sign out": "Выйти", + "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.", + "Source available here.": "Исходный код доступен здесь.", + "Liberapay: ": "Liberapay: ", + "Patreon: ": "Patreon: ", + "BTC: ": "BTC: ", + "BCH: ": "BCH: ", + "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.", + "Trending": "В тренде", + "Watch video on Youtube": "Смотреть на YouTube", + "Genre: ": "Жанр: ", + "License: ": "Лицензия: ", + "Family friendly? ": "Семейный просмотр: ", + "Wilson score: ": "Рейтинг Вильсона: ", + "Engagement: ": "Вовлеченность: ", + "Whitelisted regions: ": "Доступно для: ", + "Blacklisted regions: ": "Недоступно для: ", + "Shared `x`": "Опубликовано `x`", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).", + "View YouTube comments": "Смотреть комментарии с YouTube", + "View more comments on Reddit": "Больше комментариев на Reddit", + "View `x` comments": "Показать `x` комментариев", + "View Reddit comments": "Смотреть комментарии с Reddit", + "Hide replies": "Скрыть ответы", + "Show replies": "Показать ответы", + "Incorrect password": "Неправильный пароль", + "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.", + "Invalid TFA code": "Неправильный TFA код", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.", + "Invalid answer": "Неверный ответ", + "Invalid CAPTCHA": "Неверная капча", + "CAPTCHA is a required field": "Необходимо ввести капчу", + "User ID is a required field": "Необходимо ввести идентификатор пользователя", + "Password is a required field": "Необходимо ввести пароль", + "Invalid username or password": "Недопустимый пароль или имя пользователя", + "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google", + "Password cannot be empty": "Пароль не может быть пустым", + "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов", + "Please sign in": "Пожалуйста, войдите", + "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`", + "channel:`x`": "канал: `x`", + "Deleted or invalid channel": "Канал удален или не найден", + "This channel does not exist.": "Такой канал не существует.", + "Could not get channel info.": "Невозможно получить информацию о канале.", + "Could not fetch comments": "Невозможно получить комментарии", + "View `x` replies": "Показать `x` ответов", + "`x` ago": "`x` назад", + "Load more": "Загрузить больше", + "`x` points": "`x` очков", + "Could not create mix.": "Невозможно создать \"микс\".", + "Playlist is empty": "Плейлист пуст", + "Invalid playlist.": "Некорректный плейлист.", + "Playlist does not exist.": "Плейлист не существует.", + "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".", + "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"", + "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"", + "Invalid challenge": "Неправильный ответ в \"challenge\"", + "Invalid token": "Неправильный токен", + "Invalid user": "Недопустимое имя пользователя", + "Token is expired, please try again": "Срок действия токена истек, попробуйте позже", + "English": "Английский", + "English (auto-generated)": "Английский (созданы автоматически)", + "Afrikaans": "", + "Albanian": "", + "Amharic": "", + "Arabic": "", + "Armenian": "", + "Azerbaijani": "", + "Bangla": "", + "Basque": "", + "Belarusian": "", + "Bosnian": "", + "Bulgarian": "", + "Burmese": "", + "Catalan": "", + "Cebuano": "", + "Chinese (Simplified)": "", + "Chinese (Traditional)": "", + "Corsican": "", + "Croatian": "", + "Czech": "", + "Danish": "", + "Dutch": "", + "Esperanto": "", + "Estonian": "", + "Filipino": "", + "Finnish": "", + "French": "", + "Galician": "", + "Georgian": "", + "German": "", + "Greek": "", + "Gujarati": "", + "Haitian Creole": "", + "Hausa": "", + "Hawaiian": "", + "Hebrew": "", + "Hindi": "", + "Hmong": "", + "Hungarian": "", + "Icelandic": "", + "Igbo": "", + "Indonesian": "", + "Irish": "", + "Italian": "", + "Japanese": "", + "Javanese": "", + "Kannada": "", + "Kazakh": "", + "Khmer": "", + "Korean": "", + "Kurdish": "", + "Kyrgyz": "", + "Lao": "", + "Latin": "", + "Latvian": "", + "Lithuanian": "", + "Luxembourgish": "", + "Macedonian": "", + "Malagasy": "", + "Malay": "", + "Malayalam": "", + "Maltese": "", + "Maori": "", + "Marathi": "", + "Mongolian": "", + "Nepali": "", + "Norwegian": "", + "Nyanja": "", + "Pashto": "", + "Persian": "", + "Polish": "", + "Portuguese": "", + "Punjabi": "", + "Romanian": "", + "Russian": "", + "Samoan": "", + "Scottish Gaelic": "", + "Serbian": "", + "Shona": "", + "Sindhi": "", + "Sinhala": "", + "Slovak": "", + "Slovenian": "", + "Somali": "", + "Southern Sotho": "", + "Spanish": "", + "Spanish (Latin America)": "", + "Sundanese": "", + "Swahili": "", + "Swedish": "", + "Tajik": "", + "Tamil": "", + "Telugu": "", + "Thai": "", + "Turkish": "", + "Ukrainian": "", + "Urdu": "", + "Uzbek": "", + "Vietnamese": "", + "Welsh": "", + "Western Frisian": "", + "Xhosa": "", + "Yiddish": "", + "Yoruba": "", + "Zulu": "", + "`x` years": "`x` лет", + "`x` months": "`x` месяцев", + "`x` weeks": "`x` недель", + "`x` days": "`x` дней", + "`x` hours": "`x` часов", + "`x` minutes": "`x` минут", + "`x` seconds": "`x` секунд", + "Fallback comments: ": "Резервные комментарии: ", + "Popular": "Популярное", + "Top": "Топ", + "About": "О сайте", + "Rating: ": "Рейтинг: ", + "Language: ": "Язык: ", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "" } From 0fcfb7b82bf30377e09f61e7dca45e030fc0150a Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 23 Jan 2019 23:12:48 -0600 Subject: [PATCH 049/108] Add redirect for legacy '/profile' endpoint --- src/invidious.cr | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/invidious.cr b/src/invidious.cr index 7c98735f..7f77e317 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -2142,6 +2142,16 @@ get "/c/:user" do |env| env.redirect anchor["href"] end +# Legacy endpoint for /user/:username +get "/profile" do |env| + user = env.params.query["user"]? + if !user + env.redirect "/" + else + env.redirect "/user/#{user}" + end +end + get "/user/:user" do |env| user = env.params.url["user"] env.redirect "/channel/#{user}" From 1a9057a175bbf02c6e8c562693f0b12d656923f2 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 24 Jan 2019 00:01:56 -0600 Subject: [PATCH 050/108] Add fix to download widget for titles with unescaped characters --- assets/js/watch.js | 3 ++- src/invidious/views/watch.ecr | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/js/watch.js b/assets/js/watch.js index 3988234a..81fa6288 100644 --- a/assets/js/watch.js +++ b/assets/js/watch.js @@ -51,7 +51,8 @@ function hide_youtube_replies(target) { target.setAttribute("onclick", "show_youtube_replies(this)"); } -function download_video(title) { +function download_video(target) { + var title = target.getAttribute("data-title"); var children = document.getElementById("download_widget").children; var progress = document.getElementById("download-progress"); var url = ""; diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index 3f1ff3bc..d5ab5411 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -75,7 +75,7 @@
- From f455b1208570f903bd1747336d0452ea45973118 Mon Sep 17 00:00:00 2001 From: Esmail EL BoB Date: Thu, 24 Jan 2019 11:03:33 +0200 Subject: [PATCH 051/108] Update ar.json --- locales/ar.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/locales/ar.json b/locales/ar.json index 268be9df..b36f8c37 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -274,5 +274,7 @@ "Music": "الاغانى", "Gaming": "الألعاب", "News": "الأخبار", - "Movies": "الأفلام" + "Movies": "الأفلام", + "Download as: ": "تحميل كـ", + "Download": "تحميل" } From 16a7fcb79b627b5c9103c29b2d4604a0fedcb98c Mon Sep 17 00:00:00 2001 From: Esmail EL BoB Date: Thu, 24 Jan 2019 20:03:19 +0200 Subject: [PATCH 052/108] Update ar.json (#314) --- locales/ar.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/ar.json b/locales/ar.json index 6284043a..55592d2c 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -275,6 +275,6 @@ "Gaming": "الألعاب", "News": "الأخبار", "Movies": "الأفلام", - "Download": "", - "Download as: ": "" + "Download as:": "تحميل كـ", + "Download": "تحميل" } From 75d8c4f5c0b52b0e1743cc5cc12b4c1cc0abaf91 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 24 Jan 2019 12:16:10 -0600 Subject: [PATCH 053/108] Use logger instead of STDOUT --- src/invidious/jobs.cr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/invidious/jobs.cr b/src/invidious/jobs.cr index df02c7fb..81271cb3 100644 --- a/src/invidious/jobs.cr +++ b/src/invidious/jobs.cr @@ -21,7 +21,7 @@ def crawl_videos(db) id = ids[0] video = get_video(id, db) rescue ex - STDOUT << id << " : " << ex.message << "\n" + logger.write("#{id} : #{ex.message}\n") next ensure ids.delete(id) @@ -73,7 +73,7 @@ def refresh_channels(db, max_threads = 1, full_refresh = false) db.exec("UPDATE channels SET updated = $1, author = $2 WHERE id = $3", Time.now, channel.author, id) rescue ex - STDOUT << id << " : " << ex.message << "\n" + logger.write("#{id} : #{ex.message}\n") end active_channel.send(true) @@ -94,7 +94,7 @@ def refresh_videos(db) id = rs.read(String) video = get_video(id, db) rescue ex - STDOUT << id << " : " << ex.message << "\n" + logger.write("#{id} : #{ex.message}\n") next end end @@ -129,7 +129,7 @@ def refresh_feeds(db, max_threads = 1) begin db.exec("REFRESH MATERIALIZED VIEW #{view_name}") rescue ex - STDOUT << "REFRESH " << email << " : " << ex.message << "\n" + logger.write("REFRESH #{email} : #{ex.message}\n") end active_channel.send(true) From 4b60f7ddff900d60a86410d40bdd55f9883b87da Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 24 Jan 2019 12:19:02 -0600 Subject: [PATCH 054/108] Add logger to method calls --- src/invidious.cr | 8 ++++---- src/invidious/jobs.cr | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 7f77e317..1a96b50a 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -108,17 +108,17 @@ LOCALES = { crawl_threads.times do spawn do - crawl_videos(PG_DB) + crawl_videos(PG_DB, logger) end end -refresh_channels(PG_DB, channel_threads, CONFIG.full_refresh) +refresh_channels(PG_DB, logger, channel_threads, CONFIG.full_refresh) -refresh_feeds(PG_DB, feed_threads) +refresh_feeds(PG_DB, logger, feed_threads) video_threads.times do |i| spawn do - refresh_videos(PG_DB) + refresh_videos(PG_DB, logger) end end diff --git a/src/invidious/jobs.cr b/src/invidious/jobs.cr index 81271cb3..f6e2d8fe 100644 --- a/src/invidious/jobs.cr +++ b/src/invidious/jobs.cr @@ -1,4 +1,4 @@ -def crawl_videos(db) +def crawl_videos(db, logger) ids = Deque(String).new random = Random.new @@ -46,7 +46,7 @@ def crawl_videos(db) end end -def refresh_channels(db, max_threads = 1, full_refresh = false) +def refresh_channels(db, logger, max_threads = 1, full_refresh = false) max_channel = Channel(Int32).new spawn do @@ -86,7 +86,7 @@ def refresh_channels(db, max_threads = 1, full_refresh = false) max_channel.send(max_threads) end -def refresh_videos(db) +def refresh_videos(db, logger) loop do db.query("SELECT id FROM videos ORDER BY updated") do |rs| rs.each do @@ -104,7 +104,7 @@ def refresh_videos(db) end end -def refresh_feeds(db, max_threads = 1) +def refresh_feeds(db, logger, max_threads = 1) max_channel = Channel(Int32).new spawn do From c1081e3df042a6097bc2a0d64d60e4adeba21543 Mon Sep 17 00:00:00 2001 From: Perflyst Date: Thu, 24 Jan 2019 19:31:56 +0100 Subject: [PATCH 055/108] Add links to documentation --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index fd0d05d8..166e050c 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ Onion links: - kgg2m7yk5aybusll.onion - axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4bzzsg2ii4fv2iid.onion +[Alternative Invidious instances](https://github.com/omarroth/invidious/wiki/Invidious-Instances) + ## Installation ### Docker: @@ -139,6 +141,9 @@ $ shards $ crystal build src/invidious.cr --release ``` +## Update Invidious +You can find information about how to update in the wiki: [Update Invidious](https://github.com/omarroth/invidious/wiki/Update-Invidious) + ## Usage: ```bash @@ -168,6 +173,9 @@ $ curl -fsSLo- https://raw.githubusercontent.com/samueleaton/sentry/master/insta $ ./sentry ``` +## Documentation +[Documentation](https://github.com/omarroth/invidious/wiki) can be found in the wiki. + ## Extensions - [Alternate Tube Redirector](https://addons.mozilla.org/en-US/firefox/addon/alternate-tube-redirector/): Automatically open Youtube Videos on alternate sites like Invidious or Hooktube. From 952b208a016548ad917737848cf3031e3f8af2d6 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 24 Jan 2019 13:52:33 -0600 Subject: [PATCH 056/108] Add retry for /videoplaybacl --- src/invidious.cr | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 1a96b50a..ad9510c1 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -3644,9 +3644,23 @@ get "/videoplayback" do |env| host = "https://r#{fvip}---#{mn}.googlevideo.com" url = "/videoplayback?#{query_params.to_s}" + headers = env.request.headers + headers.delete("Host") + headers.delete("Cookie") + headers.delete("User-Agent") + headers.delete("Referer") + region = query_params["region"]? - client = make_client(URI.parse(host), proxies, region) - response = client.head(url) + + response = HTTP::Client::Response.new(403) + loop do + begin + client = make_client(URI.parse(host), proxies, region) + response = client.head(url, headers) + break + rescue ex + end + end if response.headers["Location"]? url = URI.parse(response.headers["Location"]) @@ -3664,12 +3678,6 @@ get "/videoplayback" do |env| halt env, status_code: 403 end - headers = env.request.headers - headers.delete("Host") - headers.delete("Cookie") - headers.delete("User-Agent") - headers.delete("Referer") - client = make_client(URI.parse(host), proxies, region) client.get(url, headers) do |response| env.response.status_code = response.status_code From 4c77908bb492e6d9ee567bd4c2b2fe78e63aae33 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 24 Jan 2019 19:02:09 -0600 Subject: [PATCH 057/108] Update postgres entrypoint for docker image --- docker/Dockerfile.postgres | 1 - docker/entrypoint.postgres.sh | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile.postgres b/docker/Dockerfile.postgres index 3186e050..720bdff8 100644 --- a/docker/Dockerfile.postgres +++ b/docker/Dockerfile.postgres @@ -2,7 +2,6 @@ FROM postgres:10 ENV POSTGRES_USER postgres -ADD ./setup.sh /setup.sh ADD ./config/sql /config/sql ADD ./docker/entrypoint.postgres.sh /entrypoint.sh diff --git a/docker/entrypoint.postgres.sh b/docker/entrypoint.postgres.sh index 2f3ae65f..9a258dd6 100755 --- a/docker/entrypoint.postgres.sh +++ b/docker/entrypoint.postgres.sh @@ -10,7 +10,14 @@ if [ ! -f /var/lib/postgresql/data/setupFinished ]; then sleep 5 done >&2 echo "### importing table schemas" - su postgres -c "/setup.sh" && touch /var/lib/postgresql/data/setupFinished + su postgres -c 'createdb invidious' + su postgres -c 'psql -c "CREATE USER kemal WITH PASSWORD '"'kemal'"'"' + su postgres -c 'psql invidious < config/sql/channels.sql' + su postgres -c 'psql invidious < config/sql/videos.sql' + su postgres -c 'psql invidious < config/sql/channel_videos.sql' + su postgres -c 'psql invidious < config/sql/users.sql' + su postgres -c 'psql invidious < config/sql/nonces.sql' + touch /var/lib/postgresql/data/setupFinished echo "### invidious database setup finished" exit fi From 1af86f6afbba9a479f8d6a615c9f2a9d263d8c18 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 24 Jan 2019 20:21:19 -0600 Subject: [PATCH 058/108] Add sleep to popular_videos and top_videos --- src/invidious.cr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/invidious.cr b/src/invidious.cr index ad9510c1..f3404d23 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -126,6 +126,8 @@ top_videos = [] of Video spawn do pull_top_videos(CONFIG, PG_DB) do |videos| top_videos = videos + sleep 1.minutes + Fiber.yield end end @@ -133,6 +135,8 @@ popular_videos = [] of ChannelVideo spawn do pull_popular_videos(PG_DB) do |videos| popular_videos = videos + sleep 1.minutes + Fiber.yield end end From 3751d11a0b534d215f57d5bb8c2692b7880e4cdc Mon Sep 17 00:00:00 2001 From: Esmail EL BoB Date: Fri, 25 Jan 2019 12:46:53 +0200 Subject: [PATCH 059/108] Update ar.json --- locales/ar.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/ar.json b/locales/ar.json index 55592d2c..b36f8c37 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -275,6 +275,6 @@ "Gaming": "الألعاب", "News": "الأخبار", "Movies": "الأفلام", - "Download as:": "تحميل كـ", + "Download as: ": "تحميل كـ", "Download": "تحميل" } From 586c0a05791b1d6b8a3ecf4facbc7aa8dc3fc636 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Fri, 25 Jan 2019 10:38:28 -0600 Subject: [PATCH 060/108] Add error message for unavailable endpoint /api/v1/insights/:id --- src/invidious.cr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/invidious.cr b/src/invidious.cr index f3404d23..d44bb069 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -2385,6 +2385,9 @@ get "/api/v1/insights/:id" do |env| id = env.params.url["id"] env.response.content_type = "application/json" + error_message = {"error" => "YouTube has removed publicly-available analytics."}.to_json + halt env, status_code: 503, response: error_message + client = make_client(YT_URL) headers = HTTP::Headers.new html = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1") From ba36ab95592b69dab0443741fa4dce77057cd00e Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Fri, 25 Jan 2019 10:50:18 -0600 Subject: [PATCH 061/108] Add 'pretty=1' option to API endpoints --- src/invidious.cr | 102 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 19 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index d44bb069..69b825ce 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -2262,7 +2262,11 @@ get "/api/v1/captions/:id" do |env| end end - next response + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + next JSON.parse(response).to_pretty_json + else + next response + end end env.response.content_type = "text/vtt" @@ -2368,13 +2372,24 @@ get "/api/v1/comments/:id" do |env| if format == "json" reddit_thread = JSON.parse(reddit_thread.to_json).as_h reddit_thread["comments"] = JSON.parse(comments.to_json) - next reddit_thread.to_json + + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + next reddit_thread.to_pretty_json + else + next reddit_thread.to_json + end else - next { + response = { "title" => reddit_thread.title, "permalink" => reddit_thread.permalink, "contentHtml" => content_html, - }.to_json + } + + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + next response.to_pretty_json + else + next response.to_json + end end end end @@ -2454,14 +2469,20 @@ get "/api/v1/insights/:id" do |env| avg_view_duration_seconds = html_content.xpath_node(%q(//div[@id="stats-chart-tab-watch-time"]/span/span[2])).not_nil!.content avg_view_duration_seconds = decode_length_seconds(avg_view_duration_seconds) - { + response = { "viewCount" => view_count, "timeWatchedText" => time_watched, "subscriptionsDriven" => subscriptions_driven, "shares" => shares, "avgViewDurationSeconds" => avg_view_duration_seconds, "graphData" => graph_data, - }.to_json + } + + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + next response.to_pretty_json + else + next response.to_json + end end get "/api/v1/videos/:id" do |env| @@ -2667,12 +2688,18 @@ get "/api/v1/videos/:id" do |env| end end - video_info + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(video_info).to_pretty_json + else + video_info + end end get "/api/v1/trending" do |env| locale = LOCALES[env.get("locale").as(String)]? + env.response.content_type = "application/json" + region = env.params.query["region"]? trending_type = env.params.query["type"]? @@ -2712,13 +2739,18 @@ get "/api/v1/trending" do |env| end end - env.response.content_type = "application/json" - videos + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(videos).to_pretty_json + else + videos + end end get "/api/v1/popular" do |env| locale = LOCALES[env.get("locale").as(String)]? + env.response.content_type = "application/json" + videos = JSON.build do |json| json.array do popular_videos.each do |video| @@ -2741,13 +2773,18 @@ get "/api/v1/popular" do |env| end end - env.response.content_type = "application/json" - videos + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(videos).to_pretty_json + else + videos + end end get "/api/v1/top" do |env| locale = LOCALES[env.get("locale").as(String)]? + env.response.content_type = "application/json" + videos = JSON.build do |json| json.array do top_videos.each do |video| @@ -2777,8 +2814,11 @@ get "/api/v1/top" do |env| end end - env.response.content_type = "application/json" - videos + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(videos).to_pretty_json + else + videos + end end get "/api/v1/channels/:ucid" do |env| @@ -2975,7 +3015,11 @@ get "/api/v1/channels/:ucid" do |env| end end - channel_info + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(channel_info).to_pretty_json + else + channel_info + end end ["/api/v1/channels/:ucid/videos", "/api/v1/channels/videos/:ucid"].each do |route| @@ -3040,7 +3084,11 @@ end end end - result + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(result).to_pretty_json + else + result + end end end @@ -3141,7 +3189,11 @@ get "/api/v1/channels/search/:ucid" do |env| end end - response + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(response).to_pretty_json + else + response + end end get "/api/v1/search" do |env| @@ -3266,7 +3318,11 @@ get "/api/v1/search" do |env| end end - response + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(response).to_pretty_json + else + response + end end get "/api/v1/playlists/:plid" do |env| @@ -3365,7 +3421,11 @@ get "/api/v1/playlists/:plid" do |env| }.to_json end - response + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(response).to_pretty_json + else + response + end end get "/api/v1/mixes/:rdid" do |env| @@ -3439,7 +3499,11 @@ get "/api/v1/mixes/:rdid" do |env| }.to_json end - response + if env.params.query["pretty"]? && env.params.query["pretty"] == "1" + JSON.parse(response).to_pretty_json + else + response + end end get "/api/manifest/dash/id/videoplayback" do |env| From 1f6078cf256d11b8c39608cda53fc6bc2c4bf440 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Fri, 25 Jan 2019 11:35:25 -0600 Subject: [PATCH 062/108] Fix links to invalid genre channels --- src/invidious/videos.cr | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 18a2ff8a..ec911e3f 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -670,13 +670,20 @@ def fetch_video(id, proxies, region) genre = html.xpath_node(%q(//meta[@itemprop="genre"])).try &.["content"] genre ||= "" - genre_url = html.xpath_node(%(//a[text()="#{genre}"])).try &.["href"] + genre_url = html.xpath_node(%(//ul[contains(@class, "watch-info-tag-list")]/li/a[text()="#{genre}"])).try &.["href"] + + # Sometimes YouTube tries to link to invalid/missing channels, so we fix that here case genre + when "Education" + genre_url = "/channel/UCdxpofrI-dO6oYfsqHDHphw" + when "Gaming" + genre_url = "/channel/UCOpNcN46UbXVtpKMrmU4Abg" when "Movies" genre_url = "/channel/UClgRkhTL3_hImCAmdLfDE4g" - when "Education" - # Education channel is linked but does not exist - genre_url = "/channel/UC3yA8nDwraeOfnYfBWun83g" + when "Nonprofits & Activism" + genre_url = "/channel/UCfFyYRYslvuhwMDnx6KjUvw" + when "Trailers" + genre_url = "/channel/UClgRkhTL3_hImCAmdLfDE4g" end genre_url ||= "" From 898b768b306f4a60d4fe8549affe713a6162c185 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Fri, 25 Jan 2019 12:26:16 -0600 Subject: [PATCH 063/108] Fallback on ucid for channel search when author contains hyphen --- src/invidious.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious.cr b/src/invidious.cr index 69b825ce..5bd20e13 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -2192,7 +2192,7 @@ get "/channel/:ucid" do |env| end if !auto_generated - if author.includes? " " + if author.includes?(" ") || author.includes?("-") env.set "search", "channel:#{ucid} " else env.set "search", "channel:#{author.downcase} " From 45b53b89025a15d54c50c3f3e8806b10c96df1c5 Mon Sep 17 00:00:00 2001 From: dimqua Date: Sat, 26 Jan 2019 19:12:13 +0300 Subject: [PATCH 064/108] fix file path --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 166e050c..fc8bf3cf 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ $ exit #### systemd service ```bash -$ sudo cp invidious.service /etc/systemd/system/invidious.service +$ sudo cp /home/invidious/invidious/invidious.service /etc/systemd/system/invidious.service $ sudo systemctl enable invidious.service $ sudo systemctl start invidious.service ``` From a9f5b84c7f8520d2e2e8bb03ea931b7306dc8242 Mon Sep 17 00:00:00 2001 From: Perflyst Date: Sat, 26 Jan 2019 19:52:27 +0100 Subject: [PATCH 065/108] Remove Extensions from README.md --- README.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/README.md b/README.md index 166e050c..1f583621 100644 --- a/README.md +++ b/README.md @@ -177,12 +177,7 @@ $ ./sentry [Documentation](https://github.com/omarroth/invidious/wiki) can be found in the wiki. ## Extensions - -- [Alternate Tube Redirector](https://addons.mozilla.org/en-US/firefox/addon/alternate-tube-redirector/): Automatically open Youtube Videos on alternate sites like Invidious or Hooktube. -- [Invidious Redirect](https://greasyfork.org/en/scripts/370461-invidious-redirect): Redirects Youtube URLs to Invidio.us (userscript) -- [iPhone Redirector Shortcut](https://www.icloud.com/shortcuts/6bbf26d989cf4d07a5fe1626efbc0950): Automatically open YouTube videos in Invidious (iPhone shortcut) -- [Youtube to Invidious](https://greasyfork.org/en/scripts/375264-youtube-to-invidious): Scan page for youtube embeds and urls and replace with Invidious (userscript) -- [Invidious Downloader](https://github.com/erupete/InvidiousDownloader): Tampermonkey userscript for downloading videos or audio on Invidious (userscript) +Extensions for Invidious and for integrating Invidious into other projects [are in the wiki](https://github.com/omarroth/invidious/wiki/Extensions) ## Made with Invidious From 48fc0949cc4e89a94fd326567435d98a20a4ed9a Mon Sep 17 00:00:00 2001 From: dimqua Date: Sun, 27 Jan 2019 20:41:43 +0300 Subject: [PATCH 066/108] fix broken link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9517fb4c..db4120da 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ $ crystal build src/invidious.cr --release ``` ## Update Invidious -You can find information about how to update in the wiki: [Update Invidious](https://github.com/omarroth/invidious/wiki/Update-Invidious) +You can find information about how to update in the wiki: [Updating](https://github.com/omarroth/invidious/wiki/Updating). ## Usage: From a9aae6b36c270643461a80b9987ed611077498af Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sun, 27 Jan 2019 20:35:32 -0600 Subject: [PATCH 067/108] Add internal redirect for video URLs --- src/invidious.cr | 25 +++++++++++++++++++++++ src/invidious/views/components/player.ecr | 6 +++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 5bd20e13..b90e9913 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -3652,6 +3652,31 @@ get "/api/manifest/hls_playlist/*" do |env| manifest end +# YouTube /videoplayback links expire after 6 hours, +# so we have a mechanism here to redirect to the latest version +get "/latest_version" do |env| + id = env.params.query["id"]? + itag = env.params.query["itag"]? + + if !id || !itag + halt env, status_code: 400 + end + + video = get_video(id, PG_DB, proxies) + + fmt_stream = video.fmt_stream(decrypt_function) + adaptive_fmts = video.adaptive_fmts(decrypt_function) + + urls = (fmt_stream + adaptive_fmts).select { |fmt| fmt["itag"] == itag } + if urls.empty? + halt env, status_code: 404 + elsif urls.size > 1 + halt env, status_code: 409 + end + + env.redirect urls[0]["url"] +end + options "/videoplayback" do |env| env.response.headers["Access-Control-Allow-Origin"] = "*" env.response.headers["Access-Control-Allow-Methods"] = "GET, OPTIONS" diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index cb7c1276..f5e6f506 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -11,7 +11,7 @@ <% else %> <% if params[:listen] %> <% audio_streams.each_with_index do |fmt, i| %> - " type='<%= fmt["type"] %>' label="<%= fmt["bitrate"] %>k" selected="<%= i == 0 ? true : false %>"> + " type='<%= fmt["type"] %>' label="<%= fmt["bitrate"] %>k" selected="<%= i == 0 ? true : false %>"> <% end %> <% else %> <% if params[:quality] == "dash" %> @@ -19,9 +19,9 @@ <% end %> <% fmt_stream.each_with_index do |fmt, i| %> <% if params[:quality] %> - " type='<%= fmt["type"] %>' label="<%= fmt["label"] %>" selected="<%= params[:quality] == fmt["label"].split(" - ")[0] %>"> + " type='<%= fmt["type"] %>' label="<%= fmt["label"] %>" selected="<%= params[:quality] == fmt["label"].split(" - ")[0] %>"> <% else %> - " type='<%= fmt["type"] %>' label="<%= fmt["label"] %>" selected="<%= i == 0 ? true : false %>"> + " type='<%= fmt["type"] %>' label="<%= fmt["label"] %>" selected="<%= i == 0 ? true : false %>"> <% end %> <% end %> <% end %> From 6218078c517abe88f8dc6470eb5bc83b12d990d6 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sun, 27 Jan 2019 21:06:28 -0600 Subject: [PATCH 068/108] Pull subscribe widget into separate file --- src/invidious/views/channel.ecr | 67 +---------------- .../views/components/subscribe_widget.ecr | 24 ++++++ .../components/subscribe_widget_script.ecr | 42 +++++++++++ src/invidious/views/watch.ecr | 73 ++----------------- 4 files changed, 78 insertions(+), 128 deletions(-) create mode 100644 src/invidious/views/components/subscribe_widget.ecr create mode 100644 src/invidious/views/components/subscribe_widget_script.ecr diff --git a/src/invidious/views/channel.ecr b/src/invidious/views/channel.ecr index 38e7bc1b..53b71b6f 100644 --- a/src/invidious/views/channel.ecr +++ b/src/invidious/views/channel.ecr @@ -14,30 +14,8 @@
-<% if user %> - <% if subscriptions.includes? ucid %> -

- "> - <%= translate(locale, "Unsubscribe") %> | <%= number_to_short_text(sub_count) %> - -

- <% else %> -

- "> - <%= translate(locale, "Subscribe") %> | <%= number_to_short_text(sub_count) %> - -

- <% end %> -<% else %> -

- "> - <%= translate(locale, "Login to subscribe to `x`", author) %> - -

-<% end %> +<% sub_count_text = number_to_short_text(sub_count) %> +<%= rendered "components/subscribe_widget" %>
@@ -94,43 +72,6 @@
diff --git a/src/invidious/views/components/subscribe_widget.ecr b/src/invidious/views/components/subscribe_widget.ecr new file mode 100644 index 00000000..4f36368f --- /dev/null +++ b/src/invidious/views/components/subscribe_widget.ecr @@ -0,0 +1,24 @@ +<% if user %> + <% if subscriptions.includes? ucid %> +

+ "> + <%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %> + +

+ <% else %> +

+ "> + <%= translate(locale, "Subscribe") %> | <%= sub_count_text %> + +

+ <% end %> +<% else %> +

+ "> + <%= translate(locale, "Login to subscribe to `x`", author) %> + +

+<% end %> diff --git a/src/invidious/views/components/subscribe_widget_script.ecr b/src/invidious/views/components/subscribe_widget_script.ecr new file mode 100644 index 00000000..5180bbb8 --- /dev/null +++ b/src/invidious/views/components/subscribe_widget_script.ecr @@ -0,0 +1,42 @@ +subscribe_button = document.getElementById("subscribe"); +if (subscribe_button.getAttribute('onclick')) { + subscribe_button["href"] = "javascript:void(0)"; +} + +function subscribe() { + var url = "/subscription_ajax?action_create_subscription_to_channel=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>"; + var xhr = new XMLHttpRequest(); + xhr.responseType = "json"; + xhr.timeout = 20000; + xhr.open("GET", url, true); + xhr.send(); + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + subscribe_button = document.getElementById("subscribe"); + subscribe_button.onclick = unsubscribe; + subscribe_button.innerHTML = '<%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %>' + } + } + } +} + +function unsubscribe() { + var url = "/subscription_ajax?action_remove_subscriptions=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>"; + var xhr = new XMLHttpRequest(); + xhr.responseType = "json"; + xhr.timeout = 20000; + xhr.open("GET", url, true); + xhr.send(); + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + subscribe_button = document.getElementById("subscribe"); + subscribe_button.onclick = subscribe; + subscribe_button.innerHTML = '<%= translate(locale, "Subscribe") %> | <%= sub_count_text %>' + } + } + } +} diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index d5ab5411..da45011b 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -117,30 +117,10 @@

<%= video.author %>

- <% if user %> - <% if subscriptions.includes? video.ucid %> -

- "> - <%= translate(locale, "Unsubscribe") %> | <%= video.sub_count_text %> - -

- <% else %> -

- "> - <%= translate(locale, "Subscribe") %> | <%= video.sub_count_text %> - -

- <% end %> - <% else %> -

- "> - <%= translate(locale, "Login to subscribe to `x`", video.author) %> - -

- <% end %> + <% ucid = video.ucid %> + <% author = video.author %> + <% sub_count_text = video.sub_count_text %> + <%= rendered "components/subscribe_widget" %>

<%= translate(locale, "Shared `x`", video.published.to_s("%B %-d, %Y")) %>

@@ -252,48 +232,11 @@ function number_with_separator(val) { return val; } -subscribe_button = document.getElementById("subscribe"); -if (subscribe_button.getAttribute('onclick')) { - subscribe_button["href"] = "javascript:void(0)"; -} +<% ucid = video.ucid %> +<% author = video.author %> +<% sub_count_text = video.sub_count_text %> +<%= rendered "components/subscribe_widget_script" %> -function subscribe() { - var url = "/subscription_ajax?action_create_subscription_to_channel=1&c=<%= video.ucid %>&referer=<%= env.get("current_page") %>"; - var xhr = new XMLHttpRequest(); - xhr.responseType = "json"; - xhr.timeout = 20000; - xhr.open("GET", url, true); - xhr.send(); - - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - if (xhr.status == 200) { - subscribe_button = document.getElementById("subscribe"); - subscribe_button.onclick = unsubscribe; - subscribe_button.innerHTML = '<%= translate(locale, "Unsubscribe") %> | <%= video.sub_count_text %>' - } - } - } -} - -function unsubscribe() { - var url = "/subscription_ajax?action_remove_subscriptions=1&c=<%= video.ucid %>&referer=<%= env.get("current_page") %>"; - var xhr = new XMLHttpRequest(); - xhr.responseType = "json"; - xhr.timeout = 20000; - xhr.open("GET", url, true); - xhr.send(); - - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - if (xhr.status == 200) { - subscribe_button = document.getElementById("subscribe"); - subscribe_button.onclick = subscribe; - subscribe_button.innerHTML = '<%= translate(locale, "Subscribe") %> | <%= video.sub_count_text %>' - } - } - } -} <% if plid %> function get_playlist(timeouts = 0) { From c0fdc28a8439cd9f6255a4c5b84c4fae06b4912b Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sun, 27 Jan 2019 21:20:52 -0600 Subject: [PATCH 069/108] Fix colors and data-url in download widget --- assets/css/default.css | 8 ++++++-- assets/js/watch.js | 2 -- src/invidious.cr | 11 ++++++++++- src/invidious/views/watch.ecr | 8 ++++---- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/assets/css/default.css b/assets/css/default.css index 4f0db4cf..244a5edd 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -22,11 +22,13 @@ div { padding-right: 10px; } +button.pure-button-primary, a.pure-button-primary { background-color: #a0a0a0; color: rgba(35, 35, 35, 1); } +button.pure-button-primary:hover, a.pure-button-primary:hover { background-color: rgba(0, 182, 240, 1); color: #fff; @@ -271,14 +273,16 @@ img.thumbnail { #progress-container { width: 100%; border-radius: 2px; - background: #aaa; + background-color: #a0a0a0; + color: rgba(35, 35, 35, 1); } #download-progress { width: 0%; border-radius: 2px; height: 10px; - background-color: #0078e7; + background-color: rgba(0, 182, 240, 1); + color: #fff; margin-top: 0.5em; margin-bottom: 0.5em; } diff --git a/assets/js/watch.js b/assets/js/watch.js index 81fa6288..0126c586 100644 --- a/assets/js/watch.js +++ b/assets/js/watch.js @@ -65,8 +65,6 @@ function download_video(target) { } } - url = "/videoplayback" + url.split("/videoplayback")[1]; - var xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.responseType = "arraybuffer"; diff --git a/src/invidious.cr b/src/invidious.cr index b90e9913..a720670a 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -3658,6 +3658,10 @@ get "/latest_version" do |env| id = env.params.query["id"]? itag = env.params.query["itag"]? + local = env.params.query["local"]? + local ||= "false" + local = local == "true" + if !id || !itag halt env, status_code: 400 end @@ -3674,7 +3678,12 @@ get "/latest_version" do |env| halt env, status_code: 409 end - env.redirect urls[0]["url"] + url = urls[0]["url"] + if local + url = URI.parse(url).full_path.not_nil! + end + + env.redirect url end options "/videoplayback" do |env| diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index da45011b..dc58d48d 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -59,13 +59,13 @@ @@ -77,7 +77,7 @@ From 097cbcdae391450a033d65d2262c1a698319712f Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sun, 27 Jan 2019 22:12:07 -0600 Subject: [PATCH 070/108] Update subscribe button immediately --- .../components/subscribe_widget_script.ecr | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/invidious/views/components/subscribe_widget_script.ecr b/src/invidious/views/components/subscribe_widget_script.ecr index 5180bbb8..c5e36b79 100644 --- a/src/invidious/views/components/subscribe_widget_script.ecr +++ b/src/invidious/views/components/subscribe_widget_script.ecr @@ -3,7 +3,14 @@ if (subscribe_button.getAttribute('onclick')) { subscribe_button["href"] = "javascript:void(0)"; } -function subscribe() { +function subscribe(timeouts = 0) { + subscribe_button = document.getElementById("subscribe"); + + if (timeouts > 10) { + console.log("Failed to subscribe."); + return; + } + var url = "/subscription_ajax?action_create_subscription_to_channel=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>"; var xhr = new XMLHttpRequest(); xhr.responseType = "json"; @@ -11,18 +18,34 @@ function subscribe() { xhr.open("GET", url, true); xhr.send(); + var fallback = subscribe_button.innerHTML; + subscribe_button.onclick = unsubscribe; + subscribe_button.innerHTML = '<%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %>' + xhr.onreadystatechange = function() { if (xhr.readyState == 4) { - if (xhr.status == 200) { - subscribe_button = document.getElementById("subscribe"); - subscribe_button.onclick = unsubscribe; - subscribe_button.innerHTML = '<%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %>' + if (xhr.status != 200) { + subscribe_button.onclick = subscribe; + subscribe_button.innerHTML = fallback; } } } + + xhr.ontimeout = function() { + console.log("Subscribing timed out."); + + subscribe(timeouts + 1); + }; } -function unsubscribe() { +function unsubscribe(timeouts = 0) { + subscribe_button = document.getElementById("subscribe"); + + if (timeouts > 10) { + console.log("Failed to subscribe"); + return; + } + var url = "/subscription_ajax?action_remove_subscriptions=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>"; var xhr = new XMLHttpRequest(); xhr.responseType = "json"; @@ -30,13 +53,22 @@ function unsubscribe() { xhr.open("GET", url, true); xhr.send(); + var fallback = subscribe_button.innerHTML; + subscribe_button.onclick = subscribe; + subscribe_button.innerHTML = '<%= translate(locale, "Subscribe") %> | <%= sub_count_text %>' + xhr.onreadystatechange = function() { if (xhr.readyState == 4) { - if (xhr.status == 200) { - subscribe_button = document.getElementById("subscribe"); - subscribe_button.onclick = subscribe; - subscribe_button.innerHTML = '<%= translate(locale, "Subscribe") %> | <%= sub_count_text %>' + if (xhr.status != 200) { + subscribe_button.onclick = unsubscribe; + subscribe_button.innerHTML = fallback; } } } + + xhr.ontimeout = function() { + console.log("Unsubscribing timed out."); + + unsubscribe(timeouts + 1); + }; } From b38a2bbd127fc787216e4722f2dc6a720abda415 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 28 Jan 2019 20:45:08 -0600 Subject: [PATCH 071/108] Reload player on error --- src/invidious/views/components/player.ecr | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index f5e6f506..09d34368 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -114,6 +114,18 @@ var player = videojs("player", options, function() { }); }); +player.on('error', function(event) { + console.log("An error occured in the player, reloading..."); + + var currentTime = player.currentTime(); + player.load(); + if (currentTime > 0.5) { + currentTime -= 0.5; + } + player.currentTime(currentTime); + player.play() +}); + player.share(shareOptions); <% if params[:video_start] > 0 || params[:video_end] > 0 %> From 26b720036039f57e3341406ddaa351b0c93a132a Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 28 Jan 2019 20:47:38 -0600 Subject: [PATCH 072/108] Respect playback rate when reloading player --- src/invidious/views/components/player.ecr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 09d34368..66ee358b 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -118,11 +118,13 @@ player.on('error', function(event) { console.log("An error occured in the player, reloading..."); var currentTime = player.currentTime(); + var playbackRate = player.playbackRate() player.load(); if (currentTime > 0.5) { currentTime -= 0.5; } player.currentTime(currentTime); + player.playbackRate(playbackRate); player.play() }); From ff09a7255ac03dfd7d828aaaf872b263c4c9cee4 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 28 Jan 2019 22:36:27 -0600 Subject: [PATCH 073/108] Add handling to remove invalid sources --- src/invidious/views/components/player.ecr | 39 +++++++++++++++++------ 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 66ee358b..80879b67 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -115,17 +115,38 @@ var player = videojs("player", options, function() { }); player.on('error', function(event) { - console.log("An error occured in the player, reloading..."); + if (player.error().code === 2) { + console.log("An error occured in the player, reloading..."); - var currentTime = player.currentTime(); - var playbackRate = player.playbackRate() - player.load(); - if (currentTime > 0.5) { - currentTime -= 0.5; + var currentTime = player.currentTime(); + var playbackRate = player.playbackRate(); + player.load(); + if (currentTime > 0.5) { + currentTime -= 0.5; + } + player.currentTime(currentTime); + player.playbackRate(playbackRate); + player.play() + } else if (player.error().code === 4) { + console.log("Detected invalid source, removing..."); + var currentTime = player.currentTime(); + var sources = player.options().sources; + + for (var i = 0; i < sources.length; i++) { + if (sources[i].src === player.currentSource().src) { + sources.splice(i, 1); + break + } + }; + + player.load(); + if (currentTime > 0.5) { + currentTime -= 0.5; + } + player.currentTime(currentTime); + player.src(sources); + player.play(); } - player.currentTime(currentTime); - player.playbackRate(playbackRate); - player.play() }); player.share(shareOptions); From 1e214aae7cedbb0770312e3eb2901216d27e6da7 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Tue, 29 Jan 2019 19:55:27 -0600 Subject: [PATCH 074/108] Reload player instead of removing invalid source --- src/invidious/views/components/player.ecr | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 80879b67..b165985f 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -115,7 +115,7 @@ var player = videojs("player", options, function() { }); player.on('error', function(event) { - if (player.error().code === 2) { + if (player.error().code === 2 || player.error().code === 4) { console.log("An error occured in the player, reloading..."); var currentTime = player.currentTime(); @@ -126,25 +126,6 @@ player.on('error', function(event) { } player.currentTime(currentTime); player.playbackRate(playbackRate); - player.play() - } else if (player.error().code === 4) { - console.log("Detected invalid source, removing..."); - var currentTime = player.currentTime(); - var sources = player.options().sources; - - for (var i = 0; i < sources.length; i++) { - if (sources[i].src === player.currentSource().src) { - sources.splice(i, 1); - break - } - }; - - player.load(); - if (currentTime > 0.5) { - currentTime -= 0.5; - } - player.currentTime(currentTime); - player.src(sources); player.play(); } }); From 55118a676883e6e5ce551ec6c22074893f38b8bc Mon Sep 17 00:00:00 2001 From: Agustin Ferrari Date: Wed, 30 Jan 2019 09:28:28 -0300 Subject: [PATCH 075/108] Change color to the links and add a couple of improvements in the comments --- assets/css/lighttheme.css | 2 +- src/invidious/comments.cr | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/assets/css/lighttheme.css b/assets/css/lighttheme.css index 34bb9fc1..919d73f3 100644 --- a/assets/css/lighttheme.css +++ b/assets/css/lighttheme.css @@ -4,6 +4,6 @@ a:active { } a { - color: #303030; + color: #0093ff; text-decoration: none; } diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr index 87065b5f..3b9dd8eb 100644 --- a/src/invidious/comments.cr +++ b/src/invidious/comments.cr @@ -329,7 +329,9 @@ def template_youtube_comments(comments, locale) #{child["author"]}

#{child["contentHtml"]}

- #{translate(locale, "`x` ago", recode_date(Time.unix(child["published"].as_i64)))} + #{translate(locale, "`x` ago", recode_date(Time.unix(child["published"].as_i64)))} + | + [YT] | #{number_with_separator(child["likeCount"])}

From e9ea365f2f029f09fea9420d6820d19b67c179cc Mon Sep 17 00:00:00 2001 From: Agustin Ferrari Date: Thu, 31 Jan 2019 08:21:26 -0300 Subject: [PATCH 076/108] Add additional parameters in the API comments, highlight the user name in the uploader comments and I finished permalink of the comments. --- assets/css/default.css | 7 +++++++ src/invidious/comments.cr | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/assets/css/default.css b/assets/css/default.css index 244a5edd..e449df22 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -1,3 +1,10 @@ +.channel-owner { + background-color: #008BEC; + color: beige; + border-radius: 9px; + padding: 1px 6px; +} + .h-box { padding-left: 1em; padding-right: 1em; diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr index 3b9dd8eb..34113c97 100644 --- a/src/invidious/comments.cr +++ b/src/invidious/comments.cr @@ -158,6 +158,8 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) comment_count = body["header"]["commentsHeaderRenderer"]["countText"]["simpleText"].as_s.delete("Comments,").to_i json.field "commentCount", comment_count end + + json.field "videoId", id json.field "comments" do json.array do @@ -217,6 +219,16 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) json.field "publishedText", translate(locale, "`x` ago", recode_date(published)) json.field "likeCount", node_comment["likeCount"] json.field "commentId", node_comment["commentId"] + json.field "authorIsChannelOwner", node_comment["authorIsChannelOwner"] + + if node_comment["creatorHeart"]? + json.field "creatorHeart" do + json.object do + json.field "creatorThumbnail", node_comment["creatorHeart"]["creatorHeartRenderer"]["creatorThumbnail"]["thumbnails"][2] + json.field "creatorName", node_comment["creatorHeart"]["creatorHeartRenderer"]["creatorThumbnail"]["accessibility"]["accessibilityData"]["label"] + end + end + end if node_replies && !response["commentRepliesContinuation"]? reply_count = node_replies["moreText"]["simpleText"].as_s.delete("View all reply replies,") @@ -326,12 +338,12 @@ def template_youtube_comments(comments, locale)

- #{child["author"]} + #{child["author"]}

#{child["contentHtml"]}

#{translate(locale, "`x` ago", recode_date(Time.unix(child["published"].as_i64)))} | - [YT] + [YT] | #{number_with_separator(child["likeCount"])}

From 9e73e3b15326bfac7c94a2cd997f742abbe66305 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 31 Jan 2019 08:48:44 -0600 Subject: [PATCH 077/108] Add errorcode for invalid video IDs --- src/invidious/videos.cr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index ec911e3f..6298fa4e 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -633,6 +633,10 @@ def fetch_video(id, proxies, region) end end + if info["errorcode"]?.try &.== "2" + raise "Video unavailable." + end + title = info["title"] author = info["author"] ucid = info["ucid"] From def58ff11f226f6d8f6cafc7b743e8ba2434fd72 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 31 Jan 2019 09:09:00 -0600 Subject: [PATCH 078/108] Add interval and timeout for errors in player --- src/invidious/views/components/player.ecr | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index b165985f..9efe04fc 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -116,17 +116,19 @@ var player = videojs("player", options, function() { player.on('error', function(event) { if (player.error().code === 2 || player.error().code === 4) { - console.log("An error occured in the player, reloading..."); + setInterval(setTimeout(function (event) { + console.log("An error occured in the player, reloading..."); - var currentTime = player.currentTime(); - var playbackRate = player.playbackRate(); - player.load(); - if (currentTime > 0.5) { - currentTime -= 0.5; - } - player.currentTime(currentTime); - player.playbackRate(playbackRate); - player.play(); + var currentTime = player.currentTime(); + var playbackRate = player.playbackRate(); + player.load(); + if (currentTime > 0.5) { + currentTime -= 0.5; + } + player.currentTime(currentTime); + player.playbackRate(playbackRate); + player.play(); + }, 5000), 5000); } }); From cef061d6fb62cee6ebd87c7d98c778fccb9271bb Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 31 Jan 2019 14:40:26 -0600 Subject: [PATCH 079/108] Fix incorrect default in user preferences --- src/invidious.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious.cr b/src/invidious.cr index a720670a..69bbed77 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -1146,7 +1146,7 @@ post "/preferences" do |env| captions = [captions_0, captions_1, captions_2] related_videos = env.params.body["related_videos"]?.try &.as(String) - related_videos ||= "off" + related_videos ||= "on" related_videos = related_videos == "on" redirect_feed = env.params.body["redirect_feed"]?.try &.as(String) From fbb5df084990a67e934d9aeb8fc535a0a7198b8e Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 31 Jan 2019 14:54:02 -0600 Subject: [PATCH 080/108] Default to showing recommendations for logged out users --- src/invidious.cr | 2 +- src/invidious/views/watch.ecr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 69bbed77..a720670a 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -1146,7 +1146,7 @@ post "/preferences" do |env| captions = [captions_0, captions_1, captions_2] related_videos = env.params.body["related_videos"]?.try &.as(String) - related_videos ||= "on" + related_videos ||= "off" related_videos = related_videos == "on" redirect_feed = env.params.body["redirect_feed"]?.try &.as(String) diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index dc58d48d..a8f98492 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -141,7 +141,7 @@
- <% if preferences && preferences.related_videos || plid %> + <% if !preferences || preferences && preferences.related_videos || plid %>
<% if plid %>
From c9bc081f8c4d3b6d7d19d911f6b1944c5f461e77 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 31 Jan 2019 15:06:53 -0600 Subject: [PATCH 081/108] Respect DEFAULT_USER_PREFERENCES in video params --- src/invidious.cr | 22 +++++++++++----------- src/invidious/users.cr | 18 +++++++++--------- src/invidious/videos.cr | 16 ++++++++-------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index a720670a..99f9e1af 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -1128,21 +1128,21 @@ post "/preferences" do |env| listen = listen == "on" speed = env.params.body["speed"]?.try &.as(String).to_f? - speed ||= 1.0 + speed ||= DEFAULT_USER_PREFERENCES.speed quality = env.params.body["quality"]?.try &.as(String) - quality ||= "hd720" + quality ||= DEFAULT_USER_PREFERENCES.quality volume = env.params.body["volume"]?.try &.as(String).to_i? - volume ||= 100 + volume ||= DEFAULT_USER_PREFERENCES.volume - comments_0 = env.params.body["comments_0"]?.try &.as(String) || "youtube" - comments_1 = env.params.body["comments_1"]?.try &.as(String) || "" + comments_0 = env.params.body["comments_0"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.comments[0] + comments_1 = env.params.body["comments_1"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.comments[1] comments = [comments_0, comments_1] - captions_0 = env.params.body["captions_0"]?.try &.as(String) || "" - captions_1 = env.params.body["captions_1"]?.try &.as(String) || "" - captions_2 = env.params.body["captions_2"]?.try &.as(String) || "" + captions_0 = env.params.body["captions_0"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[0] + captions_1 = env.params.body["captions_1"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[1] + captions_2 = env.params.body["captions_2"]?.try &.as(String) || DEFAULT_USER_PREFERENCES.captions[2] captions = [captions_0, captions_1, captions_2] related_videos = env.params.body["related_videos"]?.try &.as(String) @@ -1154,7 +1154,7 @@ post "/preferences" do |env| redirect_feed = redirect_feed == "on" locale = env.params.body["locale"]?.try &.as(String) - locale ||= "en-US" + locale ||= DEFAULT_USER_PREFERENCES.locale dark_mode = env.params.body["dark_mode"]?.try &.as(String) dark_mode ||= "off" @@ -1165,10 +1165,10 @@ post "/preferences" do |env| thin_mode = thin_mode == "on" max_results = env.params.body["max_results"]?.try &.as(String).to_i? - max_results ||= 40 + max_results ||= DEFAULT_USER_PREFERENCES.max_results sort = env.params.body["sort"]?.try &.as(String) - sort ||= "published" + sort ||= DEFAULT_USER_PREFERENCES.sort latest_only = env.params.body["latest_only"]?.try &.as(String) latest_only ||= "off" diff --git a/src/invidious/users.cr b/src/invidious/users.cr index dbbe87f8..d45c5af4 100644 --- a/src/invidious/users.cr +++ b/src/invidious/users.cr @@ -79,36 +79,36 @@ class Preferences autoplay: Bool, continue: { type: Bool, - default: false, + default: DEFAULT_USER_PREFERENCES.continue, }, listen: { type: Bool, - default: false, + default: DEFAULT_USER_PREFERENCES.listen, }, speed: Float32, quality: String, volume: Int32, comments: { type: Array(String), - default: ["youtube", ""], + default: DEFAULT_USER_PREFERENCES.comments, converter: StringToArray, }, captions: { type: Array(String), - default: ["", "", ""], + default: DEFAULT_USER_PREFERENCES.captions, }, redirect_feed: { type: Bool, - default: false, + default: DEFAULT_USER_PREFERENCES.redirect_feed, }, related_videos: { type: Bool, - default: true, + default: DEFAULT_USER_PREFERENCES.related_videos, }, dark_mode: Bool, thin_mode: { type: Bool, - default: false, + default: DEFAULT_USER_PREFERENCES.thin_mode, }, max_results: Int32, sort: String, @@ -116,11 +116,11 @@ class Preferences unseen_only: Bool, notifications_only: { type: Bool, - default: false, + default: DEFAULT_USER_PREFERENCES.notifications_only, }, locale: { type: String, - default: "en-US", + default: DEFAULT_USER_PREFERENCES.locale, }, }) end diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 6298fa4e..a95f5443 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -745,14 +745,14 @@ def process_video_params(query, preferences) volume ||= preferences.volume end - autoplay ||= 0 - continue ||= 0 - listen ||= 0 - preferred_captions ||= [] of String - quality ||= "hd720" - speed ||= 1 - video_loop ||= 0 - volume ||= 100 + autoplay ||= DEFAULT_USER_PREFERENCES.autoplay.to_unsafe + continue ||= DEFAULT_USER_PREFERENCES.continue.to_unsafe + listen ||= DEFAULT_USER_PREFERENCES.listen.to_unsafe + preferred_captions ||= DEFAULT_USER_PREFERENCES.captions + quality ||= DEFAULT_USER_PREFERENCES.quality + speed ||= DEFAULT_USER_PREFERENCES.speed + video_loop ||= DEFAULT_USER_PREFERENCES.video_loop.to_unsafe + volume ||= DEFAULT_USER_PREFERENCES.volume autoplay = autoplay == 1 continue = continue == 1 From a7fbcd0aa8591177b58cb84048ae9dcc47e9de49 Mon Sep 17 00:00:00 2001 From: beriain Date: Thu, 24 Jan 2019 19:41:41 +0000 Subject: [PATCH 082/108] Add Basque translation --- locales/eu.json | 274 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 locales/eu.json diff --git a/locales/eu.json b/locales/eu.json new file mode 100644 index 00000000..60aac23d --- /dev/null +++ b/locales/eu.json @@ -0,0 +1,274 @@ +{ + "`x` subscribers": "", + "`x` videos": "", + "LIVE": "", + "Shared `x` ago": "", + "Unsubscribe": "", + "Subscribe": "", + "Login to subscribe to `x`": "", + "View channel on YouTube": "", + "newest": "", + "oldest": "", + "popular": "", + "Preview page": "", + "Next page": "", + "Clear watch history?": "", + "Yes": "", + "No": "", + "Import and Export Data": "", + "Import": "", + "Import Invidious data": "", + "Import YouTube subscriptions": "", + "Import FreeTube subscriptions (.db)": "", + "Import NewPipe subscriptions (.json)": "", + "Import NewPipe data (.zip)": "", + "Export": "", + "Export subscriptions as OPML": "", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "", + "Export data as JSON": "", + "Delete account?": "", + "History": "", + "Previous page": "", + "An alternative front-end to YouTube": "", + "JavaScript license information": "", + "source": "", + "Login": "", + "Login/Register": "", + "Login to Google": "", + "User ID:": "", + "Password:": "", + "Time (h:mm:ss):": "", + "Text CAPTCHA": "", + "Image CAPTCHA": "", + "Sign In": "", + "Register": "", + "Email:": "", + "Google verification code:": "", + "Preferences": "", + "Player preferences": "", + "Always loop: ": "", + "Autoplay: ": "", + "Autoplay next video: ": "", + "Listen by default: ": "", + "Default speed: ": "", + "Preferred video quality: ": "", + "Player volume: ": "", + "Default comments: ": "", + "Default captions: ": "", + "Fallback captions: ": "", + "Show related videos? ": "", + "Visual preferences": "", + "Dark mode: ": "", + "Thin mode: ": "", + "Subscription preferences": "", + "Redirect homepage to feed: ": "", + "Number of videos shown in feed: ": "", + "Sort videos by: ": "", + "published": "", + "published - reverse": "", + "alphabetically": "", + "alphabetically - reverse": "", + "channel name": "", + "channel name - reverse": "", + "Only show latest video from channel: ": "", + "Only show latest unwatched video from channel: ": "", + "Only show unwatched: ": "", + "Only show notifications (if there are any): ": "", + "Data preferences": "", + "Clear watch history": "", + "Import/Export data": "", + "Manage subscriptions": "", + "Watch history": "", + "Delete account": "", + "Save preferences": "", + "Subscription manager": "", + "`x` subscriptions": "", + "Import/Export": "", + "unsubscribe": "", + "Subscriptions": "", + "`x` unseen notifications": "", + "search": "", + "Sign out": "", + "Released under the AGPLv3 by Omar Roth.": "", + "Source available here.": "", + "View JavaScript license information.": "", + "Trending": "", + "Watch video on Youtube": "", + "Genre: ": "", + "License: ": "", + "Family friendly? ": "", + "Wilson score: ": "", + "Engagement: ": "", + "Whitelisted regions: ": "", + "Blacklisted regions: ": "", + "Shared `x`": "", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "", + "View YouTube comments": "", + "View more comments on Reddit": "", + "View `x` comments": "", + "View Reddit comments": "", + "Hide replies": "", + "Show replies": "", + "Incorrect password": "", + "Quota exceeded, try again in a few hours": "", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "", + "Invalid TFA code": "", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "", + "Invalid answer": "", + "Invalid CAPTCHA": "", + "CAPTCHA is a required field": "", + "User ID is a required field": "", + "Password is a required field": "", + "Invalid username or password": "", + "Please sign in using 'Sign in with Google'": "", + "Password cannot be empty": "", + "Password cannot be longer than 55 characters": "", + "Please sign in": "", + "Invidious Private Feed for `x`": "", + "channel:`x`": "", + "Deleted or invalid channel": "", + "This channel does not exist.": "", + "Could not get channel info.": "", + "Could not fetch comments": "", + "View `x` replies": "", + "`x` ago": "", + "Load more": "", + "`x` points": "", + "Could not create mix.": "", + "Playlist is empty": "", + "Invalid playlist.": "", + "Playlist does not exist.": "", + "Could not pull trending pages.": "", + "Hidden field \"challenge\" is a required field": "", + "Hidden field \"token\" is a required field": "", + "Invalid challenge": "", + "Invalid token": "", + "Invalid user": "", + "Token is expired, please try again": "", + "English": "", + "English (auto-generated)": "", + "Afrikaans": "", + "Albanian": "", + "Amharic": "", + "Arabic": "", + "Armenian": "", + "Azerbaijani": "", + "Bangla": "", + "Basque": "", + "Belarusian": "", + "Bosnian": "", + "Bulgarian": "", + "Burmese": "", + "Catalan": "", + "Cebuano": "", + "Chinese (Simplified)": "", + "Chinese (Traditional)": "", + "Corsican": "", + "Croatian": "", + "Czech": "", + "Danish": "", + "Dutch": "", + "Esperanto": "", + "Estonian": "", + "Filipino": "", + "Finnish": "", + "French": "", + "Galician": "", + "Georgian": "", + "German": "", + "Greek": "", + "Gujarati": "", + "Haitian Creole": "", + "Hausa": "", + "Hawaiian": "", + "Hebrew": "", + "Hindi": "", + "Hmong": "", + "Hungarian": "", + "Icelandic": "", + "Igbo": "", + "Indonesian": "", + "Irish": "", + "Italian": "", + "Japanese": "", + "Javanese": "", + "Kannada": "", + "Kazakh": "", + "Khmer": "", + "Korean": "", + "Kurdish": "", + "Kyrgyz": "", + "Lao": "", + "Latin": "", + "Latvian": "", + "Lithuanian": "", + "Luxembourgish": "", + "Macedonian": "", + "Malagasy": "", + "Malay": "", + "Malayalam": "", + "Maltese": "", + "Maori": "", + "Marathi": "", + "Mongolian": "", + "Nepali": "", + "Norwegian": "", + "Nyanja": "", + "Pashto": "", + "Persian": "", + "Polish": "", + "Portuguese": "", + "Punjabi": "", + "Romanian": "", + "Russian": "", + "Samoan": "", + "Scottish Gaelic": "", + "Serbian": "", + "Shona": "", + "Sindhi": "", + "Sinhala": "", + "Slovak": "", + "Slovenian": "", + "Somali": "", + "Southern Sotho": "", + "Spanish": "", + "Spanish (Latin America)": "", + "Sundanese": "", + "Swahili": "", + "Swedish": "", + "Tajik": "", + "Tamil": "", + "Telugu": "", + "Thai": "", + "Turkish": "", + "Ukrainian": "", + "Urdu": "", + "Uzbek": "", + "Vietnamese": "", + "Welsh": "", + "Western Frisian": "", + "Xhosa": "", + "Yiddish": "", + "Yoruba": "", + "Zulu": "", + "`x` years": "", + "`x` months": "", + "`x` weeks": "", + "`x` days": "", + "`x` hours": "", + "`x` minutes": "", + "`x` seconds": "", + "Fallback comments: ": "", + "Popular": "", + "Top": "", + "About": "", + "Rating: ": "", + "Language: ": "", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "" +} From aeee40c894098194bf012323b2b27bbf41dd7a2c Mon Sep 17 00:00:00 2001 From: beriain Date: Thu, 24 Jan 2019 19:42:20 +0000 Subject: [PATCH 083/108] Update Basque translation --- locales/eu.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/locales/eu.json b/locales/eu.json index 60aac23d..091612d0 100644 --- a/locales/eu.json +++ b/locales/eu.json @@ -4,31 +4,31 @@ "LIVE": "", "Shared `x` ago": "", "Unsubscribe": "", - "Subscribe": "", + "Subscribe": "Harpidetu", "Login to subscribe to `x`": "", - "View channel on YouTube": "", - "newest": "", - "oldest": "", - "popular": "", - "Preview page": "", - "Next page": "", - "Clear watch history?": "", - "Yes": "", - "No": "", - "Import and Export Data": "", - "Import": "", - "Import Invidious data": "", - "Import YouTube subscriptions": "", - "Import FreeTube subscriptions (.db)": "", - "Import NewPipe subscriptions (.json)": "", - "Import NewPipe data (.zip)": "", - "Export": "", - "Export subscriptions as OPML": "", + "View channel on YouTube": "Ikusi kanala YouTuben", + "newest": "berrienak", + "oldest": "zaharrenak", + "popular": "ospetsuenak", + "Preview page": "Aurrebista orria", + "Next page": "Hurrengo orria", + "Clear watch history?": "Garbitu ikusitakoen historia?", + "Yes": "Bai", + "No": "Ez", + "Import and Export Data": "Datuak inportatu eta esportatu", + "Import": "Inportatu", + "Import Invidious data": "Invidiouseko datuak inportatu", + "Import YouTube subscriptions": "YouTubeko harpidetzak inportatu", + "Import FreeTube subscriptions (.db)": "FreeTubeko harpidetzak inportatu (.db)", + "Import NewPipe subscriptions (.json)": "NewPipeko harpidetzak inportatu (.json)", + "Import NewPipe data (.zip)": "NewPipeko datuak inportatu (.zip)", + "Export": "Esportatu", + "Export subscriptions as OPML": "Esportatu harpidetzak OPML bezala", "Export subscriptions as OPML (for NewPipe & FreeTube)": "", "Export data as JSON": "", - "Delete account?": "", - "History": "", - "Previous page": "", + "Delete account?": "Kontua ezabatu?", + "History": "Historia", + "Previous page": "Aurreko orria", "An alternative front-end to YouTube": "", "JavaScript license information": "", "source": "", From 095b5fcea0f1cbae2654f4ff43a84cd5fd3f4a14 Mon Sep 17 00:00:00 2001 From: dimqua Date: Sun, 27 Jan 2019 15:15:48 +0000 Subject: [PATCH 084/108] Update Russian translation --- locales/ru.json | 556 ++++++++++++++++++++++++------------------------ 1 file changed, 278 insertions(+), 278 deletions(-) diff --git a/locales/ru.json b/locales/ru.json index c55c63d8..8ade66c4 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -1,280 +1,280 @@ { - "`x` subscribers": "`x` подписчиков", - "`x` videos": "`x` видео", - "LIVE": "ПРЯМОЙ ЭФИР", - "Shared `x` ago": "Опубликовано `x` назад", - "Unsubscribe": "Отписаться", - "Subscribe": "Подписаться", - "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`", - "View channel on YouTube": "Канал на YouTube", - "newest": "новые", - "oldest": "старые", - "popular": "популярные", - "Preview page": "Предварительный просмотр", - "Next page": "Следующая страница", - "Clear watch history?": "Очистить историю просмотров?", - "Yes": "Да", - "No": "Нет", - "Import and Export Data": "Импорт и экспорт данных", - "Import": "Импорт", - "Import Invidious data": "Импортировать данные Invidious", - "Import YouTube subscriptions": "Импортировать YouTube подписки", - "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)", - "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)", - "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)", - "Export": "Экспорт", - "Export subscriptions as OPML": "Экспортировать подписки в OPML", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)", - "Export data as JSON": "Экспортировать данные в JSON", - "Delete account?": "Удалить аккаунт?", - "History": "История", - "Previous page": "Предыдущая страница", - "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube", - "JavaScript license information": "Лицензии JavaScript", - "source": "источник", - "Login": "Войти", - "Login/Register": "Войти/Регистрация", - "Login to Google": "Войти через Google", - "User ID:": "ID пользователя:", - "Password:": "Пароль:", - "Time (h:mm:ss):": "Время (ч:мм:сс):", - "Text CAPTCHA": "Текст капчи", - "Image CAPTCHA": "Изображение капчи", - "Sign In": "Войти", - "Register": "Регистрация", - "Email:": "Эл. почта:", - "Google verification code:": "Код подтверждения Google:", - "Preferences": "Настройки", - "Player preferences": "Настройки проигрывателя", - "Always loop: ": "Всегда повторять: ", - "Autoplay: ": "Автовоспроизведение: ", - "Autoplay next video: ": "Автовоспроизведение следующего видео: ", - "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ", - "Default speed: ": "Скорость по-умолчанию: ", - "Preferred video quality: ": "Предпочтительное качество видео: ", - "Player volume: ": "Громкость воспроизведения: ", - "Default comments: ": "Источник комментариев: ", - "youtube": "YouTube", - "reddit": "Reddit", - "Default captions: ": "Субтитры по-умолчанию: ", - "Fallback captions: ": "Резервные субтитры: ", - "Show related videos? ": "Показывать похожие видео? ", - "Visual preferences": "Визуальные настройки", - "Dark mode: ": "Темная тема: ", - "Thin mode: ": "Облегченный режим: ", - "Subscription preferences": "Настройки подписок", - "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ", - "Number of videos shown in feed: ": "Число видео в ленте: ", - "Sort videos by: ": "Сортировать видео по: ", - "published": "дате публикации", - "published - reverse": "дате - обратный порядок", - "alphabetically": "алфавиту", - "alphabetically - reverse": "алфавиту - обратный порядок", - "channel name": "имени канала", - "channel name - reverse": "имени канала - обратный порядок", - "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ", - "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ", - "Only show unwatched: ": "Отображать только непросмотренные видео: ", - "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ", - "Data preferences": "Настройки данных", - "Clear watch history": "Очистить историю просмотра", - "Import/Export data": "Импорт/Экспорт данных", - "Manage subscriptions": "Управление подписками", - "Watch history": "История просмотров", - "Delete account": "Удалить аккаунт", - "Save preferences": "Сохранить настройки", - "Subscription manager": "Менеджер подписок", - "`x` subscriptions": "`x` подписок", - "Import/Export": "Импорт/Экспорт", - "unsubscribe": "отписаться", - "Subscriptions": "Подписки", - "`x` unseen notifications": "`x` новых оповещений", - "search": "поиск", - "Sign out": "Выйти", - "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.", - "Source available here.": "Исходный код доступен здесь.", - "Liberapay: ": "Liberapay: ", - "Patreon: ": "Patreon: ", - "BTC: ": "BTC: ", - "BCH: ": "BCH: ", - "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.", - "Trending": "В тренде", - "Watch video on Youtube": "Смотреть на YouTube", - "Genre: ": "Жанр: ", - "License: ": "Лицензия: ", - "Family friendly? ": "Семейный просмотр: ", - "Wilson score: ": "Рейтинг Вильсона: ", - "Engagement: ": "Вовлеченность: ", - "Whitelisted regions: ": "Доступно для: ", - "Blacklisted regions: ": "Недоступно для: ", - "Shared `x`": "Опубликовано `x`", - "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).", - "View YouTube comments": "Смотреть комментарии с YouTube", - "View more comments on Reddit": "Больше комментариев на Reddit", - "View `x` comments": "Показать `x` комментариев", - "View Reddit comments": "Смотреть комментарии с Reddit", - "Hide replies": "Скрыть ответы", - "Show replies": "Показать ответы", - "Incorrect password": "Неправильный пароль", - "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов", - "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.", - "Invalid TFA code": "Неправильный TFA код", - "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.", - "Invalid answer": "Неверный ответ", - "Invalid CAPTCHA": "Неверная капча", - "CAPTCHA is a required field": "Необходимо ввести капчу", - "User ID is a required field": "Необходимо ввести идентификатор пользователя", - "Password is a required field": "Необходимо ввести пароль", - "Invalid username or password": "Недопустимый пароль или имя пользователя", - "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google", - "Password cannot be empty": "Пароль не может быть пустым", - "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов", - "Please sign in": "Пожалуйста, войдите", - "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`", - "channel:`x`": "канал: `x`", - "Deleted or invalid channel": "Канал удален или не найден", - "This channel does not exist.": "Такой канал не существует.", - "Could not get channel info.": "Невозможно получить информацию о канале.", - "Could not fetch comments": "Невозможно получить комментарии", - "View `x` replies": "Показать `x` ответов", - "`x` ago": "`x` назад", - "Load more": "Загрузить больше", - "`x` points": "`x` очков", - "Could not create mix.": "Невозможно создать \"микс\".", - "Playlist is empty": "Плейлист пуст", - "Invalid playlist.": "Некорректный плейлист.", - "Playlist does not exist.": "Плейлист не существует.", - "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".", - "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"", - "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"", - "Invalid challenge": "Неправильный ответ в \"challenge\"", - "Invalid token": "Неправильный токен", - "Invalid user": "Недопустимое имя пользователя", - "Token is expired, please try again": "Срок действия токена истек, попробуйте позже", - "English": "Английский", - "English (auto-generated)": "Английский (созданы автоматически)", - "Afrikaans": "", - "Albanian": "", - "Amharic": "", - "Arabic": "", - "Armenian": "", - "Azerbaijani": "", - "Bangla": "", - "Basque": "", - "Belarusian": "", - "Bosnian": "", - "Bulgarian": "", - "Burmese": "", - "Catalan": "", - "Cebuano": "", - "Chinese (Simplified)": "", - "Chinese (Traditional)": "", - "Corsican": "", - "Croatian": "", - "Czech": "", - "Danish": "", - "Dutch": "", - "Esperanto": "", - "Estonian": "", - "Filipino": "", - "Finnish": "", - "French": "", - "Galician": "", - "Georgian": "", - "German": "", - "Greek": "", - "Gujarati": "", - "Haitian Creole": "", - "Hausa": "", - "Hawaiian": "", - "Hebrew": "", - "Hindi": "", - "Hmong": "", - "Hungarian": "", - "Icelandic": "", - "Igbo": "", - "Indonesian": "", - "Irish": "", - "Italian": "", - "Japanese": "", - "Javanese": "", - "Kannada": "", - "Kazakh": "", - "Khmer": "", - "Korean": "", - "Kurdish": "", - "Kyrgyz": "", - "Lao": "", - "Latin": "", - "Latvian": "", - "Lithuanian": "", - "Luxembourgish": "", - "Macedonian": "", - "Malagasy": "", - "Malay": "", - "Malayalam": "", - "Maltese": "", - "Maori": "", - "Marathi": "", - "Mongolian": "", - "Nepali": "", - "Norwegian": "", - "Nyanja": "", - "Pashto": "", - "Persian": "", - "Polish": "", - "Portuguese": "", - "Punjabi": "", - "Romanian": "", - "Russian": "", - "Samoan": "", - "Scottish Gaelic": "", - "Serbian": "", - "Shona": "", - "Sindhi": "", - "Sinhala": "", - "Slovak": "", - "Slovenian": "", - "Somali": "", - "Southern Sotho": "", - "Spanish": "", - "Spanish (Latin America)": "", - "Sundanese": "", - "Swahili": "", - "Swedish": "", - "Tajik": "", - "Tamil": "", - "Telugu": "", - "Thai": "", - "Turkish": "", - "Ukrainian": "", - "Urdu": "", - "Uzbek": "", - "Vietnamese": "", - "Welsh": "", - "Western Frisian": "", - "Xhosa": "", - "Yiddish": "", - "Yoruba": "", - "Zulu": "", - "`x` years": "`x` лет", - "`x` months": "`x` месяцев", - "`x` weeks": "`x` недель", - "`x` days": "`x` дней", - "`x` hours": "`x` часов", - "`x` minutes": "`x` минут", - "`x` seconds": "`x` секунд", - "Fallback comments: ": "Резервные комментарии: ", - "Popular": "Популярное", - "Top": "Топ", - "About": "О сайте", - "Rating: ": "Рейтинг: ", - "Language: ": "Язык: ", - "Default": "", - "Music": "", - "Gaming": "", - "News": "", - "Movies": "", - "Download": "", - "Download as: ": "" + "`x` subscribers": "`x` подписчиков", + "`x` videos": "`x` видео", + "LIVE": "ПРЯМОЙ ЭФИР", + "Shared `x` ago": "Опубликовано `x` назад", + "Unsubscribe": "Отписаться", + "Subscribe": "Подписаться", + "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`", + "View channel on YouTube": "Канал на YouTube", + "newest": "новые", + "oldest": "старые", + "popular": "популярные", + "Preview page": "Предварительный просмотр", + "Next page": "Следующая страница", + "Clear watch history?": "Очистить историю просмотров?", + "Yes": "Да", + "No": "Нет", + "Import and Export Data": "Импорт и экспорт данных", + "Import": "Импорт", + "Import Invidious data": "Импортировать данные Invidious", + "Import YouTube subscriptions": "Импортировать YouTube подписки", + "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)", + "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)", + "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)", + "Export": "Экспорт", + "Export subscriptions as OPML": "Экспортировать подписки в OPML", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)", + "Export data as JSON": "Экспортировать данные в JSON", + "Delete account?": "Удалить аккаунт?", + "History": "История", + "Previous page": "Предыдущая страница", + "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube", + "JavaScript license information": "Лицензии JavaScript", + "source": "источник", + "Login": "Войти", + "Login/Register": "Войти/Регистрация", + "Login to Google": "Войти через Google", + "User ID:": "ID пользователя:", + "Password:": "Пароль:", + "Time (h:mm:ss):": "Время (ч:мм:сс):", + "Text CAPTCHA": "Текст капчи", + "Image CAPTCHA": "Изображение капчи", + "Sign In": "Войти", + "Register": "Регистрация", + "Email:": "Эл. почта:", + "Google verification code:": "Код подтверждения Google:", + "Preferences": "Настройки", + "Player preferences": "Настройки проигрывателя", + "Always loop: ": "Всегда повторять: ", + "Autoplay: ": "Автовоспроизведение: ", + "Autoplay next video: ": "Автовоспроизведение следующего видео: ", + "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ", + "Default speed: ": "Скорость по-умолчанию: ", + "Preferred video quality: ": "Предпочтительное качество видео: ", + "Player volume: ": "Громкость воспроизведения: ", + "Default comments: ": "Источник комментариев: ", + "youtube": "YouTube", + "reddit": "Reddit", + "Default captions: ": "Субтитры по-умолчанию: ", + "Fallback captions: ": "Резервные субтитры: ", + "Show related videos? ": "Показывать похожие видео? ", + "Visual preferences": "Визуальные настройки", + "Dark mode: ": "Темная тема: ", + "Thin mode: ": "Облегченный режим: ", + "Subscription preferences": "Настройки подписок", + "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ", + "Number of videos shown in feed: ": "Число видео в ленте: ", + "Sort videos by: ": "Сортировать видео по: ", + "published": "дате публикации", + "published - reverse": "дате - обратный порядок", + "alphabetically": "алфавиту", + "alphabetically - reverse": "алфавиту - обратный порядок", + "channel name": "имени канала", + "channel name - reverse": "имени канала - обратный порядок", + "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ", + "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ", + "Only show unwatched: ": "Отображать только непросмотренные видео: ", + "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ", + "Data preferences": "Настройки данных", + "Clear watch history": "Очистить историю просмотра", + "Import/Export data": "Импорт/Экспорт данных", + "Manage subscriptions": "Управление подписками", + "Watch history": "История просмотров", + "Delete account": "Удалить аккаунт", + "Save preferences": "Сохранить настройки", + "Subscription manager": "Менеджер подписок", + "`x` subscriptions": "`x` подписок", + "Import/Export": "Импорт/Экспорт", + "unsubscribe": "отписаться", + "Subscriptions": "Подписки", + "`x` unseen notifications": "`x` новых оповещений", + "search": "поиск", + "Sign out": "Выйти", + "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.", + "Source available here.": "Исходный код доступен здесь.", + "Liberapay: ": "Liberapay: ", + "Patreon: ": "Patreon: ", + "BTC: ": "BTC: ", + "BCH: ": "BCH: ", + "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.", + "Trending": "В тренде", + "Watch video on Youtube": "Смотреть на YouTube", + "Genre: ": "Жанр: ", + "License: ": "Лицензия: ", + "Family friendly? ": "Семейный просмотр: ", + "Wilson score: ": "Рейтинг Вильсона: ", + "Engagement: ": "Вовлеченность: ", + "Whitelisted regions: ": "Доступно для: ", + "Blacklisted regions: ": "Недоступно для: ", + "Shared `x`": "Опубликовано `x`", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).", + "View YouTube comments": "Смотреть комментарии с YouTube", + "View more comments on Reddit": "Больше комментариев на Reddit", + "View `x` comments": "Показать `x` комментариев", + "View Reddit comments": "Смотреть комментарии с Reddit", + "Hide replies": "Скрыть ответы", + "Show replies": "Показать ответы", + "Incorrect password": "Неправильный пароль", + "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.", + "Invalid TFA code": "Неправильный TFA код", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.", + "Invalid answer": "Неверный ответ", + "Invalid CAPTCHA": "Неверная капча", + "CAPTCHA is a required field": "Необходимо ввести капчу", + "User ID is a required field": "Необходимо ввести идентификатор пользователя", + "Password is a required field": "Необходимо ввести пароль", + "Invalid username or password": "Недопустимый пароль или имя пользователя", + "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google", + "Password cannot be empty": "Пароль не может быть пустым", + "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов", + "Please sign in": "Пожалуйста, войдите", + "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`", + "channel:`x`": "канал: `x`", + "Deleted or invalid channel": "Канал удален или не найден", + "This channel does not exist.": "Такой канал не существует.", + "Could not get channel info.": "Невозможно получить информацию о канале.", + "Could not fetch comments": "Невозможно получить комментарии", + "View `x` replies": "Показать `x` ответов", + "`x` ago": "`x` назад", + "Load more": "Загрузить больше", + "`x` points": "`x` очков", + "Could not create mix.": "Невозможно создать \"микс\".", + "Playlist is empty": "Плейлист пуст", + "Invalid playlist.": "Некорректный плейлист.", + "Playlist does not exist.": "Плейлист не существует.", + "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".", + "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"", + "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"", + "Invalid challenge": "Неправильный ответ в \"challenge\"", + "Invalid token": "Неправильный токен", + "Invalid user": "Недопустимое имя пользователя", + "Token is expired, please try again": "Срок действия токена истек, попробуйте позже", + "English": "Английский", + "English (auto-generated)": "Английский (созданы автоматически)", + "Afrikaans": "Африкаанс", + "Albanian": "Албанский", + "Amharic": "Амхарский", + "Arabic": "Арабский", + "Armenian": "Армянский", + "Azerbaijani": "Азербайджанский", + "Bangla": "", + "Basque": "", + "Belarusian": "", + "Bosnian": "", + "Bulgarian": "", + "Burmese": "", + "Catalan": "", + "Cebuano": "", + "Chinese (Simplified)": "", + "Chinese (Traditional)": "", + "Corsican": "", + "Croatian": "", + "Czech": "", + "Danish": "", + "Dutch": "", + "Esperanto": "", + "Estonian": "", + "Filipino": "", + "Finnish": "", + "French": "", + "Galician": "", + "Georgian": "", + "German": "", + "Greek": "", + "Gujarati": "", + "Haitian Creole": "", + "Hausa": "", + "Hawaiian": "", + "Hebrew": "", + "Hindi": "", + "Hmong": "", + "Hungarian": "", + "Icelandic": "", + "Igbo": "", + "Indonesian": "", + "Irish": "", + "Italian": "", + "Japanese": "", + "Javanese": "", + "Kannada": "", + "Kazakh": "", + "Khmer": "", + "Korean": "", + "Kurdish": "", + "Kyrgyz": "", + "Lao": "", + "Latin": "", + "Latvian": "", + "Lithuanian": "", + "Luxembourgish": "", + "Macedonian": "", + "Malagasy": "", + "Malay": "", + "Malayalam": "", + "Maltese": "", + "Maori": "", + "Marathi": "", + "Mongolian": "", + "Nepali": "", + "Norwegian": "", + "Nyanja": "", + "Pashto": "", + "Persian": "", + "Polish": "", + "Portuguese": "", + "Punjabi": "", + "Romanian": "", + "Russian": "", + "Samoan": "", + "Scottish Gaelic": "", + "Serbian": "", + "Shona": "", + "Sindhi": "", + "Sinhala": "", + "Slovak": "", + "Slovenian": "", + "Somali": "", + "Southern Sotho": "", + "Spanish": "", + "Spanish (Latin America)": "", + "Sundanese": "", + "Swahili": "", + "Swedish": "", + "Tajik": "", + "Tamil": "", + "Telugu": "", + "Thai": "", + "Turkish": "", + "Ukrainian": "", + "Urdu": "", + "Uzbek": "", + "Vietnamese": "", + "Welsh": "", + "Western Frisian": "", + "Xhosa": "", + "Yiddish": "", + "Yoruba": "", + "Zulu": "Зулусский", + "`x` years": "`x` лет", + "`x` months": "`x` месяцев", + "`x` weeks": "`x` недель", + "`x` days": "`x` дней", + "`x` hours": "`x` часов", + "`x` minutes": "`x` минут", + "`x` seconds": "`x` секунд", + "Fallback comments: ": "Резервные комментарии: ", + "Popular": "Популярное", + "Top": "Топ", + "About": "О сайте", + "Rating: ": "Рейтинг: ", + "Language: ": "Язык: ", + "Default": "По-умолчанию", + "Music": "Музыка", + "Gaming": "Игры", + "News": "Новости", + "Movies": "Фильмы", + "Download": "Скачать", + "Download as: ": "Скачать как: " } From d5c9b7dfe8055e939c555c32d106f02c7f983120 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Thu, 31 Jan 2019 20:25:58 -0600 Subject: [PATCH 085/108] Only play after error if already playing --- src/invidious/views/components/player.ecr | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 9efe04fc..7f932ef4 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -121,13 +121,18 @@ player.on('error', function(event) { var currentTime = player.currentTime(); var playbackRate = player.playbackRate(); + var paused = player.paused() + player.load(); if (currentTime > 0.5) { currentTime -= 0.5; } player.currentTime(currentTime); player.playbackRate(playbackRate); - player.play(); + + if (!paused) { + player.play(); + } }, 5000), 5000); } }); From b0ba670c919e4d1f4613ebc8973a8a1065dc4292 Mon Sep 17 00:00:00 2001 From: Agustin Ferrari Date: Fri, 1 Feb 2019 09:09:10 -0300 Subject: [PATCH 086/108] Comments now show if they were edited and if they received a heart from the uploader (plus additional classes in default.css). The isEdited attribute was also added in the comments API and new strings in en-US.json --- assets/css/default.css | 33 +++++++++++++++++++++++++++++++++ locales/en-US.json | 6 +++++- src/invidious/comments.cr | 34 +++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/assets/css/default.css b/assets/css/default.css index e449df22..0f7e9eee 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -5,6 +5,39 @@ padding: 1px 6px; } +.creator-heart-container { + display: inline-block; + padding: 0px 7px 6px 0px; + margin: 0px -7px -4px 0px; +} + +.creator-heart { + position: relative; + width: 16px; + height: 16px; + border: 2px none; +} + +.creator-heart-background-hearted { + width: 16px; + height: 16px; + padding: 0px; + position: relative; +} + +.creator-heart-small-hearted { + position: absolute; + right: -7px; + bottom: -4px; +} + +.creator-heart-small-container { + position: relative; + width: 13px; + height: 13px; + color: rgb(255, 0, 0); +} + .h-box { padding-left: 1em; padding-right: 1em; diff --git a/locales/en-US.json b/locales/en-US.json index ccc01458..20fc019e 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -270,5 +270,9 @@ "News": "News", "Movies": "Movies", "Download": "Download", - "Download as: ": "Download as: " + "Download as: ": "Download as: ", + "%A %B %-d, %Y": "%A %B %-d, %Y", + "(edited)": "(edited)", + "Youtube permalink of the comment": "Youtube permalink of the comment", + "`x` marked it with a ❤": "`x` marked it with a ❤" } diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr index 34113c97..e6d74d1d 100644 --- a/src/invidious/comments.cr +++ b/src/invidious/comments.cr @@ -211,7 +211,14 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) json.field "authorUrl", "" end - published = decode_date(node_comment["publishedTimeText"]["runs"][0]["text"].as_s.rchop(" (edited)")) + published_text = node_comment["publishedTimeText"]["runs"][0]["text"].as_s + published = decode_date(published_text.rchop(" (edited)")) + + if published_text.includes?(" (edited)") + json.field "isEdited", true + else + json.field "isEdited", false + end json.field "content", content json.field "contentHtml", content_html @@ -221,11 +228,12 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) json.field "commentId", node_comment["commentId"] json.field "authorIsChannelOwner", node_comment["authorIsChannelOwner"] - if node_comment["creatorHeart"]? + if node_comment["actionButtons"]["commentActionButtonsRenderer"]["creatorHeart"]? + hearth_data = node_comment["actionButtons"]["commentActionButtonsRenderer"]["creatorHeart"]["creatorHeartRenderer"]["creatorThumbnail"] json.field "creatorHeart" do json.object do - json.field "creatorThumbnail", node_comment["creatorHeart"]["creatorHeartRenderer"]["creatorThumbnail"]["thumbnails"][2] - json.field "creatorName", node_comment["creatorHeart"]["creatorHeartRenderer"]["creatorThumbnail"]["accessibility"]["accessibilityData"]["label"] + json.field "creatorThumbnail", hearth_data["thumbnails"][-1]["url"] + json.field "creatorName", hearth_data["accessibility"]["accessibilityData"]["label"] end end end @@ -341,11 +349,27 @@ def template_youtube_comments(comments, locale) #{child["author"]}

#{child["contentHtml"]}

- #{translate(locale, "`x` ago", recode_date(Time.unix(child["published"].as_i64)))} + #{translate(locale, "`x` ago", recode_date(Time.unix(child["published"].as_i64)))} #{child["isEdited"] == true ? translate(locale, "(edited)") : ""} | [YT] | #{number_with_separator(child["likeCount"])} + END_HTML + + if child["creatorHeart"]? + html += <<-END_HTML + +
+ +
+
🖤
+
+
+
+ END_HTML + end + + html += <<-END_HTML

#{replies_html}
From 9989c8100ae73b1f2cdfb409e66142b63d12142b Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 2 Feb 2019 15:27:19 -0600 Subject: [PATCH 087/108] Properly escape email when creating view --- src/invidious.cr | 2 +- src/invidious/views/components/player.ecr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 99f9e1af..abdd8cb9 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -1033,7 +1033,7 @@ post "/login" do |env| view_name = "subscriptions_#{sha256(user.email)[0..7]}" PG_DB.exec("CREATE MATERIALIZED VIEW #{view_name} AS \ SELECT * FROM channel_videos WHERE \ - ucid = ANY ((SELECT subscriptions FROM users WHERE email = '#{user.email}')::text[]) \ + ucid = ANY ((SELECT subscriptions FROM users WHERE email = E'#{user.email.gsub("'", "\\'")}')::text[]) \ ORDER BY published DESC;") if Kemal.config.ssl || CONFIG.https_only diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr index 7f932ef4..99f99c58 100644 --- a/src/invidious/views/components/player.ecr +++ b/src/invidious/views/components/player.ecr @@ -121,7 +121,7 @@ player.on('error', function(event) { var currentTime = player.currentTime(); var playbackRate = player.playbackRate(); - var paused = player.paused() + var paused = player.paused(); player.load(); if (currentTime > 0.5) { From ceaddbc8211b727c07bc47aa77a9cac431702fbc Mon Sep 17 00:00:00 2001 From: Agustin Ferrari Date: Sat, 2 Feb 2019 20:13:40 -0300 Subject: [PATCH 088/108] Minor fixes in CSS colors --- assets/css/default.css | 4 ++-- assets/css/lighttheme.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/css/default.css b/assets/css/default.css index 0f7e9eee..800d529a 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -1,6 +1,6 @@ .channel-owner { background-color: #008BEC; - color: beige; + color: #fff; border-radius: 9px; padding: 1px 6px; } @@ -63,7 +63,7 @@ div { } button.pure-button-primary, -a.pure-button-primary { +a.pure-button-primary, .channel-owner:hover { background-color: #a0a0a0; color: rgba(35, 35, 35, 1); } diff --git a/assets/css/lighttheme.css b/assets/css/lighttheme.css index 919d73f3..1ecd2bd0 100644 --- a/assets/css/lighttheme.css +++ b/assets/css/lighttheme.css @@ -4,6 +4,6 @@ a:active { } a { - color: #0093ff; + color: #61809b; text-decoration: none; } From 87e1fa0a28ea02ec3ab56d8d2b31990ff1fc22eb Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 2 Feb 2019 19:07:09 -0600 Subject: [PATCH 089/108] Add new text to locales --- locales/ar.json | 6 +- locales/de.json | 6 +- locales/eu.json | 548 ++++++++++++++++++++++---------------------- locales/fr.json | 6 +- locales/nb_NO.json | 6 +- locales/nl.json | 6 +- locales/pl.json | 6 +- locales/ru.json | 560 +++++++++++++++++++++++---------------------- 8 files changed, 588 insertions(+), 556 deletions(-) diff --git a/locales/ar.json b/locales/ar.json index b36f8c37..da7125f3 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -276,5 +276,9 @@ "News": "الأخبار", "Movies": "الأفلام", "Download as: ": "تحميل كـ", - "Download": "تحميل" + "Download": "تحميل", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } diff --git a/locales/de.json b/locales/de.json index e176da76..a23631a0 100644 --- a/locales/de.json +++ b/locales/de.json @@ -276,5 +276,9 @@ "News": "", "Movies": "", "Download": "", - "Download as: ": "" + "Download as: ": "", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } diff --git a/locales/eu.json b/locales/eu.json index 091612d0..b0378ea8 100644 --- a/locales/eu.json +++ b/locales/eu.json @@ -1,274 +1,278 @@ { - "`x` subscribers": "", - "`x` videos": "", - "LIVE": "", - "Shared `x` ago": "", - "Unsubscribe": "", - "Subscribe": "Harpidetu", - "Login to subscribe to `x`": "", - "View channel on YouTube": "Ikusi kanala YouTuben", - "newest": "berrienak", - "oldest": "zaharrenak", - "popular": "ospetsuenak", - "Preview page": "Aurrebista orria", - "Next page": "Hurrengo orria", - "Clear watch history?": "Garbitu ikusitakoen historia?", - "Yes": "Bai", - "No": "Ez", - "Import and Export Data": "Datuak inportatu eta esportatu", - "Import": "Inportatu", - "Import Invidious data": "Invidiouseko datuak inportatu", - "Import YouTube subscriptions": "YouTubeko harpidetzak inportatu", - "Import FreeTube subscriptions (.db)": "FreeTubeko harpidetzak inportatu (.db)", - "Import NewPipe subscriptions (.json)": "NewPipeko harpidetzak inportatu (.json)", - "Import NewPipe data (.zip)": "NewPipeko datuak inportatu (.zip)", - "Export": "Esportatu", - "Export subscriptions as OPML": "Esportatu harpidetzak OPML bezala", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "", - "Export data as JSON": "", - "Delete account?": "Kontua ezabatu?", - "History": "Historia", - "Previous page": "Aurreko orria", - "An alternative front-end to YouTube": "", - "JavaScript license information": "", - "source": "", - "Login": "", - "Login/Register": "", - "Login to Google": "", - "User ID:": "", - "Password:": "", - "Time (h:mm:ss):": "", - "Text CAPTCHA": "", - "Image CAPTCHA": "", - "Sign In": "", - "Register": "", - "Email:": "", - "Google verification code:": "", - "Preferences": "", - "Player preferences": "", - "Always loop: ": "", - "Autoplay: ": "", - "Autoplay next video: ": "", - "Listen by default: ": "", - "Default speed: ": "", - "Preferred video quality: ": "", - "Player volume: ": "", - "Default comments: ": "", - "Default captions: ": "", - "Fallback captions: ": "", - "Show related videos? ": "", - "Visual preferences": "", - "Dark mode: ": "", - "Thin mode: ": "", - "Subscription preferences": "", - "Redirect homepage to feed: ": "", - "Number of videos shown in feed: ": "", - "Sort videos by: ": "", - "published": "", - "published - reverse": "", - "alphabetically": "", - "alphabetically - reverse": "", - "channel name": "", - "channel name - reverse": "", - "Only show latest video from channel: ": "", - "Only show latest unwatched video from channel: ": "", - "Only show unwatched: ": "", - "Only show notifications (if there are any): ": "", - "Data preferences": "", - "Clear watch history": "", - "Import/Export data": "", - "Manage subscriptions": "", - "Watch history": "", - "Delete account": "", - "Save preferences": "", - "Subscription manager": "", - "`x` subscriptions": "", - "Import/Export": "", - "unsubscribe": "", - "Subscriptions": "", - "`x` unseen notifications": "", - "search": "", - "Sign out": "", - "Released under the AGPLv3 by Omar Roth.": "", - "Source available here.": "", - "View JavaScript license information.": "", - "Trending": "", - "Watch video on Youtube": "", - "Genre: ": "", - "License: ": "", - "Family friendly? ": "", - "Wilson score: ": "", - "Engagement: ": "", - "Whitelisted regions: ": "", - "Blacklisted regions: ": "", - "Shared `x`": "", - "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "", - "View YouTube comments": "", - "View more comments on Reddit": "", - "View `x` comments": "", - "View Reddit comments": "", - "Hide replies": "", - "Show replies": "", - "Incorrect password": "", - "Quota exceeded, try again in a few hours": "", - "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "", - "Invalid TFA code": "", - "Login failed. This may be because two-factor authentication is not enabled on your account.": "", - "Invalid answer": "", - "Invalid CAPTCHA": "", - "CAPTCHA is a required field": "", - "User ID is a required field": "", - "Password is a required field": "", - "Invalid username or password": "", - "Please sign in using 'Sign in with Google'": "", - "Password cannot be empty": "", - "Password cannot be longer than 55 characters": "", - "Please sign in": "", - "Invidious Private Feed for `x`": "", - "channel:`x`": "", - "Deleted or invalid channel": "", - "This channel does not exist.": "", - "Could not get channel info.": "", - "Could not fetch comments": "", - "View `x` replies": "", - "`x` ago": "", - "Load more": "", - "`x` points": "", - "Could not create mix.": "", - "Playlist is empty": "", - "Invalid playlist.": "", - "Playlist does not exist.": "", - "Could not pull trending pages.": "", - "Hidden field \"challenge\" is a required field": "", - "Hidden field \"token\" is a required field": "", - "Invalid challenge": "", - "Invalid token": "", - "Invalid user": "", - "Token is expired, please try again": "", - "English": "", - "English (auto-generated)": "", - "Afrikaans": "", - "Albanian": "", - "Amharic": "", - "Arabic": "", - "Armenian": "", - "Azerbaijani": "", - "Bangla": "", - "Basque": "", - "Belarusian": "", - "Bosnian": "", - "Bulgarian": "", - "Burmese": "", - "Catalan": "", - "Cebuano": "", - "Chinese (Simplified)": "", - "Chinese (Traditional)": "", - "Corsican": "", - "Croatian": "", - "Czech": "", - "Danish": "", - "Dutch": "", - "Esperanto": "", - "Estonian": "", - "Filipino": "", - "Finnish": "", - "French": "", - "Galician": "", - "Georgian": "", - "German": "", - "Greek": "", - "Gujarati": "", - "Haitian Creole": "", - "Hausa": "", - "Hawaiian": "", - "Hebrew": "", - "Hindi": "", - "Hmong": "", - "Hungarian": "", - "Icelandic": "", - "Igbo": "", - "Indonesian": "", - "Irish": "", - "Italian": "", - "Japanese": "", - "Javanese": "", - "Kannada": "", - "Kazakh": "", - "Khmer": "", - "Korean": "", - "Kurdish": "", - "Kyrgyz": "", - "Lao": "", - "Latin": "", - "Latvian": "", - "Lithuanian": "", - "Luxembourgish": "", - "Macedonian": "", - "Malagasy": "", - "Malay": "", - "Malayalam": "", - "Maltese": "", - "Maori": "", - "Marathi": "", - "Mongolian": "", - "Nepali": "", - "Norwegian": "", - "Nyanja": "", - "Pashto": "", - "Persian": "", - "Polish": "", - "Portuguese": "", - "Punjabi": "", - "Romanian": "", - "Russian": "", - "Samoan": "", - "Scottish Gaelic": "", - "Serbian": "", - "Shona": "", - "Sindhi": "", - "Sinhala": "", - "Slovak": "", - "Slovenian": "", - "Somali": "", - "Southern Sotho": "", - "Spanish": "", - "Spanish (Latin America)": "", - "Sundanese": "", - "Swahili": "", - "Swedish": "", - "Tajik": "", - "Tamil": "", - "Telugu": "", - "Thai": "", - "Turkish": "", - "Ukrainian": "", - "Urdu": "", - "Uzbek": "", - "Vietnamese": "", - "Welsh": "", - "Western Frisian": "", - "Xhosa": "", - "Yiddish": "", - "Yoruba": "", - "Zulu": "", - "`x` years": "", - "`x` months": "", - "`x` weeks": "", - "`x` days": "", - "`x` hours": "", - "`x` minutes": "", - "`x` seconds": "", - "Fallback comments: ": "", - "Popular": "", - "Top": "", - "About": "", - "Rating: ": "", - "Language: ": "", - "Default": "", - "Music": "", - "Gaming": "", - "News": "", - "Movies": "", - "Download": "", - "Download as: ": "" + "`x` subscribers": "", + "`x` videos": "", + "LIVE": "", + "Shared `x` ago": "", + "Unsubscribe": "", + "Subscribe": "Harpidetu", + "Login to subscribe to `x`": "", + "View channel on YouTube": "Ikusi kanala YouTuben", + "newest": "berrienak", + "oldest": "zaharrenak", + "popular": "ospetsuenak", + "Preview page": "Aurrebista orria", + "Next page": "Hurrengo orria", + "Clear watch history?": "Garbitu ikusitakoen historia?", + "Yes": "Bai", + "No": "Ez", + "Import and Export Data": "Datuak inportatu eta esportatu", + "Import": "Inportatu", + "Import Invidious data": "Invidiouseko datuak inportatu", + "Import YouTube subscriptions": "YouTubeko harpidetzak inportatu", + "Import FreeTube subscriptions (.db)": "FreeTubeko harpidetzak inportatu (.db)", + "Import NewPipe subscriptions (.json)": "NewPipeko harpidetzak inportatu (.json)", + "Import NewPipe data (.zip)": "NewPipeko datuak inportatu (.zip)", + "Export": "Esportatu", + "Export subscriptions as OPML": "Esportatu harpidetzak OPML bezala", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "", + "Export data as JSON": "", + "Delete account?": "Kontua ezabatu?", + "History": "Historia", + "Previous page": "Aurreko orria", + "An alternative front-end to YouTube": "", + "JavaScript license information": "", + "source": "", + "Login": "", + "Login/Register": "", + "Login to Google": "", + "User ID:": "", + "Password:": "", + "Time (h:mm:ss):": "", + "Text CAPTCHA": "", + "Image CAPTCHA": "", + "Sign In": "", + "Register": "", + "Email:": "", + "Google verification code:": "", + "Preferences": "", + "Player preferences": "", + "Always loop: ": "", + "Autoplay: ": "", + "Autoplay next video: ": "", + "Listen by default: ": "", + "Default speed: ": "", + "Preferred video quality: ": "", + "Player volume: ": "", + "Default comments: ": "", + "Default captions: ": "", + "Fallback captions: ": "", + "Show related videos? ": "", + "Visual preferences": "", + "Dark mode: ": "", + "Thin mode: ": "", + "Subscription preferences": "", + "Redirect homepage to feed: ": "", + "Number of videos shown in feed: ": "", + "Sort videos by: ": "", + "published": "", + "published - reverse": "", + "alphabetically": "", + "alphabetically - reverse": "", + "channel name": "", + "channel name - reverse": "", + "Only show latest video from channel: ": "", + "Only show latest unwatched video from channel: ": "", + "Only show unwatched: ": "", + "Only show notifications (if there are any): ": "", + "Data preferences": "", + "Clear watch history": "", + "Import/Export data": "", + "Manage subscriptions": "", + "Watch history": "", + "Delete account": "", + "Save preferences": "", + "Subscription manager": "", + "`x` subscriptions": "", + "Import/Export": "", + "unsubscribe": "", + "Subscriptions": "", + "`x` unseen notifications": "", + "search": "", + "Sign out": "", + "Released under the AGPLv3 by Omar Roth.": "", + "Source available here.": "", + "View JavaScript license information.": "", + "Trending": "", + "Watch video on Youtube": "", + "Genre: ": "", + "License: ": "", + "Family friendly? ": "", + "Wilson score: ": "", + "Engagement: ": "", + "Whitelisted regions: ": "", + "Blacklisted regions: ": "", + "Shared `x`": "", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "", + "View YouTube comments": "", + "View more comments on Reddit": "", + "View `x` comments": "", + "View Reddit comments": "", + "Hide replies": "", + "Show replies": "", + "Incorrect password": "", + "Quota exceeded, try again in a few hours": "", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "", + "Invalid TFA code": "", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "", + "Invalid answer": "", + "Invalid CAPTCHA": "", + "CAPTCHA is a required field": "", + "User ID is a required field": "", + "Password is a required field": "", + "Invalid username or password": "", + "Please sign in using 'Sign in with Google'": "", + "Password cannot be empty": "", + "Password cannot be longer than 55 characters": "", + "Please sign in": "", + "Invidious Private Feed for `x`": "", + "channel:`x`": "", + "Deleted or invalid channel": "", + "This channel does not exist.": "", + "Could not get channel info.": "", + "Could not fetch comments": "", + "View `x` replies": "", + "`x` ago": "", + "Load more": "", + "`x` points": "", + "Could not create mix.": "", + "Playlist is empty": "", + "Invalid playlist.": "", + "Playlist does not exist.": "", + "Could not pull trending pages.": "", + "Hidden field \"challenge\" is a required field": "", + "Hidden field \"token\" is a required field": "", + "Invalid challenge": "", + "Invalid token": "", + "Invalid user": "", + "Token is expired, please try again": "", + "English": "", + "English (auto-generated)": "", + "Afrikaans": "", + "Albanian": "", + "Amharic": "", + "Arabic": "", + "Armenian": "", + "Azerbaijani": "", + "Bangla": "", + "Basque": "", + "Belarusian": "", + "Bosnian": "", + "Bulgarian": "", + "Burmese": "", + "Catalan": "", + "Cebuano": "", + "Chinese (Simplified)": "", + "Chinese (Traditional)": "", + "Corsican": "", + "Croatian": "", + "Czech": "", + "Danish": "", + "Dutch": "", + "Esperanto": "", + "Estonian": "", + "Filipino": "", + "Finnish": "", + "French": "", + "Galician": "", + "Georgian": "", + "German": "", + "Greek": "", + "Gujarati": "", + "Haitian Creole": "", + "Hausa": "", + "Hawaiian": "", + "Hebrew": "", + "Hindi": "", + "Hmong": "", + "Hungarian": "", + "Icelandic": "", + "Igbo": "", + "Indonesian": "", + "Irish": "", + "Italian": "", + "Japanese": "", + "Javanese": "", + "Kannada": "", + "Kazakh": "", + "Khmer": "", + "Korean": "", + "Kurdish": "", + "Kyrgyz": "", + "Lao": "", + "Latin": "", + "Latvian": "", + "Lithuanian": "", + "Luxembourgish": "", + "Macedonian": "", + "Malagasy": "", + "Malay": "", + "Malayalam": "", + "Maltese": "", + "Maori": "", + "Marathi": "", + "Mongolian": "", + "Nepali": "", + "Norwegian": "", + "Nyanja": "", + "Pashto": "", + "Persian": "", + "Polish": "", + "Portuguese": "", + "Punjabi": "", + "Romanian": "", + "Russian": "", + "Samoan": "", + "Scottish Gaelic": "", + "Serbian": "", + "Shona": "", + "Sindhi": "", + "Sinhala": "", + "Slovak": "", + "Slovenian": "", + "Somali": "", + "Southern Sotho": "", + "Spanish": "", + "Spanish (Latin America)": "", + "Sundanese": "", + "Swahili": "", + "Swedish": "", + "Tajik": "", + "Tamil": "", + "Telugu": "", + "Thai": "", + "Turkish": "", + "Ukrainian": "", + "Urdu": "", + "Uzbek": "", + "Vietnamese": "", + "Welsh": "", + "Western Frisian": "", + "Xhosa": "", + "Yiddish": "", + "Yoruba": "", + "Zulu": "", + "`x` years": "", + "`x` months": "", + "`x` weeks": "", + "`x` days": "", + "`x` hours": "", + "`x` minutes": "", + "`x` seconds": "", + "Fallback comments: ": "", + "Popular": "", + "Top": "", + "About": "", + "Rating: ": "", + "Language: ": "", + "Default": "", + "Music": "", + "Gaming": "", + "News": "", + "Movies": "", + "Download": "", + "Download as: ": "", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } diff --git a/locales/fr.json b/locales/fr.json index 8d81d6cc..e4bb5111 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -270,5 +270,9 @@ "News": "", "Movies": "", "Download": "", - "Download as: ": "" + "Download as: ": "", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } diff --git a/locales/nb_NO.json b/locales/nb_NO.json index 7fe3e6a8..dd575416 100644 --- a/locales/nb_NO.json +++ b/locales/nb_NO.json @@ -270,5 +270,9 @@ "News": "", "Movies": "", "Download": "", - "Download as: ": "" + "Download as: ": "", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } diff --git a/locales/nl.json b/locales/nl.json index de681e71..0969b4cc 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -270,5 +270,9 @@ "News": "", "Movies": "", "Download": "", - "Download as: ": "" + "Download as: ": "", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } diff --git a/locales/pl.json b/locales/pl.json index 497e098d..3b46559b 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -270,5 +270,9 @@ "News": "", "Movies": "", "Download": "", - "Download as: ": "" + "Download as: ": "", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } diff --git a/locales/ru.json b/locales/ru.json index 8ade66c4..ec62cadb 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -1,280 +1,284 @@ { - "`x` subscribers": "`x` подписчиков", - "`x` videos": "`x` видео", - "LIVE": "ПРЯМОЙ ЭФИР", - "Shared `x` ago": "Опубликовано `x` назад", - "Unsubscribe": "Отписаться", - "Subscribe": "Подписаться", - "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`", - "View channel on YouTube": "Канал на YouTube", - "newest": "новые", - "oldest": "старые", - "popular": "популярные", - "Preview page": "Предварительный просмотр", - "Next page": "Следующая страница", - "Clear watch history?": "Очистить историю просмотров?", - "Yes": "Да", - "No": "Нет", - "Import and Export Data": "Импорт и экспорт данных", - "Import": "Импорт", - "Import Invidious data": "Импортировать данные Invidious", - "Import YouTube subscriptions": "Импортировать YouTube подписки", - "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)", - "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)", - "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)", - "Export": "Экспорт", - "Export subscriptions as OPML": "Экспортировать подписки в OPML", - "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)", - "Export data as JSON": "Экспортировать данные в JSON", - "Delete account?": "Удалить аккаунт?", - "History": "История", - "Previous page": "Предыдущая страница", - "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube", - "JavaScript license information": "Лицензии JavaScript", - "source": "источник", - "Login": "Войти", - "Login/Register": "Войти/Регистрация", - "Login to Google": "Войти через Google", - "User ID:": "ID пользователя:", - "Password:": "Пароль:", - "Time (h:mm:ss):": "Время (ч:мм:сс):", - "Text CAPTCHA": "Текст капчи", - "Image CAPTCHA": "Изображение капчи", - "Sign In": "Войти", - "Register": "Регистрация", - "Email:": "Эл. почта:", - "Google verification code:": "Код подтверждения Google:", - "Preferences": "Настройки", - "Player preferences": "Настройки проигрывателя", - "Always loop: ": "Всегда повторять: ", - "Autoplay: ": "Автовоспроизведение: ", - "Autoplay next video: ": "Автовоспроизведение следующего видео: ", - "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ", - "Default speed: ": "Скорость по-умолчанию: ", - "Preferred video quality: ": "Предпочтительное качество видео: ", - "Player volume: ": "Громкость воспроизведения: ", - "Default comments: ": "Источник комментариев: ", - "youtube": "YouTube", - "reddit": "Reddit", - "Default captions: ": "Субтитры по-умолчанию: ", - "Fallback captions: ": "Резервные субтитры: ", - "Show related videos? ": "Показывать похожие видео? ", - "Visual preferences": "Визуальные настройки", - "Dark mode: ": "Темная тема: ", - "Thin mode: ": "Облегченный режим: ", - "Subscription preferences": "Настройки подписок", - "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ", - "Number of videos shown in feed: ": "Число видео в ленте: ", - "Sort videos by: ": "Сортировать видео по: ", - "published": "дате публикации", - "published - reverse": "дате - обратный порядок", - "alphabetically": "алфавиту", - "alphabetically - reverse": "алфавиту - обратный порядок", - "channel name": "имени канала", - "channel name - reverse": "имени канала - обратный порядок", - "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ", - "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ", - "Only show unwatched: ": "Отображать только непросмотренные видео: ", - "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ", - "Data preferences": "Настройки данных", - "Clear watch history": "Очистить историю просмотра", - "Import/Export data": "Импорт/Экспорт данных", - "Manage subscriptions": "Управление подписками", - "Watch history": "История просмотров", - "Delete account": "Удалить аккаунт", - "Save preferences": "Сохранить настройки", - "Subscription manager": "Менеджер подписок", - "`x` subscriptions": "`x` подписок", - "Import/Export": "Импорт/Экспорт", - "unsubscribe": "отписаться", - "Subscriptions": "Подписки", - "`x` unseen notifications": "`x` новых оповещений", - "search": "поиск", - "Sign out": "Выйти", - "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.", - "Source available here.": "Исходный код доступен здесь.", - "Liberapay: ": "Liberapay: ", - "Patreon: ": "Patreon: ", - "BTC: ": "BTC: ", - "BCH: ": "BCH: ", - "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.", - "Trending": "В тренде", - "Watch video on Youtube": "Смотреть на YouTube", - "Genre: ": "Жанр: ", - "License: ": "Лицензия: ", - "Family friendly? ": "Семейный просмотр: ", - "Wilson score: ": "Рейтинг Вильсона: ", - "Engagement: ": "Вовлеченность: ", - "Whitelisted regions: ": "Доступно для: ", - "Blacklisted regions: ": "Недоступно для: ", - "Shared `x`": "Опубликовано `x`", - "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).", - "View YouTube comments": "Смотреть комментарии с YouTube", - "View more comments on Reddit": "Больше комментариев на Reddit", - "View `x` comments": "Показать `x` комментариев", - "View Reddit comments": "Смотреть комментарии с Reddit", - "Hide replies": "Скрыть ответы", - "Show replies": "Показать ответы", - "Incorrect password": "Неправильный пароль", - "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов", - "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.", - "Invalid TFA code": "Неправильный TFA код", - "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.", - "Invalid answer": "Неверный ответ", - "Invalid CAPTCHA": "Неверная капча", - "CAPTCHA is a required field": "Необходимо ввести капчу", - "User ID is a required field": "Необходимо ввести идентификатор пользователя", - "Password is a required field": "Необходимо ввести пароль", - "Invalid username or password": "Недопустимый пароль или имя пользователя", - "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google", - "Password cannot be empty": "Пароль не может быть пустым", - "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов", - "Please sign in": "Пожалуйста, войдите", - "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`", - "channel:`x`": "канал: `x`", - "Deleted or invalid channel": "Канал удален или не найден", - "This channel does not exist.": "Такой канал не существует.", - "Could not get channel info.": "Невозможно получить информацию о канале.", - "Could not fetch comments": "Невозможно получить комментарии", - "View `x` replies": "Показать `x` ответов", - "`x` ago": "`x` назад", - "Load more": "Загрузить больше", - "`x` points": "`x` очков", - "Could not create mix.": "Невозможно создать \"микс\".", - "Playlist is empty": "Плейлист пуст", - "Invalid playlist.": "Некорректный плейлист.", - "Playlist does not exist.": "Плейлист не существует.", - "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".", - "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"", - "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"", - "Invalid challenge": "Неправильный ответ в \"challenge\"", - "Invalid token": "Неправильный токен", - "Invalid user": "Недопустимое имя пользователя", - "Token is expired, please try again": "Срок действия токена истек, попробуйте позже", - "English": "Английский", - "English (auto-generated)": "Английский (созданы автоматически)", - "Afrikaans": "Африкаанс", - "Albanian": "Албанский", - "Amharic": "Амхарский", - "Arabic": "Арабский", - "Armenian": "Армянский", - "Azerbaijani": "Азербайджанский", - "Bangla": "", - "Basque": "", - "Belarusian": "", - "Bosnian": "", - "Bulgarian": "", - "Burmese": "", - "Catalan": "", - "Cebuano": "", - "Chinese (Simplified)": "", - "Chinese (Traditional)": "", - "Corsican": "", - "Croatian": "", - "Czech": "", - "Danish": "", - "Dutch": "", - "Esperanto": "", - "Estonian": "", - "Filipino": "", - "Finnish": "", - "French": "", - "Galician": "", - "Georgian": "", - "German": "", - "Greek": "", - "Gujarati": "", - "Haitian Creole": "", - "Hausa": "", - "Hawaiian": "", - "Hebrew": "", - "Hindi": "", - "Hmong": "", - "Hungarian": "", - "Icelandic": "", - "Igbo": "", - "Indonesian": "", - "Irish": "", - "Italian": "", - "Japanese": "", - "Javanese": "", - "Kannada": "", - "Kazakh": "", - "Khmer": "", - "Korean": "", - "Kurdish": "", - "Kyrgyz": "", - "Lao": "", - "Latin": "", - "Latvian": "", - "Lithuanian": "", - "Luxembourgish": "", - "Macedonian": "", - "Malagasy": "", - "Malay": "", - "Malayalam": "", - "Maltese": "", - "Maori": "", - "Marathi": "", - "Mongolian": "", - "Nepali": "", - "Norwegian": "", - "Nyanja": "", - "Pashto": "", - "Persian": "", - "Polish": "", - "Portuguese": "", - "Punjabi": "", - "Romanian": "", - "Russian": "", - "Samoan": "", - "Scottish Gaelic": "", - "Serbian": "", - "Shona": "", - "Sindhi": "", - "Sinhala": "", - "Slovak": "", - "Slovenian": "", - "Somali": "", - "Southern Sotho": "", - "Spanish": "", - "Spanish (Latin America)": "", - "Sundanese": "", - "Swahili": "", - "Swedish": "", - "Tajik": "", - "Tamil": "", - "Telugu": "", - "Thai": "", - "Turkish": "", - "Ukrainian": "", - "Urdu": "", - "Uzbek": "", - "Vietnamese": "", - "Welsh": "", - "Western Frisian": "", - "Xhosa": "", - "Yiddish": "", - "Yoruba": "", - "Zulu": "Зулусский", - "`x` years": "`x` лет", - "`x` months": "`x` месяцев", - "`x` weeks": "`x` недель", - "`x` days": "`x` дней", - "`x` hours": "`x` часов", - "`x` minutes": "`x` минут", - "`x` seconds": "`x` секунд", - "Fallback comments: ": "Резервные комментарии: ", - "Popular": "Популярное", - "Top": "Топ", - "About": "О сайте", - "Rating: ": "Рейтинг: ", - "Language: ": "Язык: ", - "Default": "По-умолчанию", - "Music": "Музыка", - "Gaming": "Игры", - "News": "Новости", - "Movies": "Фильмы", - "Download": "Скачать", - "Download as: ": "Скачать как: " + "`x` subscribers": "`x` подписчиков", + "`x` videos": "`x` видео", + "LIVE": "ПРЯМОЙ ЭФИР", + "Shared `x` ago": "Опубликовано `x` назад", + "Unsubscribe": "Отписаться", + "Subscribe": "Подписаться", + "Login to subscribe to `x`": "Войти, чтобы подписаться на `x`", + "View channel on YouTube": "Канал на YouTube", + "newest": "новые", + "oldest": "старые", + "popular": "популярные", + "Preview page": "Предварительный просмотр", + "Next page": "Следующая страница", + "Clear watch history?": "Очистить историю просмотров?", + "Yes": "Да", + "No": "Нет", + "Import and Export Data": "Импорт и экспорт данных", + "Import": "Импорт", + "Import Invidious data": "Импортировать данные Invidious", + "Import YouTube subscriptions": "Импортировать YouTube подписки", + "Import FreeTube subscriptions (.db)": "Импортировать FreeTube подписки (.db)", + "Import NewPipe subscriptions (.json)": "Импортировать NewPipe подписки (.json)", + "Import NewPipe data (.zip)": "Импортировать данные NewPipe (.zip)", + "Export": "Экспорт", + "Export subscriptions as OPML": "Экспортировать подписки в OPML", + "Export subscriptions as OPML (for NewPipe & FreeTube)": "Экспортировать подписки в OPML (для NewPipe и FreeTube)", + "Export data as JSON": "Экспортировать данные в JSON", + "Delete account?": "Удалить аккаунт?", + "History": "История", + "Previous page": "Предыдущая страница", + "An alternative front-end to YouTube": "Альтернативный фронтенд для YouTube", + "JavaScript license information": "Лицензии JavaScript", + "source": "источник", + "Login": "Войти", + "Login/Register": "Войти/Регистрация", + "Login to Google": "Войти через Google", + "User ID:": "ID пользователя:", + "Password:": "Пароль:", + "Time (h:mm:ss):": "Время (ч:мм:сс):", + "Text CAPTCHA": "Текст капчи", + "Image CAPTCHA": "Изображение капчи", + "Sign In": "Войти", + "Register": "Регистрация", + "Email:": "Эл. почта:", + "Google verification code:": "Код подтверждения Google:", + "Preferences": "Настройки", + "Player preferences": "Настройки проигрывателя", + "Always loop: ": "Всегда повторять: ", + "Autoplay: ": "Автовоспроизведение: ", + "Autoplay next video: ": "Автовоспроизведение следующего видео: ", + "Listen by default: ": "Режим \"только аудио\" по-умолчанию: ", + "Default speed: ": "Скорость по-умолчанию: ", + "Preferred video quality: ": "Предпочтительное качество видео: ", + "Player volume: ": "Громкость воспроизведения: ", + "Default comments: ": "Источник комментариев: ", + "youtube": "YouTube", + "reddit": "Reddit", + "Default captions: ": "Субтитры по-умолчанию: ", + "Fallback captions: ": "Резервные субтитры: ", + "Show related videos? ": "Показывать похожие видео? ", + "Visual preferences": "Визуальные настройки", + "Dark mode: ": "Темная тема: ", + "Thin mode: ": "Облегченный режим: ", + "Subscription preferences": "Настройки подписок", + "Redirect homepage to feed: ": "Отображать ленту вместо главной страницы: ", + "Number of videos shown in feed: ": "Число видео в ленте: ", + "Sort videos by: ": "Сортировать видео по: ", + "published": "дате публикации", + "published - reverse": "дате - обратный порядок", + "alphabetically": "алфавиту", + "alphabetically - reverse": "алфавиту - обратный порядок", + "channel name": "имени канала", + "channel name - reverse": "имени канала - обратный порядок", + "Only show latest video from channel: ": "Отображать только последние видео с каждого канала: ", + "Only show latest unwatched video from channel: ": "Отображать только непросмотренные видео с каждого канала: ", + "Only show unwatched: ": "Отображать только непросмотренные видео: ", + "Only show notifications (if there are any): ": "Отображать только оповещения (если есть): ", + "Data preferences": "Настройки данных", + "Clear watch history": "Очистить историю просмотра", + "Import/Export data": "Импорт/Экспорт данных", + "Manage subscriptions": "Управление подписками", + "Watch history": "История просмотров", + "Delete account": "Удалить аккаунт", + "Save preferences": "Сохранить настройки", + "Subscription manager": "Менеджер подписок", + "`x` subscriptions": "`x` подписок", + "Import/Export": "Импорт/Экспорт", + "unsubscribe": "отписаться", + "Subscriptions": "Подписки", + "`x` unseen notifications": "`x` новых оповещений", + "search": "поиск", + "Sign out": "Выйти", + "Released under the AGPLv3 by Omar Roth.": "Распространяется Omar Roth по AGPLv3.", + "Source available here.": "Исходный код доступен здесь.", + "Liberapay: ": "Liberapay: ", + "Patreon: ": "Patreon: ", + "BTC: ": "BTC: ", + "BCH: ": "BCH: ", + "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.", + "Trending": "В тренде", + "Watch video on Youtube": "Смотреть на YouTube", + "Genre: ": "Жанр: ", + "License: ": "Лицензия: ", + "Family friendly? ": "Семейный просмотр: ", + "Wilson score: ": "Рейтинг Вильсона: ", + "Engagement: ": "Вовлеченность: ", + "Whitelisted regions: ": "Доступно для: ", + "Blacklisted regions: ": "Недоступно для: ", + "Shared `x`": "Опубликовано `x`", + "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).", + "View YouTube comments": "Смотреть комментарии с YouTube", + "View more comments on Reddit": "Больше комментариев на Reddit", + "View `x` comments": "Показать `x` комментариев", + "View Reddit comments": "Смотреть комментарии с Reddit", + "Hide replies": "Скрыть ответы", + "Show replies": "Показать ответы", + "Incorrect password": "Неправильный пароль", + "Quota exceeded, try again in a few hours": "Превышена квота, попробуйте снова через несколько часов", + "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Вход не выполнен, проверьте, не включена ли двухфакторная аутентификация.", + "Invalid TFA code": "Неправильный TFA код", + "Login failed. This may be because two-factor authentication is not enabled on your account.": "Не удалось войти. Это может быть из-за того, что в вашем аккаунте не включена двухфакторная аутентификация.", + "Invalid answer": "Неверный ответ", + "Invalid CAPTCHA": "Неверная капча", + "CAPTCHA is a required field": "Необходимо ввести капчу", + "User ID is a required field": "Необходимо ввести идентификатор пользователя", + "Password is a required field": "Необходимо ввести пароль", + "Invalid username or password": "Недопустимый пароль или имя пользователя", + "Please sign in using 'Sign in with Google'": "Пожалуйста войдите через Google", + "Password cannot be empty": "Пароль не может быть пустым", + "Password cannot be longer than 55 characters": "Пароль не может быть длиннее 55 символов", + "Please sign in": "Пожалуйста, войдите", + "Invidious Private Feed for `x`": "Приватная лента Invidious для `x`", + "channel:`x`": "канал: `x`", + "Deleted or invalid channel": "Канал удален или не найден", + "This channel does not exist.": "Такой канал не существует.", + "Could not get channel info.": "Невозможно получить информацию о канале.", + "Could not fetch comments": "Невозможно получить комментарии", + "View `x` replies": "Показать `x` ответов", + "`x` ago": "`x` назад", + "Load more": "Загрузить больше", + "`x` points": "`x` очков", + "Could not create mix.": "Невозможно создать \"микс\".", + "Playlist is empty": "Плейлист пуст", + "Invalid playlist.": "Некорректный плейлист.", + "Playlist does not exist.": "Плейлист не существует.", + "Could not pull trending pages.": "Невозможно получить страницы \"в тренде\".", + "Hidden field \"challenge\" is a required field": "Необходимо заполнить скрытое поле \"challenge\"", + "Hidden field \"token\" is a required field": "Необходимо заполнить скрытое поле \"токен\"", + "Invalid challenge": "Неправильный ответ в \"challenge\"", + "Invalid token": "Неправильный токен", + "Invalid user": "Недопустимое имя пользователя", + "Token is expired, please try again": "Срок действия токена истек, попробуйте позже", + "English": "Английский", + "English (auto-generated)": "Английский (созданы автоматически)", + "Afrikaans": "Африкаанс", + "Albanian": "Албанский", + "Amharic": "Амхарский", + "Arabic": "Арабский", + "Armenian": "Армянский", + "Azerbaijani": "Азербайджанский", + "Bangla": "", + "Basque": "", + "Belarusian": "", + "Bosnian": "", + "Bulgarian": "", + "Burmese": "", + "Catalan": "", + "Cebuano": "", + "Chinese (Simplified)": "", + "Chinese (Traditional)": "", + "Corsican": "", + "Croatian": "", + "Czech": "", + "Danish": "", + "Dutch": "", + "Esperanto": "", + "Estonian": "", + "Filipino": "", + "Finnish": "", + "French": "", + "Galician": "", + "Georgian": "", + "German": "", + "Greek": "", + "Gujarati": "", + "Haitian Creole": "", + "Hausa": "", + "Hawaiian": "", + "Hebrew": "", + "Hindi": "", + "Hmong": "", + "Hungarian": "", + "Icelandic": "", + "Igbo": "", + "Indonesian": "", + "Irish": "", + "Italian": "", + "Japanese": "", + "Javanese": "", + "Kannada": "", + "Kazakh": "", + "Khmer": "", + "Korean": "", + "Kurdish": "", + "Kyrgyz": "", + "Lao": "", + "Latin": "", + "Latvian": "", + "Lithuanian": "", + "Luxembourgish": "", + "Macedonian": "", + "Malagasy": "", + "Malay": "", + "Malayalam": "", + "Maltese": "", + "Maori": "", + "Marathi": "", + "Mongolian": "", + "Nepali": "", + "Norwegian": "", + "Nyanja": "", + "Pashto": "", + "Persian": "", + "Polish": "", + "Portuguese": "", + "Punjabi": "", + "Romanian": "", + "Russian": "", + "Samoan": "", + "Scottish Gaelic": "", + "Serbian": "", + "Shona": "", + "Sindhi": "", + "Sinhala": "", + "Slovak": "", + "Slovenian": "", + "Somali": "", + "Southern Sotho": "", + "Spanish": "", + "Spanish (Latin America)": "", + "Sundanese": "", + "Swahili": "", + "Swedish": "", + "Tajik": "", + "Tamil": "", + "Telugu": "", + "Thai": "", + "Turkish": "", + "Ukrainian": "", + "Urdu": "", + "Uzbek": "", + "Vietnamese": "", + "Welsh": "", + "Western Frisian": "", + "Xhosa": "", + "Yiddish": "", + "Yoruba": "", + "Zulu": "Зулусский", + "`x` years": "`x` лет", + "`x` months": "`x` месяцев", + "`x` weeks": "`x` недель", + "`x` days": "`x` дней", + "`x` hours": "`x` часов", + "`x` minutes": "`x` минут", + "`x` seconds": "`x` секунд", + "Fallback comments: ": "Резервные комментарии: ", + "Popular": "Популярное", + "Top": "Топ", + "About": "О сайте", + "Rating: ": "Рейтинг: ", + "Language: ": "Язык: ", + "Default": "По-умолчанию", + "Music": "Музыка", + "Gaming": "Игры", + "News": "Новости", + "Movies": "Фильмы", + "Download": "Скачать", + "Download as: ": "Скачать как: ", + "%A %B %-d, %Y": "", + "(edited)": "", + "Youtube permalink of the comment": "", + "`x` marked it with a ❤": "" } From d0a690c30314d41661f706d66f868e6be56a0f66 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 2 Feb 2019 22:48:47 -0600 Subject: [PATCH 090/108] Add CORS to API endpoints --- src/invidious.cr | 1 + src/invidious/helpers/helpers.cr | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/invidious.cr b/src/invidious.cr index abdd8cb9..81318acf 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -3977,6 +3977,7 @@ public_folder "assets" Kemal.config.powered_by_header = false add_handler FilteredCompressHandler.new add_handler DenyFrame.new +add_handler APIHandler.new add_context_storage_type(User) Kemal.config.logger = logger diff --git a/src/invidious/helpers/helpers.cr b/src/invidious/helpers/helpers.cr index 91a80203..942757c3 100644 --- a/src/invidious/helpers/helpers.cr +++ b/src/invidious/helpers/helpers.cr @@ -43,6 +43,18 @@ class FilteredCompressHandler < Kemal::Handler end end +class APIHandler < Kemal::Handler + only ["/api/v1/*"] + + def call(env) + return call_next env unless only_match? env + + env.response.headers["Access-Control-Allow-Origin"] = "*" + + call_next env + end +end + class DenyFrame < Kemal::Handler exclude ["/embed/*"] From 2c440513182e915bcd32ec0b88bb06d318517639 Mon Sep 17 00:00:00 2001 From: Tommy Miland Date: Sun, 3 Feb 2019 12:57:01 +0100 Subject: [PATCH 091/108] Update README.md Add manual commands to Debian and Ubuntu install instructions. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index db4120da..8be021c9 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,12 @@ $ docker-compose build $ sudo pacman -S shards crystal imagemagick librsvg postgresql # Ubuntu or Debian +# First you have to add the repository to your APT configuration. For easy setup just run in your command line: $ curl -sSL https://dist.crystal-lang.org/apt/setup.sh | sudo bash -$ sudo apt update +# That will add the signing key and the repository configuration. If you prefer to do it manually, execute the following commands: +$ curl -sL "https://keybase.io/crystal/pgp_keys.asc" | sudo apt-key add - +$ echo "deb https://dist.crystal-lang.org/apt crystal main" | sudo tee /etc/apt/sources.list.d/crystal.list +$ sudo apt-get update $ sudo apt install crystal libssl-dev libxml2-dev libyaml-dev libgmp-dev libreadline-dev librsvg2-dev postgresql imagemagick libsqlite3-dev ``` From c1ed660ca0ac182c144401e7e428233af4454807 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sun, 3 Feb 2019 08:45:34 -0600 Subject: [PATCH 092/108] Proxy creator thumbnail for heart container --- src/invidious/comments.cr | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr index e6d74d1d..0bad5b2e 100644 --- a/src/invidious/comments.cr +++ b/src/invidious/comments.cr @@ -158,7 +158,7 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) comment_count = body["header"]["commentsHeaderRenderer"]["countText"]["simpleText"].as_s.delete("Comments,").to_i json.field "commentCount", comment_count end - + json.field "videoId", id json.field "comments" do @@ -213,7 +213,7 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) published_text = node_comment["publishedTimeText"]["runs"][0]["text"].as_s published = decode_date(published_text.rchop(" (edited)")) - + if published_text.includes?(" (edited)") json.field "isEdited", true else @@ -227,7 +227,7 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) json.field "likeCount", node_comment["likeCount"] json.field "commentId", node_comment["commentId"] json.field "authorIsChannelOwner", node_comment["authorIsChannelOwner"] - + if node_comment["actionButtons"]["commentActionButtonsRenderer"]["creatorHeart"]? hearth_data = node_comment["actionButtons"]["commentActionButtonsRenderer"]["creatorHeart"]["creatorHeartRenderer"]["creatorThumbnail"] json.field "creatorHeart" do @@ -349,18 +349,19 @@ def template_youtube_comments(comments, locale) #{child["author"]}

#{child["contentHtml"]}

- #{translate(locale, "`x` ago", recode_date(Time.unix(child["published"].as_i64)))} #{child["isEdited"] == true ? translate(locale, "(edited)") : ""} + #{translate(locale, "`x` ago", recode_date(Time.unix(child["published"].as_i64)))} #{child["isEdited"] == true ? translate(locale, "(edited)") : ""} | [YT] | #{number_with_separator(child["likeCount"])} END_HTML - + if child["creatorHeart"]? + creator_thumbnail = "/ggpht#{URI.parse(child["creatorHeart"]["creatorThumbnail"].as_s).full_path}" html += <<-END_HTML
- +
🖤
@@ -368,7 +369,7 @@ def template_youtube_comments(comments, locale) END_HTML end - + html += <<-END_HTML

#{replies_html} From e6e3d826b9b4af36674b7df0fba5e2dc30d08fd2 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 4 Feb 2019 12:05:31 -0600 Subject: [PATCH 093/108] Update shard.yml --- shard.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shard.yml b/shard.yml index 79997ad4..d0671664 100644 --- a/shard.yml +++ b/shard.yml @@ -13,12 +13,11 @@ dependencies: github: detectlanguage/detectlanguage-crystal kemal: github: kemalcr/kemal - commit: afd17fc pg: github: will/crystal-pg sqlite3: github: crystal-lang/crystal-sqlite3 -crystal: 0.27.0 +crystal: 0.27.1 license: AGPLv3 From ed8a9af35527fb3216f39d9e3aab197f7c5e98c0 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 4 Feb 2019 12:05:51 -0600 Subject: [PATCH 094/108] Add helpers_spec --- spec/helpers_spec.cr | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 spec/helpers_spec.cr diff --git a/spec/helpers_spec.cr b/spec/helpers_spec.cr new file mode 100644 index 00000000..d5a38c25 --- /dev/null +++ b/spec/helpers_spec.cr @@ -0,0 +1,62 @@ +require "kemal" +require "pg" +require "spec" +require "yaml" +require "../src/invidious/helpers/*" +require "../src/invidious/channels" +require "../src/invidious/playlists" +require "../src/invidious/search" + +describe "Helpers" do + describe "#produce_channel_videos_url" do + it "correctly produces url for requesting page `x` of a channel's videos" do + produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw").should eq("/browse_ajax?continuation=4qmFsgI8EhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaIEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0V4&gl=US&hl=en") + + produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw", sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJCEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJkVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0V4R0FFJTNE&gl=US&hl=en") + + produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw", page: 20).should eq("/browse_ajax?continuation=4qmFsgJEEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaKEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0l5TUElM0QlM0Q%3D&gl=US&hl=en") + + produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", auto_generated: true).should eq("/browse_ajax?continuation=4qmFsgJIEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaLEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQTJlZ294TlRRNU5qQXpOelE1&gl=US&hl=en") + + produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", page: 20, auto_generated: true, sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJOEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaMkVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQTJlZ294TkRrNU5Ea3hOelE1R0FFJTNE&gl=US&hl=en") + end + end + + describe "#produce_channel_search_url" do + it "correctly produces token for searching a specific channel" do + produce_channel_search_url("UCXuqSBlHAE6Xw-yeJA0Tunw", "", 100).should eq("/browse_ajax?continuation=4qmFsgI-EhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaIEVnWnpaV0Z5WTJnd0FqZ0JZQUZxQUxnQkFIb0RNVEF3WgA%3D") + + produce_channel_search_url("UCXuqSBlHAE6Xw-yeJA0Tunw", "По ожиशुपतिरपि子而時ஸ்றீனி", 0).should eq("/browse_ajax?continuation=4qmFsgJZEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJEVnWnpaV0Z5WTJnd0FqZ0JZQUZxQUxnQkFIb0JNQSUzRCUzRFoX0J_QviDQvtC20LjgpLbgpYHgpKrgpKTgpL_gpLDgpKrgpL_lrZDogIzmmYLgrrjgr43grrHgr4Dgrqngrr8%3D") + end + end + + describe "#produce_playlist_url" do + it "correctly produces url for requesting index `x` of a playlist" do + produce_playlist_url("UUCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIsEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoOZWdaUVZEcERRVUUlM0Q%3D") + + produce_playlist_url("UCCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIsEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoOZWdaUVZEcERRVUUlM0Q%3D") + + produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 0).should eq("/browse_ajax?continuation=4qmFsgI2EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDmVnWlFWRHBEUVVFJTNE") + + produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 10000).should eq("/browse_ajax?continuation=4qmFsgI0EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDGVnZFFWRHBEU2tKUA%3D%3D") + + produce_playlist_url("PL55713C70BA91BD6E", 0).should eq("/browse_ajax?continuation=4qmFsgImEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoOZWdaUVZEcERRVUUlM0Q%3D") + + produce_playlist_url("PL55713C70BA91BD6E", 10000).should eq("/browse_ajax?continuation=4qmFsgIkEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoMZWdkUVZEcERTa0pQ") + end + end + + describe "#produce_search_params" do + it "correctly produces token for searching with specified filters" do + produce_search_params.should eq("CAASAhAB") + + produce_search_params(sort: "upload_date", content_type: "video").should eq("CAISAhAB") + + produce_search_params(content_type: "playlist").should eq("CAASAhAD") + + produce_search_params(sort: "date", content_type: "video", features: ["hd", "cc", "purchased", "hdr"]).should eq("CAISCxABIAEwAUgByAEB") + + produce_search_params(content_type: "channel").should eq("CAASAhAC") + end + end +end From 276662a1473b3b55146f2ab9568ed385b8f09ba7 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 4 Feb 2019 15:17:10 -0600 Subject: [PATCH 095/108] Use IO::Memory for creating continuation tokens --- spec/helpers_spec.cr | 16 ++++----- src/invidious/channels.cr | 62 +++++++++++++++++++--------------- src/invidious/helpers/utils.cr | 2 +- src/invidious/playlists.cr | 43 ++++++++++++----------- src/invidious/search.cr | 57 ++++++++++++++++++------------- 5 files changed, 101 insertions(+), 79 deletions(-) diff --git a/spec/helpers_spec.cr b/spec/helpers_spec.cr index d5a38c25..fddf55a5 100644 --- a/spec/helpers_spec.cr +++ b/spec/helpers_spec.cr @@ -24,25 +24,25 @@ describe "Helpers" do describe "#produce_channel_search_url" do it "correctly produces token for searching a specific channel" do - produce_channel_search_url("UCXuqSBlHAE6Xw-yeJA0Tunw", "", 100).should eq("/browse_ajax?continuation=4qmFsgI-EhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaIEVnWnpaV0Z5WTJnd0FqZ0JZQUZxQUxnQkFIb0RNVEF3WgA%3D") + produce_channel_search_url("UCXuqSBlHAE6Xw-yeJA0Tunw", "", 100).should eq("/browse_ajax?continuation=4qmFsgI-EhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaIEVnWnpaV0Z5WTJnd0FqZ0JZQUZxQUxnQkFIb0RNVEF3WgA%3D&gl=US&hl=en") - produce_channel_search_url("UCXuqSBlHAE6Xw-yeJA0Tunw", "По ожиशुपतिरपि子而時ஸ்றீனி", 0).should eq("/browse_ajax?continuation=4qmFsgJZEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJEVnWnpaV0Z5WTJnd0FqZ0JZQUZxQUxnQkFIb0JNQSUzRCUzRFoX0J_QviDQvtC20LjgpLbgpYHgpKrgpKTgpL_gpLDgpKrgpL_lrZDogIzmmYLgrrjgr43grrHgr4Dgrqngrr8%3D") + produce_channel_search_url("UCXuqSBlHAE6Xw-yeJA0Tunw", "По ожиशुपतिरपि子而時ஸ்றீனி", 0).should eq("/browse_ajax?continuation=4qmFsgJZEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJEVnWnpaV0Z5WTJnd0FqZ0JZQUZxQUxnQkFIb0JNQSUzRCUzRFoX0J_QviDQvtC20LjgpLbgpYHgpKrgpKTgpL_gpLDgpKrgpL_lrZDogIzmmYLgrrjgr43grrHgr4Dgrqngrr8%3D&gl=US&hl=en") end end describe "#produce_playlist_url" do it "correctly produces url for requesting index `x` of a playlist" do - produce_playlist_url("UUCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIsEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoOZWdaUVZEcERRVUUlM0Q%3D") + produce_playlist_url("UUCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIsEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoOZWdaUVZEcERRVUUlM0Q%3D&gl=US&hl=en") - produce_playlist_url("UCCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIsEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoOZWdaUVZEcERRVUUlM0Q%3D") + produce_playlist_url("UCCla9fZca4I7KagBtgRGnOw", 0).should eq("/browse_ajax?continuation=4qmFsgIsEhpWTFVVQ2xhOWZaY2E0STdLYWdCdGdSR25PdxoOZWdaUVZEcERRVUUlM0Q%3D&gl=US&hl=en") - produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 0).should eq("/browse_ajax?continuation=4qmFsgI2EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDmVnWlFWRHBEUVVFJTNE") + produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 0).should eq("/browse_ajax?continuation=4qmFsgI2EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDmVnWlFWRHBEUVVFJTNE&gl=US&hl=en") - produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 10000).should eq("/browse_ajax?continuation=4qmFsgI0EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDGVnZFFWRHBEU2tKUA%3D%3D") + produce_playlist_url("PLt5AfwLFPxWLNVixpe1w3fi6lE2OTq0ET", 10000).should eq("/browse_ajax?continuation=4qmFsgI0EiRWTFBMdDVBZndMRlB4V0xOVml4cGUxdzNmaTZsRTJPVHEwRVQaDGVnZFFWRHBEU2tKUA%3D%3D&gl=US&hl=en") - produce_playlist_url("PL55713C70BA91BD6E", 0).should eq("/browse_ajax?continuation=4qmFsgImEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoOZWdaUVZEcERRVUUlM0Q%3D") + produce_playlist_url("PL55713C70BA91BD6E", 0).should eq("/browse_ajax?continuation=4qmFsgImEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoOZWdaUVZEcERRVUUlM0Q%3D&gl=US&hl=en") - produce_playlist_url("PL55713C70BA91BD6E", 10000).should eq("/browse_ajax?continuation=4qmFsgIkEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoMZWdkUVZEcERTa0pQ") + produce_playlist_url("PL55713C70BA91BD6E", 10000).should eq("/browse_ajax?continuation=4qmFsgIkEhRWTFBMNTU3MTNDNzBCQTkxQkQ2RRoMZWdkUVZEcERTa0pQ&gl=US&hl=en") end end diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr index c1915a10..28fbdcd6 100644 --- a/src/invidious/channels.cr +++ b/src/invidious/channels.cr @@ -202,50 +202,58 @@ def produce_channel_videos_url(ucid, page = 1, auto_generated = nil, sort_by = " timestamp = seed - (page - 1).months page = "#{timestamp.to_unix}" - switch = "\x36" + switch = 0x36 else page = "#{page}" - switch = "\x00" + switch = 0x00 end - meta = "\x12\x06videos" - meta += "\x30\x02" - meta += "\x38\x01" - meta += "\x60\x01" - meta += "\x6a\x00" - meta += "\xb8\x01\x00" - meta += "\x20#{switch}" - meta += "\x7a" - meta += page.size.to_u8.unsafe_chr - meta += page + meta = IO::Memory.new + meta.write(Bytes[0x12, 0x06]) + meta.print("videos") + + meta.write(Bytes[0x30, 0x02]) + meta.write(Bytes[0x38, 0x01]) + meta.write(Bytes[0x60, 0x01]) + meta.write(Bytes[0x6a, 0x00]) + meta.write(Bytes[0xb8, 0x01, 0x00]) + + meta.write(Bytes[0x20, switch, 0x7a, page.size]) + meta.print(page) case sort_by when "newest" # Empty tags can be omitted - # meta += "\x18\x00" + # meta.write(Bytes[0x18,0x00]) when "popular" - meta += "\x18\x01" + meta.write(Bytes[0x18, 0x01]) when "oldest" - meta += "\x18\x02" + meta.write(Bytes[0x18, 0x02]) end - meta = Base64.urlsafe_encode(meta) + meta.rewind + meta = Base64.urlsafe_encode(meta.to_slice) meta = URI.escape(meta) - continuation = "\x12" - continuation += ucid.size.to_u8.unsafe_chr - continuation += ucid - continuation += "\x1a" - continuation += meta.size.to_u8.unsafe_chr - continuation += meta + continuation = IO::Memory.new + continuation.write(Bytes[0x12, ucid.size]) + continuation.print(ucid) - continuation = continuation.size.to_u8.unsafe_chr + continuation - continuation = "\xe2\xa9\x85\xb2\x02" + continuation + continuation.write(Bytes[0x1a, meta.size]) + continuation.print(meta) - continuation = Base64.urlsafe_encode(continuation) - continuation = URI.escape(continuation) + continuation.rewind + continuation = continuation.gets_to_end - url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en" + wrapper = IO::Memory.new + wrapper.write(Bytes[0xe2, 0xa9, 0x85, 0xb2, 0x02, continuation.size]) + wrapper.print(continuation) + wrapper.rewind + + wrapper = Base64.urlsafe_encode(wrapper.to_slice) + wrapper = URI.escape(wrapper) + + url = "/browse_ajax?continuation=#{wrapper}&gl=US&hl=en" return url end diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 07c4bff3..282e8ce5 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -282,7 +282,7 @@ def write_var_int(value : Int) end end - return bytes + return Slice.new(bytes.to_unsafe, bytes.size) end def sha256(text) diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr index 6e48bacf..28f2e4ce 100644 --- a/src/invidious/playlists.cr +++ b/src/invidious/playlists.cr @@ -126,32 +126,37 @@ def produce_playlist_url(id, index) end ucid = "VL" + id - meta = [0x08_u8] + write_var_int(index) - meta = Slice.new(meta.to_unsafe, meta.size) - meta = Base64.urlsafe_encode(meta, false) + meta = IO::Memory.new + meta.write(Bytes[0x08]) + meta.write(write_var_int(index)) + + meta.rewind + meta = Base64.urlsafe_encode(meta.to_slice, false) meta = "PT:#{meta}" - wrapped = "\x7a" - wrapped += meta.bytes.size.unsafe_chr - wrapped += meta + continuation = IO::Memory.new + continuation.write(Bytes[0x7a, meta.size]) + continuation.print(meta) - wrapped = Base64.urlsafe_encode(wrapped) - meta = URI.escape(wrapped) + continuation.rewind + meta = Base64.urlsafe_encode(continuation.to_slice) + meta = URI.escape(meta) - continuation = "\x12" - continuation += ucid.size.unsafe_chr - continuation += ucid - continuation += "\x1a" - continuation += meta.bytes.size.unsafe_chr - continuation += meta + continuation = IO::Memory.new + continuation.write(Bytes[0x12, ucid.size]) + continuation.print(ucid) + continuation.write(Bytes[0x1a, meta.size]) + continuation.print(meta) - continuation = continuation.size.to_u8.unsafe_chr + continuation - continuation = "\xe2\xa9\x85\xb2\x02" + continuation + wrapper = IO::Memory.new + wrapper.write(Bytes[0xe2, 0xa9, 0x85, 0xb2, 0x02, continuation.size]) + wrapper.print(continuation) + wrapper.rewind - continuation = Base64.urlsafe_encode(continuation) - continuation = URI.escape(continuation) + wrapper = Base64.urlsafe_encode(wrapper.to_slice) + wrapper = URI.escape(wrapper) - url = "/browse_ajax?continuation=#{continuation}" + url = "/browse_ajax?continuation=#{wrapper}&gl=US&hl=en" return url end diff --git a/src/invidious/search.cr b/src/invidious/search.cr index 97104b02..20e34c24 100644 --- a/src/invidious/search.cr +++ b/src/invidious/search.cr @@ -203,36 +203,45 @@ end def produce_channel_search_url(ucid, query, page) page = "#{page}" - meta = "\x12\x06search" - meta += "\x30\x02" - meta += "\x38\x01" - meta += "\x60\x01" - meta += "\x6a\x00" - meta += "\xb8\x01\x00" - meta += "\x7a" - meta += page.size.unsafe_chr - meta += page + meta = IO::Memory.new + meta.write(Bytes[0x12, 0x06]) + meta.print("search") - meta = Base64.urlsafe_encode(meta) + meta.write(Bytes[0x30, 0x02]) + meta.write(Bytes[0x38, 0x01]) + meta.write(Bytes[0x60, 0x01]) + meta.write(Bytes[0x6a, 0x00]) + meta.write(Bytes[0xb8, 0x01, 0x00]) + + meta.write(Bytes[0x7a, page.size]) + meta.print(page) + + meta.rewind + meta = Base64.urlsafe_encode(meta.to_slice) meta = URI.escape(meta) - continuation = "\x12" - continuation += ucid.size.unsafe_chr - continuation += ucid - continuation += "\x1a" - continuation += meta.size.unsafe_chr - continuation += meta - continuation += "\x5a" - continuation += query.size.unsafe_chr - continuation += query + continuation = IO::Memory.new + continuation.write(Bytes[0x12, ucid.size]) + continuation.print(ucid) - continuation = continuation.size.unsafe_chr + continuation - continuation = "\xe2\xa9\x85\xb2\x02" + continuation + continuation.write(Bytes[0x1a, meta.size]) + continuation.print(meta) - continuation = Base64.urlsafe_encode(continuation) - continuation = URI.escape(continuation) + continuation.write(Bytes[0x5a, query.size]) + continuation.print(query) - url = "/browse_ajax?continuation=#{continuation}" + continuation.rewind + continuation = continuation.gets_to_end + + wrapper = IO::Memory.new + wrapper.write(Bytes[0xe2, 0xa9, 0x85, 0xb2, 0x02, continuation.size]) + wrapper.print(continuation) + wrapper.rewind + + wrapper = Base64.urlsafe_encode(wrapper.to_slice) + wrapper = URI.escape(wrapper) + + url = "/browse_ajax?continuation=#{wrapper}&gl=US&hl=en" return url end From 2630dc8dcd5d1460b395406eead144dd04cd7ba0 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 4 Feb 2019 15:28:51 -0600 Subject: [PATCH 096/108] Add 'related_videos' to video params --- src/invidious/videos.cr | 5 +++++ src/invidious/views/watch.ecr | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index a95f5443..21c87edf 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -725,6 +725,7 @@ end def process_video_params(query, preferences) autoplay = query["autoplay"]?.try &.to_i? continue = query["continue"]?.try &.to_i? + related_videos = query["related_videos"]? listen = query["listen"]? && (query["listen"] == "true" || query["listen"] == "1").to_unsafe preferred_captions = query["subtitles"]?.try &.split(",").map { |a| a.downcase } quality = query["quality"]? @@ -737,6 +738,7 @@ def process_video_params(query, preferences) # region ||= preferences.region autoplay ||= preferences.autoplay.to_unsafe continue ||= preferences.continue.to_unsafe + related_videos ||= preferences.related_videos.to_unsafe listen ||= preferences.listen.to_unsafe preferred_captions ||= preferences.captions quality ||= preferences.quality @@ -747,6 +749,7 @@ def process_video_params(query, preferences) autoplay ||= DEFAULT_USER_PREFERENCES.autoplay.to_unsafe continue ||= DEFAULT_USER_PREFERENCES.continue.to_unsafe + related_videos ||= DEFAULT_USER_PREFERENCES.related_videos.to_unsafe listen ||= DEFAULT_USER_PREFERENCES.listen.to_unsafe preferred_captions ||= DEFAULT_USER_PREFERENCES.captions quality ||= DEFAULT_USER_PREFERENCES.quality @@ -756,6 +759,7 @@ def process_video_params(query, preferences) autoplay = autoplay == 1 continue = continue == 1 + related_videos = related_videos == 1 listen = listen == 1 video_loop = video_loop == 1 @@ -793,6 +797,7 @@ def process_video_params(query, preferences) quality: quality, raw: raw, region: region, + related_videos: related_videos, speed: speed, video_end: video_end, video_loop: video_loop, diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr index a8f98492..7ba5ae7f 100644 --- a/src/invidious/views/watch.ecr +++ b/src/invidious/views/watch.ecr @@ -110,7 +110,7 @@
- - <% if !preferences || preferences && preferences.related_videos || plid %> + <% if params[:related_videos] || plid %>
<% if plid %>
<% end %> - <% if !preferences || preferences && preferences.related_videos %> + <% if params[:related_videos] %>
<% if !rvs.empty? %> From f225d38680b4013c9c6d4f27247160996a694146 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Mon, 4 Feb 2019 15:34:53 -0600 Subject: [PATCH 097/108] Revert updated dependencies --- shard.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/shard.yml b/shard.yml index d0671664..def9b06d 100644 --- a/shard.yml +++ b/shard.yml @@ -13,6 +13,7 @@ dependencies: github: detectlanguage/detectlanguage-crystal kemal: github: kemalcr/kemal + commit: afd17fc pg: github: will/crystal-pg sqlite3: From 699f85e773c7e69ac081c2361be3de89541accf5 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Tue, 5 Feb 2019 08:49:24 -0600 Subject: [PATCH 098/108] Fix Google login --- src/invidious.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious.cr b/src/invidious.cr index 81318acf..b85baa19 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -814,7 +814,7 @@ post "/login" do |env| if challenge_results[0][-1][0].as_a? # Prefer Authenticator app and SMS over unsupported protocols - if challenge_results[0][-1][0][0][8] != 6 || challenge_results[0][-1][0][0][8] != 9 + if challenge_results[0][-1][0][0][8] != 6 && challenge_results[0][-1][0][0][8] != 9 tfa = challenge_results[0][-1][0].as_a.select { |auth_type| auth_type[8] == 6 || auth_type[8] == 9 }[0] select_challenge = "[#{challenge_results[0][-1][0].as_a.index(tfa).not_nil!}]" From 8170dad9bd9f10a67234db73b2ace31df98af671 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 6 Feb 2019 16:12:11 -0600 Subject: [PATCH 099/108] Simplify video extractor --- src/invidious/videos.cr | 121 ++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 61 deletions(-) diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 21c87edf..2219d145 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -542,53 +542,69 @@ def get_video(id, db, proxies = {} of String => Array({ip: String, port: Int32}) return video end +def extract_player_config(body, html) + html_info = body.match(/ytplayer\.config = (?.*?);ytplayer\.load/).try &.["info"] + params = HTTP::Params.new + + if html_info + JSON.parse(html_info)["args"].as_h.each do |key, value| + params[key] = value.to_s + end + + if md = body.match(/'XSRF_TOKEN': "(?[A-Za-z0-9\_\-\=]+)"/) + params["session_token"] = md["session_token"] + end + + if md = body.match(/itct=(?[^"]+)"/) + params["itct"] = md["itct"] + end + + if md = body.match(/'COMMENTS_TOKEN': "(?[^"]+)"/) + params["ctoken"] = md["ctoken"] + end + + # 'RELATED_PLAYER_ARGS': {"rvs":"endscreen_autoplay_session_data=autonav%3D1%26itct%3DCBYQ4ZIBIhMIkLz0mYuo4AIVBBRgCh0s8Q_4KPgdMgxyZWxhdGVkLWF1dG9IxLTo_IDLvsmwAQ%253D%253D%26playnext%3D1\u0026iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FnofDVbl437Q%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCjePolZCv0jzoC8xQnJToXvVUniA\u0026session_data=itct%3DCBUQvU4YACITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+Official+YouTube+Channel\u0026id=nofDVbl437Q\u0026title=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+%E3%80%8E%E3%82%A2%E3%82%A4%E3%83%A9%E3%83%96%E3%83%A6%E3%83%BC%E3%80%8FMV%28Short+Ver.%29\u0026short_view_count_text=5.4M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FnofDVbl437Q%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCjePolZCv0jzoC8xQnJToXvVUniA\u0026length_seconds=101,thumbnail_ids=VeP9jRiTazc\u0026session_data=itct%3DCBQQvk4YASITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026playlist_iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FsJL6WA-aGkQ%2Fmqdefault.jpg\u0026playlist_length=0\u0026list=RDsJL6WA-aGkQ\u0026video_id=VeP9jRiTazc\u0026playlist_title=Mix+-+%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+%E3%80%8EDear+Bride%E3%80%8FMV%28Short+Ver.%29\u0026playlist_iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FsJL6WA-aGkQ%2Fhqdefault.jpg,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FSX_ViT4Ra7k%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCNnEUPZeEd4VerhkKn_JRt27Iu5A\u0026session_data=itct%3DCBMQvU4YAiITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E7%B1%B3%E6%B4%A5%E7%8E%84%E5%B8%AB\u0026id=SX_ViT4Ra7k\u0026title=%E7%B1%B3%E6%B4%A5%E7%8E%84%E5%B8%AB++MV%E3%80%8CLemon%E3%80%8D\u0026short_view_count_text=297M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FSX_ViT4Ra7k%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCNnEUPZeEd4VerhkKn_JRt27Iu5A\u0026length_seconds=275,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDeGkiItB9d8%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDL_BPCIkguhgTWn24lmm_9TOTXKA\u0026session_data=itct%3DCBIQvU4YAyITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E6%AC%85%E5%9D%8246+OFFICIAL+YouTube+CHANNEL\u0026id=DeGkiItB9d8\u0026title=%E6%AC%85%E5%9D%8246+%E3%80%8E%E3%82%B5%E3%82%A4%E3%83%AC%E3%83%B3%E3%83%88%E3%83%9E%E3%82%B8%E3%83%A7%E3%83%AA%E3%83%86%E3%82%A3%E3%83%BC%E3%80%8F\u0026short_view_count_text=118M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDeGkiItB9d8%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDL_BPCIkguhgTWn24lmm_9TOTXKA\u0026length_seconds=267,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJ5Z7tIq7bco%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCO8gs2FfZwdwc_sQDFAx91lHYdxA\u0026session_data=itct%3DCBEQvU4YBCITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=OfficeAugusta\u0026id=J5Z7tIq7bco\u0026title=%E3%82%B9%E3%82%AD%E3%83%9E%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81+%2F+%E5%A5%8F%28%E3%81%8B%E3%81%AA%E3%81%A7%29+%E3%80%8C%E3%82%B9%E3%82%AD%E3%83%9E%E3%83%8E%E3%83%8F%E3%83%8A%E3%82%BF%E3%83%90+%EF%BD%9ELove+Song+Selection%EF%BD%9E%E3%80%8D2018%E5%B9%B49%E6%9C%8819%E6%97%A5%E7%99%BA%E5%A3%B2%EF%BC%81\u0026short_view_count_text=96M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJ5Z7tIq7bco%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCO8gs2FfZwdwc_sQDFAx91lHYdxA\u0026length_seconds=345,thumbnail_ids=JZqplTvRex8\u0026session_data=itct%3DCBAQvk4YBSITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026playlist_iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJZqplTvRex8%2Fmqdefault.jpg\u0026playlist_length=503\u0026list=PLH8SlvExlZpESVwF5uiYLVKI9NCQTSlHO\u0026video_id=JZqplTvRex8\u0026playlist_title=%E3%80%90400%E6%9B%B2%E3%80%91%E9%82%A6%E6%A5%BD+%E3%83%A9%E3%83%B3%E3%82%AD%E3%83%B3%E3%82%B0+%E6%9C%80%E6%96%B0+2019%E5%B9%B4+2018%E5%B9%B4+2017%E5%B9%B4+2016%E5%B9%B4+2015%E5%B9%B4+J-POP+J%E3%83%9D%E3%83%83%E3%83%97+%E5%90%8D%E6%9B%B2%E9%9B%86\u0026playlist_iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJZqplTvRex8%2Fhqdefault.jpg,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FWA4iX5D9Z64%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLC_mXb4rEzwwNIcdNtHDWh8aLuEbw\u0026session_data=itct%3DCA8QvU4YBiITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=TaylorSwiftVEVO\u0026id=WA4iX5D9Z64\u0026title=Taylor+Swift+-+We+Are+Never+Ever+Getting+Back+Together\u0026short_view_count_text=558M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FWA4iX5D9Z64%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLC_mXb4rEzwwNIcdNtHDWh8aLuEbw\u0026length_seconds=216,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FaPHGClLjZWk%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBl5J229L8gTC5TUTPVLi3yrk438w\u0026session_data=itct%3DCA4QvU4YByITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+Official+YouTube+Channel\u0026id=aPHGClLjZWk\u0026title=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+%E3%80%8E%E3%83%88%E3%83%AA%E3%82%BB%E3%83%84%E3%80%8FMV%28Short+Ver.%29\u0026short_view_count_text=53M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FaPHGClLjZWk%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBl5J229L8gTC5TUTPVLi3yrk438w\u0026length_seconds=135,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FhzWDXge2ANM%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLAc4Sk_-Uap8_Qf9470Lkvuhvv2ag\u0026session_data=itct%3DCA0QvU4YCCITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=UNIVERSAL+MUSIC+JAPAN\u0026id=hzWDXge2ANM\u0026title=back+number+-+%E3%80%8C%E3%83%8F%E3%83%83%E3%83%94%E3%83%BC%E3%82%A8%E3%83%B3%E3%83%89%E3%80%8DMusic+Video\u0026short_view_count_text=40M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FhzWDXge2ANM%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLAc4Sk_-Uap8_Qf9470Lkvuhvv2ag\u0026length_seconds=119,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FM1HRI_egra4%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBpY8yFrVNSRQnEbnTRyLh4M8PYDg\u0026session_data=itct%3DCAwQvU4YCSITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=JUJU+Official+YouTube+Channel\u0026id=M1HRI_egra4\u0026title=JUJU+%E3%80%8C%E3%81%84%E3%81%84%E3%82%8F%E3%81%91%E3%80%8D%C3%97%E7%9F%A2%E6%B2%A2%E3%81%82%E3%81%84+%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%91%E3%82%A4%E3%82%A2%E3%83%BC%E3%83%89%E3%83%A0%E3%83%BC%E3%83%93%E3%83%BC\u0026short_view_count_text=3.7M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FM1HRI_egra4%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBpY8yFrVNSRQnEbnTRyLh4M8PYDg\u0026length_seconds=214,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FPDSkFeMVNFs%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLD2fA627uKtoKe5ZPhiY61AW1RoIA\u0026session_data=itct%3DCAsQvU4YCiITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=radwimpsstaff\u0026id=PDSkFeMVNFs\u0026title=%E5%89%8D%E5%89%8D%E5%89%8D%E4%B8%96+%28movie+ver.%29+RADWIMPS+MV\u0026short_view_count_text=206M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FPDSkFeMVNFs%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLD2fA627uKtoKe5ZPhiY61AW1RoIA\u0026length_seconds=293,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FiLnX9s0EJhU%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDuEGQQJpN61f5Yr7QIAGxnkhfbcw\u0026session_data=itct%3DCAoQvU4YCyITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=avex\u0026id=iLnX9s0EJhU\u0026title=AAA+%2F+%E3%80%8CLil%27+Infinity%E3%80%8DMusic+Video\u0026short_view_count_text=25M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FiLnX9s0EJhU%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDuEGQQJpN61f5Yr7QIAGxnkhfbcw\u0026length_seconds=328"}, + if md = body.match(/'RELATED_PLAYER_ARGS': (?{"rvs":"[^"]+"})/) + params["rvs"] = JSON.parse(md["rvs"])["rvs"].as_s + end + else + error_message = html.xpath_node(%q(//h1[@id="unavailable-message"])) + if error_message + params["reason"] = error_message.content.strip + else + params["reason"] = "Could not extract video info." + end + end + + return params +end + def fetch_video(id, proxies, region) - html_channel = Channel(XML::Node | String).new - info_channel = Channel(HTTP::Params).new + client = make_client(YT_URL, proxies, region) + response = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999") - spawn do - client = make_client(YT_URL, proxies, region) - html = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999") - - if md = html.headers["location"]?.try &.match(/v=(?[a-zA-Z0-9_-]{11})/) - next html_channel.send(md["id"]) - end - - html = XML.parse_html(html.body) - html_channel.send(html) + if md = response.headers["location"]?.try &.match(/v=(?[a-zA-Z0-9_-]{11})/) + raise VideoRedirect.new(md["id"]) end - spawn do - client = make_client(YT_URL, proxies, region) - info = client.get("/get_video_info?video_id=#{id}&el=detailpage&ps=default&eurl=&gl=US&hl=en&disable_polymer=1") - info = HTTP::Params.parse(info.body) - - if info["reason"]? - info = client.get("/get_video_info?video_id=#{id}&ps=default&eurl=&gl=US&hl=en&disable_polymer=1") - info = HTTP::Params.parse(info.body) - end - - info_channel.send(info) - end - - html = html_channel.receive - if html.as?(String) - raise VideoRedirect.new("#{html.as(String)}") - end - html = html.as(XML::Node) - - info = info_channel.receive + html = XML.parse_html(response.body) + info = extract_player_config(response.body, html) + # Try to use proxies for region-blocked videos if info["reason"]? && info["reason"].includes? "your country" - bypass_channel = Channel({HTTPClient, String} | Nil).new + bypass_channel = Channel({XML::Node, HTTP::Params} | Nil).new proxies.each do |proxy_region, list| spawn do client = make_client(YT_URL, proxies, proxy_region) + body = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999").body - info = HTTP::Params.parse(client.get("/get_video_info?video_id=#{id}&ps=default&eurl=&gl=US&hl=en&disable_polymer=1").body) - if !info["reason"]? - bypass_channel.send({client, proxy_region}) + proxy_html = XML.parse_html(body) + proxy_info = extract_player_config(body, proxy_html) + + if !proxy_info["reason"]? + proxy_info["region"] = proxy_region + bypass_channel.send({proxy_html, proxy_info}) else bypass_channel.send(nil) end @@ -598,37 +614,19 @@ def fetch_video(id, proxies, region) proxies.size.times do response = bypass_channel.receive if response - begin - client, proxy_region = response - - html = XML.parse_html(client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999").body) - info = HTTP::Params.parse(client.get("/get_video_info?video_id=#{id}&el=detailpage&ps=default&eurl=&gl=US&hl=en&disable_polymer=1").body) - - if info["reason"]? - info = HTTP::Params.parse(client.get("/get_video_info?video_id=#{id}&ps=default&eurl=&gl=US&hl=en&disable_polymer=1").body) - end - - info["region"] = proxy_region - - break - rescue ex - end + html, info = response + break end end end + # Try to pull streams from embed URL if info["reason"]? - html_info = html.to_s.match(/ytplayer\.config = (?.*?);ytplayer\.load/).try &.["info"] - if html_info - html_info = JSON.parse(html_info)["args"].as_h - info.delete("reason") + embed_info = HTTP::Params.parse(client.get("/get_video_info?video_id=#{id}&ps=default&eurl=&gl=US&hl=en&disable_polymer=1").body) - html_info.each do |k, v| - info[k] = v.to_s - end - end - - if info["reason"]? + if !embed_info["reason"]? + info = embed_info + else raise info["reason"] end end @@ -668,6 +666,7 @@ def fetch_video(id, proxies, region) allowed_regions = html.xpath_node(%q(//meta[@itemprop="regionsAllowed"])).try &.["content"].split(",") allowed_regions ||= [] of String + is_family_friendly = html.xpath_node(%q(//meta[@itemprop="isFamilyFriendly"])).try &.["content"] == "True" is_family_friendly ||= true From 1dcfa90c8e86d6604cff9da045acbb0f736ea6a8 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 6 Feb 2019 17:49:28 -0600 Subject: [PATCH 100/108] Update version and bump changelog --- CHANGELOG.md | 76 +++++++++++++++++++++++++++++++++++++++ shard.yml | 2 +- src/invidious/comments.cr | 2 +- 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99b4adf5..46de1263 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,79 @@ +# 0.14.0 (2019-02-06) + +## Version 0.14.0: Community + +This last month several contributors have made improvements specifically for the people using this project. New pages have been added to the wiki, and there is now a [Matrix Server](https://riot.im/app/#/room/#invidious:matrix.org) and IRC channel so it's easier and faster for people to ask questions or chat. There have been [101 commits](https://github.com/omarroth/invidious/compare/0.13.0...0.14.0) since the last major release from 8 contributors. + +It has come to my attention in the past month how many people are self-hosting, and I would like to make it easier for them to do so. + +With that in mind, expect future releases to have a section for For Administrators (if any relevant changes) and For Developers (if any relevant changes). + +## For Administrators + +This month the most notable change for administrators is releases. As always, there will be a major release each month. However, a new minor release will be made whenever there are any critical bugs that need to be fixed. + +This past month is the first time there has been a minor release - `0.13.1` - which fixes a breaking change made by YouTube. Administrators using versioning for their instances will be able to rely on the latest version, and should have a system in place to upgrade their instance as soon as a new release is available. + +Several new pages have been added to the [wiki](https://github.com/omarroth/invidious/wiki#for-administrators) (as mentioned below) that will help administrators better setup their own instances. Configuration, maintenance, and instructions for updating are of note, as well as several common issues that are encountered when first setting up. + +## For Developers + +There's now a `pretty=1` parameter for most endpoints so you can view data easily from the browser, which is convenient for debugging and casual use. You can see an example [here](https://invidio.us/api/v1/videos/CvFH_6DNRCY?pretty=1). + +Unfortunately the `/api/v1/insights/:id` endpoint is no longer functional, as YouTube removed all publicly available analytics around a month ago. The YouTube endpoint now returns a 404, so it's unlikely it will be functional again. + +## Wiki + +There have been a sizable number of changes to the Wiki, including a [list of public Invidious instances](https://github.com/omarroth/invidious/wiki/Invidious-Instances), the [list of extensions](https://github.com/omarroth/invidious/wiki/Extensions), and documentation for administrators (as mentioned above) and developers. + +The wiki is editable by anyone so feel free to add anything you think is useful. + +## Matrix & IRC + +Thee is now a [Matrix Server](https://riot.im/app/#/room/#invidious:matrix.org) for Invidious, so please feel free to hop on if you have any questions or want to chat. There is also a registered IRC channel: #invidious on Freenode which is bridged to Matrix. + +## Features + +Several new features have been added, including a download button, creator hearts and comment colors, and a French translation. + +There have been fixes for Google logins, missing text in locales, invalid links to genre channels, and better error handling in the player, among others. + +Several fixes and features are omitted for space, so I'd recommend taking a look at the [compare tab](https://github.com/omarroth/invidious/compare/0.13.0...0.14.0) for more information. + +## Annotations Update + +Annotations were removed January 15th, 2019 around15:00 UTC. Before they were deleted we were able to archive annotations from around 1.4 billion videos. I'd very much recommend taking a look [here](https://www.reddit.com/r/DataHoarder/comments/al7exa/youtube_annotation_archive_update_and_preview/) for more information and a list of acknowledgements. I'm extremely thankful to everyone who was able to contribute and I'm glad we were able to save such a large part of internet history. + +There's been large strides in supporting them in the player as well, which you can follow in [#303](https://github.com/omarroth/invidious/pull/303). You can preview the functionality at https://dev.invidio.us . Before they are added to the main site expect to see an option to disable them, both site-wide and per video. + +Organizing this project has unfortunately taken up quite a bit of my time, and I've been very grateful for everyone's patience. + +## Finances + +### Donations + +- [Patreon](https://www.patreon.com/omarroth) : \$49.42 +- [Liberapay](https://liberapay.com/omarroth) : \$27.89 +- Crypto : ~\$0.00 (converted from BCH, BTC) +- Total : \$77.31 + +### Expenses + +invidious-load1 (nyc1) : $10.00 (load balancer) +invidious-update1 (s-1vcpu-1gb) : $5.00 (updates feeds) +invidious-node1 (s-1vcpu-1gb) : $5.00 (web server) +invidious-node2 (s-1vcpu-1gb) : $5.00 (web server) +invidious-node3 (s-1vcpu-1gb) : $5.00 (web server) +invidious-node4 (s-1vcpu-1gb) : $5.00 (web server) +invidious-db1 (s-4vcpu-8gb) : $40.00 (database) +Total : $75.00 + +As always I'm grateful for everyone's contributions and support. I'll see you all in March. + +# 0.13.1 (2019-01-19) + +## + # 0.13.0 (2019-01-06) ## Version 0.13.0: Translations, Annotations, and Tor diff --git a/shard.yml b/shard.yml index def9b06d..e0fea2ee 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: invidious -version: 0.13.1 +version: 0.14.0 authors: - Omar Roth diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr index 0bad5b2e..4c51cbcb 100644 --- a/src/invidious/comments.cr +++ b/src/invidious/comments.cr @@ -291,7 +291,7 @@ end def fetch_reddit_comments(id) client = make_client(REDDIT_URL) - headers = HTTP::Headers{"User-Agent" => "web:invidio.us:v0.13.1 (by /u/omarroth)"} + headers = HTTP::Headers{"User-Agent" => "web:invidio.us:v0.14.0 (by /u/omarroth)"} query = "(url:3D#{id}%20OR%20url:#{id})%20(site:youtube.com%20OR%20site:youtu.be)" search_results = client.get("/search.json?q=#{query}", headers) From d625d0ffbdc23306e279c47fb55ef9d2b18990c6 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 6 Feb 2019 17:55:22 -0600 Subject: [PATCH 101/108] Use get_video for pulling comment token --- src/invidious.cr | 11 ++++--- src/invidious/comments.cr | 67 ++++++++------------------------------- src/invidious/videos.cr | 48 +++++++++++++++------------- 3 files changed, 46 insertions(+), 80 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index b85baa19..ddd3084f 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -254,6 +254,7 @@ end get "/watch" do |env| locale = LOCALES[env.get("locale").as(String)]? + region = env.params.query["region"]? if env.params.query.to_s.includes?("%20") || env.params.query.to_s.includes?("+") url = "/watch?" + env.params.query.to_s.gsub("%20", "").delete("+") @@ -323,7 +324,7 @@ get "/watch" do |env| if source == "youtube" begin - comment_html = JSON.parse(fetch_youtube_comments(id, "", proxies, "html", locale))["contentHtml"] + comment_html = JSON.parse(fetch_youtube_comments(id, PG_DB, nil, proxies, "html", locale, region))["contentHtml"] rescue ex if preferences.comments[1] == "reddit" comments, reddit_thread = fetch_reddit_comments(id) @@ -342,12 +343,12 @@ get "/watch" do |env| comment_html = replace_links(comment_html) rescue ex if preferences.comments[1] == "youtube" - comment_html = JSON.parse(fetch_youtube_comments(id, "", proxies, "html", locale))["contentHtml"] + comment_html = JSON.parse(fetch_youtube_comments(id, PG_DB, nil, proxies, "html", locale, region))["contentHtml"] end end end else - comment_html = JSON.parse(fetch_youtube_comments(id, "", proxies, "html", locale))["contentHtml"] + comment_html = JSON.parse(fetch_youtube_comments(id, PG_DB, nil, proxies, "html", locale, region))["contentHtml"] end comment_html ||= "" @@ -2329,6 +2330,7 @@ end get "/api/v1/comments/:id" do |env| locale = LOCALES[env.get("locale").as(String)]? + region = env.params.query["region"]? env.response.content_type = "application/json" @@ -2341,11 +2343,10 @@ get "/api/v1/comments/:id" do |env| format ||= "json" continuation = env.params.query["continuation"]? - continuation ||= "" if source == "youtube" begin - comments = fetch_youtube_comments(id, continuation, proxies, format, locale) + comments = fetch_youtube_comments(id, PG_DB, continuation, proxies, format, locale, region) rescue ex error_message = {"error" => ex.message}.to_json halt env, status_code: 500, response: error_message diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr index 4c51cbcb..bd377611 100644 --- a/src/invidious/comments.cr +++ b/src/invidious/comments.cr @@ -56,72 +56,32 @@ class RedditListing }) end -def fetch_youtube_comments(id, continuation, proxies, format, locale) - client = make_client(YT_URL) - html = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999") - headers = HTTP::Headers.new - headers["cookie"] = html.cookies.add_request_headers(headers)["cookie"] - body = html.body +def fetch_youtube_comments(id, db, continuation, proxies, format, locale, region) + video = get_video(id, db, proxies, region: region) - session_token = body.match(/'XSRF_TOKEN': "(?[A-Za-z0-9\_\-\=]+)"/).not_nil!["session_token"] - itct = body.match(/itct=(?[^"]+)"/).not_nil!["itct"] - ctoken = body.match(/'COMMENTS_TOKEN': "(?[^"]+)"/) + session_token = video.info["session_token"]? + itct = video.info["itct"]? + ctoken = video.info["ctoken"]? + continuation ||= ctoken - if body.match(//) && !body.match(/player-age-gate-content\">/) - bypass_channel = Channel({String, HTTPClient, HTTP::Headers} | Nil).new - - proxies.each do |proxy_region, list| - spawn do - proxy_client = make_client(YT_URL, proxies, proxy_region) - - response = proxy_client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999") - proxy_headers = HTTP::Headers.new - proxy_headers["Cookie"] = response.cookies.add_request_headers(headers)["cookie"] - proxy_html = response.body - - if !proxy_html.match(//) && !proxy_html.match(/player-age-gate-content\">/) - bypass_channel.send({proxy_html, proxy_client, proxy_headers}) - else - bypass_channel.send(nil) - end - end - end - - proxies.size.times do - response = bypass_channel.receive - if response - html, client, headers = response - - session_token = html.match(/'XSRF_TOKEN': "(?[A-Za-z0-9\_\-\=]+)"/).not_nil!["session_token"] - itct = html.match(/itct=(?[^"]+)"/).not_nil!["itct"] - ctoken = html.match(/'COMMENTS_TOKEN': "(?[^"]+)"/) - - break - end - end - end - - if !ctoken + if !continuation || !itct || !session_token if format == "json" return {"comments" => [] of String}.to_json else return {"contentHtml" => "", "commentCount" => 0}.to_json end end - ctoken = ctoken["ctoken"] - - if !continuation.empty? - ctoken = continuation - else - continuation = ctoken - end post_req = { - "session_token" => session_token, + "session_token" => session_token.not_nil!, } post_req = HTTP::Params.encode(post_req) + client = make_client(YT_URL, proxies, video.info["region"]?) + headers = HTTP::Headers.new + headers["content-type"] = "application/x-www-form-urlencoded" + headers["cookie"] = video.info["cookie"] headers["x-client-data"] = "CIi2yQEIpbbJAQipncoBCNedygEIqKPKAQ==" headers["x-spf-previous"] = "https://www.youtube.com/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999" @@ -129,7 +89,8 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale) headers["x-youtube-client-name"] = "1" headers["x-youtube-client-version"] = "2.20180719" - response = client.post("/comment_service_ajax?action_get_comments=1&pbj=1&ctoken=#{ctoken}&continuation=#{continuation}&itct=#{itct}&hl=en&gl=US", headers, post_req) + + response = client.post("/comment_service_ajax?action_get_comments=1&pbj=1&ctoken=#{continuation}&continuation=#{continuation}&itct=#{itct}&hl=en&gl=US", headers, post_req) response = JSON.parse(response.body) if !response["response"]["continuationContents"]? diff --git a/src/invidious/videos.cr b/src/invidious/videos.cr index 2219d145..4a3beac8 100644 --- a/src/invidious/videos.cr +++ b/src/invidious/videos.cr @@ -543,30 +543,30 @@ def get_video(id, db, proxies = {} of String => Array({ip: String, port: Int32}) end def extract_player_config(body, html) - html_info = body.match(/ytplayer\.config = (?.*?);ytplayer\.load/).try &.["info"] params = HTTP::Params.new + if md = body.match(/'XSRF_TOKEN': "(?[A-Za-z0-9\_\-\=]+)"/) + params["session_token"] = md["session_token"] + end + + if md = body.match(/itct=(?[^"]+)"/) + params["itct"] = md["itct"] + end + + if md = body.match(/'COMMENTS_TOKEN': "(?[^"]+)"/) + params["ctoken"] = md["ctoken"] + end + + if md = body.match(/'RELATED_PLAYER_ARGS': (?{"rvs":"[^"]+"})/) + params["rvs"] = JSON.parse(md["rvs"])["rvs"].as_s + end + + html_info = body.match(/ytplayer\.config = (?.*?);ytplayer\.load/).try &.["info"] + if html_info JSON.parse(html_info)["args"].as_h.each do |key, value| params[key] = value.to_s end - - if md = body.match(/'XSRF_TOKEN': "(?[A-Za-z0-9\_\-\=]+)"/) - params["session_token"] = md["session_token"] - end - - if md = body.match(/itct=(?[^"]+)"/) - params["itct"] = md["itct"] - end - - if md = body.match(/'COMMENTS_TOKEN': "(?[^"]+)"/) - params["ctoken"] = md["ctoken"] - end - - # 'RELATED_PLAYER_ARGS': {"rvs":"endscreen_autoplay_session_data=autonav%3D1%26itct%3DCBYQ4ZIBIhMIkLz0mYuo4AIVBBRgCh0s8Q_4KPgdMgxyZWxhdGVkLWF1dG9IxLTo_IDLvsmwAQ%253D%253D%26playnext%3D1\u0026iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FnofDVbl437Q%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCjePolZCv0jzoC8xQnJToXvVUniA\u0026session_data=itct%3DCBUQvU4YACITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+Official+YouTube+Channel\u0026id=nofDVbl437Q\u0026title=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+%E3%80%8E%E3%82%A2%E3%82%A4%E3%83%A9%E3%83%96%E3%83%A6%E3%83%BC%E3%80%8FMV%28Short+Ver.%29\u0026short_view_count_text=5.4M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FnofDVbl437Q%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCjePolZCv0jzoC8xQnJToXvVUniA\u0026length_seconds=101,thumbnail_ids=VeP9jRiTazc\u0026session_data=itct%3DCBQQvk4YASITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026playlist_iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FsJL6WA-aGkQ%2Fmqdefault.jpg\u0026playlist_length=0\u0026list=RDsJL6WA-aGkQ\u0026video_id=VeP9jRiTazc\u0026playlist_title=Mix+-+%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+%E3%80%8EDear+Bride%E3%80%8FMV%28Short+Ver.%29\u0026playlist_iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FsJL6WA-aGkQ%2Fhqdefault.jpg,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FSX_ViT4Ra7k%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCNnEUPZeEd4VerhkKn_JRt27Iu5A\u0026session_data=itct%3DCBMQvU4YAiITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E7%B1%B3%E6%B4%A5%E7%8E%84%E5%B8%AB\u0026id=SX_ViT4Ra7k\u0026title=%E7%B1%B3%E6%B4%A5%E7%8E%84%E5%B8%AB++MV%E3%80%8CLemon%E3%80%8D\u0026short_view_count_text=297M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FSX_ViT4Ra7k%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCNnEUPZeEd4VerhkKn_JRt27Iu5A\u0026length_seconds=275,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDeGkiItB9d8%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDL_BPCIkguhgTWn24lmm_9TOTXKA\u0026session_data=itct%3DCBIQvU4YAyITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E6%AC%85%E5%9D%8246+OFFICIAL+YouTube+CHANNEL\u0026id=DeGkiItB9d8\u0026title=%E6%AC%85%E5%9D%8246+%E3%80%8E%E3%82%B5%E3%82%A4%E3%83%AC%E3%83%B3%E3%83%88%E3%83%9E%E3%82%B8%E3%83%A7%E3%83%AA%E3%83%86%E3%82%A3%E3%83%BC%E3%80%8F\u0026short_view_count_text=118M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDeGkiItB9d8%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDL_BPCIkguhgTWn24lmm_9TOTXKA\u0026length_seconds=267,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJ5Z7tIq7bco%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCO8gs2FfZwdwc_sQDFAx91lHYdxA\u0026session_data=itct%3DCBEQvU4YBCITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=OfficeAugusta\u0026id=J5Z7tIq7bco\u0026title=%E3%82%B9%E3%82%AD%E3%83%9E%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81+%2F+%E5%A5%8F%28%E3%81%8B%E3%81%AA%E3%81%A7%29+%E3%80%8C%E3%82%B9%E3%82%AD%E3%83%9E%E3%83%8E%E3%83%8F%E3%83%8A%E3%82%BF%E3%83%90+%EF%BD%9ELove+Song+Selection%EF%BD%9E%E3%80%8D2018%E5%B9%B49%E6%9C%8819%E6%97%A5%E7%99%BA%E5%A3%B2%EF%BC%81\u0026short_view_count_text=96M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJ5Z7tIq7bco%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLCO8gs2FfZwdwc_sQDFAx91lHYdxA\u0026length_seconds=345,thumbnail_ids=JZqplTvRex8\u0026session_data=itct%3DCBAQvk4YBSITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026playlist_iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJZqplTvRex8%2Fmqdefault.jpg\u0026playlist_length=503\u0026list=PLH8SlvExlZpESVwF5uiYLVKI9NCQTSlHO\u0026video_id=JZqplTvRex8\u0026playlist_title=%E3%80%90400%E6%9B%B2%E3%80%91%E9%82%A6%E6%A5%BD+%E3%83%A9%E3%83%B3%E3%82%AD%E3%83%B3%E3%82%B0+%E6%9C%80%E6%96%B0+2019%E5%B9%B4+2018%E5%B9%B4+2017%E5%B9%B4+2016%E5%B9%B4+2015%E5%B9%B4+J-POP+J%E3%83%9D%E3%83%83%E3%83%97+%E5%90%8D%E6%9B%B2%E9%9B%86\u0026playlist_iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FJZqplTvRex8%2Fhqdefault.jpg,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FWA4iX5D9Z64%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLC_mXb4rEzwwNIcdNtHDWh8aLuEbw\u0026session_data=itct%3DCA8QvU4YBiITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=TaylorSwiftVEVO\u0026id=WA4iX5D9Z64\u0026title=Taylor+Swift+-+We+Are+Never+Ever+Getting+Back+Together\u0026short_view_count_text=558M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FWA4iX5D9Z64%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLC_mXb4rEzwwNIcdNtHDWh8aLuEbw\u0026length_seconds=216,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FaPHGClLjZWk%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBl5J229L8gTC5TUTPVLi3yrk438w\u0026session_data=itct%3DCA4QvU4YByITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+Official+YouTube+Channel\u0026id=aPHGClLjZWk\u0026title=%E8%A5%BF%E9%87%8E%E3%82%AB%E3%83%8A+%E3%80%8E%E3%83%88%E3%83%AA%E3%82%BB%E3%83%84%E3%80%8FMV%28Short+Ver.%29\u0026short_view_count_text=53M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FaPHGClLjZWk%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBl5J229L8gTC5TUTPVLi3yrk438w\u0026length_seconds=135,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FhzWDXge2ANM%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLAc4Sk_-Uap8_Qf9470Lkvuhvv2ag\u0026session_data=itct%3DCA0QvU4YCCITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=UNIVERSAL+MUSIC+JAPAN\u0026id=hzWDXge2ANM\u0026title=back+number+-+%E3%80%8C%E3%83%8F%E3%83%83%E3%83%94%E3%83%BC%E3%82%A8%E3%83%B3%E3%83%89%E3%80%8DMusic+Video\u0026short_view_count_text=40M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FhzWDXge2ANM%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLAc4Sk_-Uap8_Qf9470Lkvuhvv2ag\u0026length_seconds=119,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FM1HRI_egra4%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBpY8yFrVNSRQnEbnTRyLh4M8PYDg\u0026session_data=itct%3DCAwQvU4YCSITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=JUJU+Official+YouTube+Channel\u0026id=M1HRI_egra4\u0026title=JUJU+%E3%80%8C%E3%81%84%E3%81%84%E3%82%8F%E3%81%91%E3%80%8D%C3%97%E7%9F%A2%E6%B2%A2%E3%81%82%E3%81%84+%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%91%E3%82%A4%E3%82%A2%E3%83%BC%E3%83%89%E3%83%A0%E3%83%BC%E3%83%93%E3%83%BC\u0026short_view_count_text=3.7M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FM1HRI_egra4%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLBpY8yFrVNSRQnEbnTRyLh4M8PYDg\u0026length_seconds=214,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FPDSkFeMVNFs%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLD2fA627uKtoKe5ZPhiY61AW1RoIA\u0026session_data=itct%3DCAsQvU4YCiITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=radwimpsstaff\u0026id=PDSkFeMVNFs\u0026title=%E5%89%8D%E5%89%8D%E5%89%8D%E4%B8%96+%28movie+ver.%29+RADWIMPS+MV\u0026short_view_count_text=206M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FPDSkFeMVNFs%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLD2fA627uKtoKe5ZPhiY61AW1RoIA\u0026length_seconds=293,iurlhq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FiLnX9s0EJhU%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDuEGQQJpN61f5Yr7QIAGxnkhfbcw\u0026session_data=itct%3DCAoQvU4YCyITCJC89JmLqOACFQQUYAodLPEP-Cj4HTIJZW5kc2NyZWVuSMS06PyAy77JsAE%253D\u0026author=avex\u0026id=iLnX9s0EJhU\u0026title=AAA+%2F+%E3%80%8CLil%27+Infinity%E3%80%8DMusic+Video\u0026short_view_count_text=25M+views\u0026iurlmq=https%3A%2F%2Fi.ytimg.com%2Fvi%2FiLnX9s0EJhU%2Fhqdefault.jpg%3Fsqp%3D-oaymwEjCNACELwBSFryq4qpAxUIARUAAAAAGAElAADIQj0AgKJDeAE%3D%26rs%3DAOn4CLDuEGQQJpN61f5Yr7QIAGxnkhfbcw\u0026length_seconds=328"}, - if md = body.match(/'RELATED_PLAYER_ARGS': (?{"rvs":"[^"]+"})/) - params["rvs"] = JSON.parse(md["rvs"])["rvs"].as_s - end else error_message = html.xpath_node(%q(//h1[@id="unavailable-message"])) if error_message @@ -589,6 +589,7 @@ def fetch_video(id, proxies, region) html = XML.parse_html(response.body) info = extract_player_config(response.body, html) + info["cookie"] = response.cookies.to_h.map { |name, cookie| "#{name}=#{cookie.value}" }.join("; ") # Try to use proxies for region-blocked videos if info["reason"]? && info["reason"].includes? "your country" @@ -597,13 +598,14 @@ def fetch_video(id, proxies, region) proxies.each do |proxy_region, list| spawn do client = make_client(YT_URL, proxies, proxy_region) - body = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999").body + proxy_response = client.get("/watch?v=#{id}&gl=US&hl=en&disable_polymer=1&has_verified=1&bpctr=9999999999") - proxy_html = XML.parse_html(body) - proxy_info = extract_player_config(body, proxy_html) + proxy_html = XML.parse_html(proxy_response.body) + proxy_info = extract_player_config(proxy_response.body, proxy_html) if !proxy_info["reason"]? proxy_info["region"] = proxy_region + proxy_info["cookie"] = proxy_response.cookies.to_h.map { |name, cookie| "#{name}=#{cookie.value}" }.join("; ") bypass_channel.send({proxy_html, proxy_info}) else bypass_channel.send(nil) @@ -625,7 +627,9 @@ def fetch_video(id, proxies, region) embed_info = HTTP::Params.parse(client.get("/get_video_info?video_id=#{id}&ps=default&eurl=&gl=US&hl=en&disable_polymer=1").body) if !embed_info["reason"]? - info = embed_info + embed_info.each do |key, value| + info[key] = value.to_s + end else raise info["reason"] end From a7b79824de7fdcadd5139a1e5ccf7870c194b305 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 6 Feb 2019 18:21:40 -0600 Subject: [PATCH 102/108] Add support for 'region' in search --- src/invidious.cr | 7 ++++--- src/invidious/search.cr | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index ddd3084f..87305db6 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -596,6 +596,7 @@ end get "/search" do |env| locale = LOCALES[env.get("locale").as(String)]? + region = env.params.query["region"]? query = env.params.query["search_query"]? query ||= env.params.query["q"]? @@ -671,7 +672,7 @@ get "/search" do |env| next templated "error" end - count, videos = search(search_query, page, search_params).as(Tuple) + count, videos = search(search_query, page, search_params, proxies, region).as(Tuple) end templated "search" @@ -3199,6 +3200,7 @@ end get "/api/v1/search" do |env| locale = LOCALES[env.get("locale").as(String)]? + region = env.params.query["region"]? env.response.content_type = "application/json" @@ -3220,7 +3222,6 @@ get "/api/v1/search" do |env| features = env.params.query["features"]?.try &.split(",").map { |feature| feature.downcase } features ||= [] of String - # TODO: Support other content types content_type = env.params.query["type"]?.try &.downcase content_type ||= "video" @@ -3235,7 +3236,7 @@ get "/api/v1/search" do |env| end end - count, search_results = search(query, page, search_params).as(Tuple) + count, search_results = search(query, page, search_params, proxies, region).as(Tuple) response = JSON.build do |json| json.array do search_results.each do |item| diff --git a/src/invidious/search.cr b/src/invidious/search.cr index 20e34c24..ce29abf2 100644 --- a/src/invidious/search.cr +++ b/src/invidious/search.cr @@ -85,8 +85,8 @@ def channel_search(query, page, channel) return count, items end -def search(query, page = 1, search_params = produce_search_params(content_type: "all")) - client = make_client(YT_URL) +def search(query, page = 1, search_params = produce_search_params(content_type: "all"), proxies = nil, region = nil) + client = make_client(YT_URL, proxies, region) if query.empty? return {0, [] of SearchItem} end From 29af5fc4a684ce6e47234e58cb53591f682f9e35 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Wed, 6 Feb 2019 21:29:31 -0600 Subject: [PATCH 103/108] Prune proxy list --- src/invidious/helpers/proxy.cr | 47 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/invidious/helpers/proxy.cr b/src/invidious/helpers/proxy.cr index 5f073f6f..e3c9d2f5 100644 --- a/src/invidious/helpers/proxy.cr +++ b/src/invidious/helpers/proxy.cr @@ -281,28 +281,27 @@ def y_func(c) end PROXY_LIST = { - "GB" => [{ip: "104.248.168.237", port: 3128}, {ip: "104.248.170.188", port: 3128}, {ip: "104.248.172.86", port: 3128}, {ip: "104.248.172.93", port: 3128}, {ip: "104.248.175.70", port: 3128}, {ip: "138.68.165.69", port: 3128}, {ip: "139.59.166.82", port: 3128}, {ip: "139.59.172.14", port: 3128}, {ip: "139.59.178.103", port: 3128}, {ip: "139.59.178.138", port: 3128}, {ip: "139.59.179.135", port: 3128}, {ip: "139.59.180.116", port: 3128}, {ip: "139.59.180.180", port: 3128}, {ip: "139.59.183.122", port: 3128}, {ip: "139.59.184.152", port: 3128}, {ip: "139.59.187.163", port: 3128}, {ip: "139.59.188.126", port: 3128}, {ip: "147.135.206.233", port: 3128}, {ip: "159.65.212.57", port: 1080}, {ip: "159.65.86.33", port: 8080}, {ip: "167.114.180.102", port: 8080}, {ip: "167.99.197.45", port: 8080}, {ip: "167.99.80.103", port: 8080}, {ip: "167.99.87.19", port: 8080}, {ip: "176.35.250.108", port: 8080}, {ip: "176.35.51.2", port: 53281}, {ip: "176.35.85.11", port: 8080}, {ip: "178.62.114.9", port: 3128}, {ip: "178.62.114.9", port: 80}, {ip: "178.62.115.223", port: 3128}, {ip: "178.62.34.134", port: 3128}, {ip: "178.62.45.209", port: 3128}, {ip: "178.62.53.74", port: 3128}, {ip: "178.62.92.127", port: 3128}, {ip: "185.44.249.86", port: 31910}, {ip: "188.166.152.229", port: 3128}, {ip: "188.166.156.20", port: 3128}, {ip: "193.117.138.126", port: 31667}, {ip: "206.189.114.111", port: 8080}, {ip: "206.189.117.27", port: 8080}, {ip: "206.189.28.51", port: 3128}, {ip: "206.189.29.172", port: 8080}, {ip: "209.97.182.186", port: 3128}, {ip: "209.97.188.156", port: 3128}, {ip: "209.97.188.44", port: 8080}, {ip: "209.97.191.221", port: 8080}, {ip: "212.139.190.90", port: 42321}, {ip: "217.33.203.90", port: 53281}, {ip: "35.176.85.90", port: 3128}, {ip: "46.101.1.193", port: 3128}, {ip: "46.101.12.219", port: 3128}, {ip: "46.101.28.32", port: 3128}, {ip: "46.101.30.74", port: 3128}, {ip: "46.101.32.61", port: 3128}, {ip: "46.101.38.243", port: 3128}, {ip: "46.101.43.233", port: 3128}, {ip: "46.101.46.249", port: 80}, {ip: "46.101.54.10", port: 3128}, {ip: "46.101.92.31", port: 3128}, {ip: "5.148.128.44", port: 80}, {ip: "62.232.62.238", port: 8080}, {ip: "62.255.104.214", port: 8080}, {ip: "62.7.85.234", port: 8080}, {ip: "78.158.54.213", port: 44564}, {ip: "79.170.192.143", port: 38805}, {ip: "79.78.184.12", port: 56834}, {ip: "80.251.9.246", port: 8080}, {ip: "81.136.143.191", port: 41352}, {ip: "81.174.247.181", port: 8118}, {ip: "81.199.32.150", port: 42767}, {ip: "81.199.32.90", port: 45152}, {ip: "82.31.209.22", port: 51368}, {ip: "84.9.99.187", port: 52786}, {ip: "85.91.252.25", port: 41298}, {ip: "85.91.252.27", port: 44565}, {ip: "88.150.135.10", port: 36624}, {ip: "88.97.50.200", port: 57317}], - "DE" => [{ip: "104.248.135.57", port: 8080}, {ip: "104.248.246.246", port: 8080}, {ip: "109.192.91.198", port: 53701}, {ip: "130.180.28.106", port: 42036}, {ip: "130.193.112.146", port: 36923}, {ip: "138.197.182.74", port: 80}, {ip: "138.201.223.250", port: 31288}, {ip: "138.68.69.65", port: 3128}, {ip: "138.68.73.59", port: 32574}, {ip: "138.68.91.20", port: 3128}, {ip: "142.93.163.12", port: 3128}, {ip: "144.76.76.25", port: 3128}, {ip: "149.172.217.53", port: 8080}, {ip: "159.69.210.89", port: 3128}, {ip: "159.69.210.89", port: 80}, {ip: "159.69.211.173", port: 3128}, {ip: "172.94.14.56", port: 34213}, {ip: "173.212.219.151", port: 3128}, {ip: "173.212.240.229", port: 3128}, {ip: "173.249.43.105", port: 3128}, {ip: "176.9.6.85", port: 8080}, {ip: "185.27.10.31", port: 49484}, {ip: "188.40.149.69", port: 36941}, {ip: "188.40.166.196", port: 3128}, {ip: "194.25.235.130", port: 47565}, {ip: "199.247.20.246", port: 8080}, {ip: "207.154.200.199", port: 3128}, {ip: "212.202.244.90", port: 8080}, {ip: "213.208.34.242", port: 39085}, {ip: "213.71.139.113", port: 8080}, {ip: "217.160.235.78", port: 3128}, {ip: "217.8.55.201", port: 32231}, {ip: "24.134.35.197", port: 44418}, {ip: "37.221.192.231", port: 3128}, {ip: "46.101.148.121", port: 80}, {ip: "46.4.35.218", port: 8080}, {ip: "5.189.131.87", port: 3128}, {ip: "5.189.144.198", port: 3128}, {ip: "5.189.165.39", port: 3128}, {ip: "5.45.108.185", port: 8118}, {ip: "5.56.18.35", port: 38827}, {ip: "5.9.58.22", port: 3128}, {ip: "78.47.151.98", port: 8888}, {ip: "80.147.158.52", port: 3128}, {ip: "80.155.171.82", port: 8080}, {ip: "81.89.101.243", port: 3128}, {ip: "85.214.240.42", port: 3128}, {ip: "87.106.23.164", port: 3128}, {ip: "87.138.207.100", port: 3128}, {ip: "88.99.110.138", port: 3128}, {ip: "88.99.149.188", port: 31288}, {ip: "88.99.217.12", port: 3128}, {ip: "91.205.172.156", port: 3128}, {ip: "94.130.126.72", port: 8080}, {ip: "94.16.120.18", port: 5555}, {ip: "95.89.19.67", port: 3128}, {ip: "95.90.165.51", port: 43241}], - "FR" => [{ip: "137.74.254.242", port: 3128}, {ip: "140.82.55.214", port: 3128}, {ip: "151.80.135.147", port: 3128}, {ip: "151.80.143.155", port: 53281}, {ip: "163.172.134.194", port: 3128}, {ip: "167.114.247.229", port: 9999}, {ip: "178.33.150.97", port: 3128}, {ip: "185.163.62.121", port: 55943}, {ip: "188.165.5.140", port: 3128}, {ip: "193.248.44.112", port: 45134}, {ip: "195.154.41.145", port: 56748}, {ip: "37.187.121.205", port: 3128}, {ip: "37.187.2.31", port: 3128}, {ip: "37.187.99.146", port: 3128}, {ip: "5.135.164.72", port: 3128}, {ip: "5.135.83.96", port: 44058}, {ip: "5.39.91.73", port: 3128}, {ip: "51.15.190.56", port: 3128}, {ip: "51.15.229.200", port: 3128}, {ip: "51.15.69.7", port: 3128}, {ip: "51.38.135.29", port: 3128}, {ip: "51.38.162.2", port: 32231}, {ip: "51.38.217.121", port: 808}, {ip: "51.38.234.95", port: 8080}, {ip: "51.38.91.21", port: 8080}, {ip: "51.75.109.81", port: 3128}, {ip: "51.75.109.82", port: 3128}, {ip: "51.75.109.83", port: 3128}, {ip: "51.75.109.84", port: 3128}, {ip: "51.75.109.85", port: 3128}, {ip: "51.75.109.86", port: 3128}, {ip: "51.75.109.88", port: 3128}, {ip: "51.75.109.89", port: 3128}, {ip: "51.75.109.90", port: 3128}, {ip: "51.75.109.93", port: 3128}, {ip: "51.75.109.94", port: 3128}, {ip: "51.75.25.8", port: 3133}, {ip: "54.36.28.158", port: 3128}, {ip: "62.210.151.46", port: 8080}, {ip: "62.210.167.3", port: 3128}, {ip: "77.90.120.20", port: 51956}, {ip: "81.252.195.242", port: 3128}, {ip: "82.127.192.44", port: 50871}, {ip: "83.206.17.138", port: 3128}, {ip: "84.22.68.141", port: 44224}, {ip: "90.63.218.232", port: 8080}, {ip: "90.84.240.81", port: 3128}, {ip: "91.121.110.107", port: 8118}, {ip: "91.134.137.116", port: 9999}, {ip: "91.134.165.198", port: 9999}], - "IN" => [{ip: "1.186.151.206", port: 36253}, {ip: "1.186.192.242", port: 60891}, {ip: "1.186.239.230", port: 8080}, {ip: "1.186.242.20", port: 56781}, {ip: "1.186.40.2", port: 54754}, {ip: "1.186.40.9", port: 54754}, {ip: "1.186.63.130", port: 39142}, {ip: "101.0.36.17", port: 38125}, {ip: "103.100.80.42", port: 8080}, {ip: "103.102.72.191", port: 44507}, {ip: "103.102.72.197", port: 8080}, {ip: "103.102.72.8", port: 54368}, {ip: "103.102.72.82", port: 42903}, {ip: "103.102.73.77", port: 43519}, {ip: "103.102.73.83", port: 52133}, {ip: "103.103.212.222", port: 53281}, {ip: "103.105.237.6", port: 60887}, {ip: "103.105.40.1", port: 16538}, {ip: "103.105.40.145", port: 16538}, {ip: "103.105.40.153", port: 16538}, {ip: "103.106.101.10", port: 45100}, {ip: "103.106.101.14", port: 45100}, {ip: "103.106.148.203", port: 60227}, {ip: "103.106.148.207", port: 51451}, {ip: "103.107.179.173", port: 44914}, {ip: "103.108.83.135", port: 41673}, {ip: "103.108.96.247", port: 56287}, {ip: "103.109.14.237", port: 60458}, {ip: "103.109.178.87", port: 38004}, {ip: "103.109.179.199", port: 34427}, {ip: "103.112.9.12", port: 33823}, {ip: "103.112.9.31", port: 58817}, {ip: "103.116.37.22", port: 47359}, {ip: "103.12.135.78", port: 8080}, {ip: "103.12.246.12", port: 8080}, {ip: "103.12.246.13", port: 8080}, {ip: "103.14.196.2", port: 53281}, {ip: "103.14.198.144", port: 53281}, {ip: "103.14.199.225", port: 53281}, {ip: "103.14.234.22", port: 8080}, {ip: "103.14.235.109", port: 8080}, {ip: "103.14.235.26", port: 8080}, {ip: "103.18.152.22", port: 32967}, {ip: "103.192.169.186", port: 53528}, {ip: "103.193.199.126", port: 54004}, {ip: "103.193.255.170", port: 43342}, {ip: "103.193.255.247", port: 53377}, {ip: "103.194.248.72", port: 46970}, {ip: "103.194.248.87", port: 8080}, {ip: "103.194.88.10", port: 56432}, {ip: "103.194.88.129", port: 47565}, {ip: "103.194.88.45", port: 45027}, {ip: "103.194.88.77", port: 56602}, {ip: "103.194.88.78", port: 52785}, {ip: "103.195.24.83", port: 21776}, {ip: "103.195.25.79", port: 36127}, {ip: "103.195.37.89", port: 8080}, {ip: "103.198.172.3", port: 44392}, {ip: "103.198.172.4", port: 50820}, {ip: "103.199.157.133", port: 41687}, {ip: "103.199.157.209", port: 41687}, {ip: "103.199.159.177", port: 35249}, {ip: "103.204.191.35", port: 43479}, {ip: "103.204.231.210", port: 35978}, {ip: "103.205.112.1", port: 23500}, {ip: "103.205.112.129", port: 23500}, {ip: "103.206.128.137", port: 30764}, {ip: "103.206.130.242", port: 36827}, {ip: "103.208.202.10", port: 48699}, {ip: "103.209.64.19", port: 6666}, {ip: "103.209.65.12", port: 6666}, {ip: "103.21.163.76", port: 6666}, {ip: "103.210.28.70", port: 8080}, {ip: "103.211.76.18", port: 31491}, {ip: "103.211.76.5", port: 8080}, {ip: "103.212.128.147", port: 41940}, {ip: "103.212.128.75", port: 46719}, {ip: "103.212.93.193", port: 43476}, {ip: "103.215.134.56", port: 45612}, {ip: "103.215.201.120", port: 42682}, {ip: "103.216.144.17", port: 8080}, {ip: "103.216.144.21", port: 8080}, {ip: "103.216.169.33", port: 8080}, {ip: "103.216.82.153", port: 6666}, {ip: "103.216.82.19", port: 6666}, {ip: "103.216.82.190", port: 6666}, {ip: "103.216.82.195", port: 6666}, {ip: "103.216.82.196", port: 6666}, {ip: "103.216.82.200", port: 6666}, {ip: "103.216.82.209", port: 54806}, {ip: "103.216.82.214", port: 6666}, {ip: "103.216.82.29", port: 6666}, {ip: "103.216.82.37", port: 6666}, {ip: "103.216.82.44", port: 8080}, {ip: "103.216.82.45", port: 6666}, {ip: "103.216.82.50", port: 53281}, {ip: "103.217.124.94", port: 56428}, {ip: "103.217.129.129", port: 35302}, {ip: "103.217.129.250", port: 35302}, {ip: "103.217.154.119", port: 23500}, {ip: "103.218.100.145", port: 8080}, {ip: "103.218.133.248", port: 33888}, {ip: "103.218.134.101", port: 37122}, {ip: "103.219.142.3", port: 46404}, {ip: "103.22.173.230", port: 8080}, {ip: "103.220.224.237", port: 30730}, {ip: "103.220.224.242", port: 30730}, {ip: "103.220.42.163", port: 55714}, {ip: "103.220.42.166", port: 55714}, {ip: "103.224.185.10", port: 49259}, {ip: "103.224.36.49", port: 8080}, {ip: "103.224.37.129", port: 8080}, {ip: "103.224.37.3", port: 83}, {ip: "103.224.38.2", port: 83}, {ip: "103.226.0.30", port: 8080}, {ip: "103.226.142.78", port: 8080}, {ip: "103.226.142.90", port: 41386}, {ip: "103.226.203.41", port: 40099}, {ip: "103.226.241.170", port: 56759}, {ip: "103.226.3.29", port: 8080}, {ip: "103.23.119.59", port: 52584}, {ip: "103.230.152.139", port: 30213}, {ip: "103.232.245.129", port: 42208}, {ip: "103.233.118.38", port: 39747}, {ip: "103.235.155.102", port: 49827}, {ip: "103.236.114.38", port: 49638}, {ip: "103.237.174.82", port: 44071}, {ip: "103.238.109.73", port: 46653}, {ip: "103.238.109.85", port: 45504}, {ip: "103.238.109.86", port: 51827}, {ip: "103.239.146.173", port: 34169}, {ip: "103.240.160.21", port: 6666}, {ip: "103.240.161.107", port: 6666}, {ip: "103.240.161.108", port: 6666}, {ip: "103.240.161.109", port: 6666}, {ip: "103.240.161.59", port: 48809}, {ip: "103.240.168.164", port: 57201}, {ip: "103.240.35.252", port: 53281}, {ip: "103.241.227.108", port: 34974}, {ip: "103.241.227.99", port: 37032}, {ip: "103.242.184.160", port: 37887}, {ip: "103.243.9.134", port: 8080}, {ip: "103.245.1.70", port: 50880}, {ip: "103.245.198.101", port: 8080}, {ip: "103.245.32.116", port: 50833}, {ip: "103.246.224.209", port: 53281}, {ip: "103.249.241.227", port: 8080}, {ip: "103.25.155.189", port: 8080}, {ip: "103.250.148.82", port: 6666}, {ip: "103.250.153.242", port: 35594}, {ip: "103.250.156.22", port: 42203}, {ip: "103.250.166.12", port: 6666}, {ip: "103.250.39.66", port: 34856}, {ip: "103.251.225.16", port: 6666}, {ip: "103.251.58.51", port: 61489}, {ip: "103.252.184.25", port: 53281}, {ip: "103.253.169.115", port: 32731}, {ip: "103.253.211.182", port: 8080}, {ip: "103.253.211.182", port: 80}, {ip: "103.255.234.169", port: 39847}, {ip: "103.255.234.189", port: 45865}, {ip: "103.255.234.81", port: 39847}, {ip: "103.26.54.21", port: 8080}, {ip: "103.26.55.94", port: 8080}, {ip: "103.27.141.10", port: 32708}, {ip: "103.29.221.209", port: 37725}, {ip: "103.36.124.121", port: 50607}, {ip: "103.36.126.226", port: 49820}, {ip: "103.36.49.47", port: 23500}, {ip: "103.38.5.246", port: 53281}, {ip: "103.42.161.118", port: 8080}, {ip: "103.42.162.30", port: 8080}, {ip: "103.42.162.50", port: 8080}, {ip: "103.42.162.58", port: 8080}, {ip: "103.42.248.173", port: 59135}, {ip: "103.43.40.69", port: 8080}, {ip: "103.43.43.88", port: 40986}, {ip: "103.46.233.12", port: 83}, {ip: "103.46.233.13", port: 83}, {ip: "103.46.233.16", port: 83}, {ip: "103.46.233.17", port: 83}, {ip: "103.46.233.19", port: 83}, {ip: "103.46.233.21", port: 83}, {ip: "103.46.233.23", port: 83}, {ip: "103.46.233.29", port: 81}, {ip: "103.46.233.29", port: 83}, {ip: "103.46.233.50", port: 83}, {ip: "103.47.153.87", port: 8080}, {ip: "103.47.175.164", port: 59508}, {ip: "103.47.66.2", port: 39804}, {ip: "103.47.93.22", port: 38130}, {ip: "103.47.94.14", port: 8080}, {ip: "103.48.59.206", port: 8080}, {ip: "103.49.53.1", port: 81}, {ip: "103.50.154.4", port: 35909}, {ip: "103.51.28.134", port: 53281}, {ip: "103.52.220.1", port: 49068}, {ip: "103.53.53.245", port: 41287}, {ip: "103.54.28.226", port: 49415}, {ip: "103.56.228.166", port: 53281}, {ip: "103.56.30.128", port: 8080}, {ip: "103.6.185.147", port: 59353}, {ip: "103.63.24.74", port: 34874}, {ip: "103.65.193.146", port: 51520}, {ip: "103.65.193.17", port: 50862}, {ip: "103.65.195.1", port: 33960}, {ip: "103.65.195.193", port: 33960}, {ip: "103.65.198.94", port: 8080}, {ip: "103.69.217.67", port: 8080}, {ip: "103.69.217.8", port: 57769}, {ip: "103.69.220.14", port: 3128}, {ip: "103.70.128.84", port: 8080}, {ip: "103.70.128.86", port: 8080}, {ip: "103.70.131.74", port: 8080}, {ip: "103.70.144.2", port: 48989}, {ip: "103.70.144.66", port: 8080}, {ip: "103.70.146.250", port: 59563}, {ip: "103.70.147.30", port: 43246}, {ip: "103.72.216.194", port: 38345}, {ip: "103.74.94.71", port: 46226}, {ip: "103.75.161.38", port: 21776}, {ip: "103.75.32.93", port: 40755}, {ip: "103.76.188.52", port: 45939}, {ip: "103.76.188.85", port: 46646}, {ip: "103.76.190.178", port: 36660}, {ip: "103.76.253.155", port: 3128}, {ip: "103.79.228.147", port: 58013}, {ip: "103.79.228.198", port: 56411}, {ip: "103.79.251.2", port: 41382}, {ip: "103.79.251.89", port: 41382}, {ip: "103.80.118.178", port: 43406}, {ip: "103.85.228.9", port: 34228}, {ip: "103.87.104.137", port: 8080}, {ip: "103.87.168.6", port: 30624}, {ip: "103.87.169.191", port: 30839}, {ip: "103.87.25.40", port: 32609}, {ip: "103.87.48.40", port: 44942}, {ip: "103.88.55.150", port: 47968}, {ip: "103.89.253.246", port: 3128}, {ip: "103.89.253.247", port: 3128}, {ip: "103.89.253.249", port: 3128}, {ip: "103.90.156.217", port: 54417}, {ip: "103.90.200.6", port: 48583}, {ip: "103.90.44.137", port: 8080}, {ip: "103.92.117.18", port: 48603}, {ip: "103.93.178.51", port: 35032}, {ip: "103.94.66.183", port: 8080}, {ip: "103.97.85.4", port: 38560}, {ip: "103.99.12.10", port: 54877}, {ip: "106.51.237.110", port: 8080}, {ip: "106.51.254.169", port: 8080}, {ip: "110.172.168.171", port: 53281}, {ip: "110.172.168.201", port: 53281}, {ip: "110.172.168.244", port: 8080}, {ip: "110.172.172.206", port: 57728}, {ip: "110.172.173.2", port: 8080}, {ip: "110.173.188.138", port: 39798}, {ip: "110.232.248.37", port: 32781}, {ip: "110.232.253.209", port: 48903}, {ip: "110.235.196.85", port: 8888}, {ip: "110.235.198.3", port: 57660}, {ip: "110.235.236.84", port: 53281}, {ip: "111.125.137.119", port: 30297}, {ip: "111.91.120.230", port: 37683}, {ip: "111.93.173.38", port: 42521}, {ip: "112.196.101.154", port: 8080}, {ip: "112.196.101.155", port: 8080}, {ip: "114.30.75.160", port: 56770}, {ip: "114.69.229.161", port: 8080}, {ip: "114.69.232.210", port: 54105}, {ip: "114.79.180.91", port: 23500}, {ip: "115.178.103.97", port: 23500}, {ip: "115.178.96.186", port: 23500}, {ip: "115.178.97.242", port: 23500}, {ip: "115.178.97.31", port: 23500}, {ip: "115.178.99.193", port: 23500}, {ip: "115.178.99.98", port: 23500}, {ip: "116.212.176.168", port: 36825}, {ip: "116.72.230.28", port: 37949}, {ip: "116.74.95.18", port: 21776}, {ip: "117.196.228.109", port: 55121}, {ip: "117.196.230.185", port: 39142}, {ip: "117.196.231.201", port: 37769}, {ip: "117.196.236.189", port: 40990}, {ip: "117.196.236.190", port: 53511}, {ip: "117.196.236.194", port: 40161}, {ip: "117.196.236.216", port: 58750}, {ip: "117.196.236.240", port: 61040}, {ip: "117.196.237.11", port: 48336}, {ip: "117.196.237.204", port: 37490}, {ip: "117.196.237.255", port: 47402}, {ip: "117.196.237.68", port: 36126}, {ip: "117.196.238.100", port: 38640}, {ip: "117.196.238.103", port: 53825}, {ip: "117.196.238.150", port: 34842}, {ip: "117.196.238.158", port: 45737}, {ip: "117.196.238.247", port: 30639}, {ip: "117.197.118.80", port: 33473}, {ip: "117.197.41.176", port: 38018}, {ip: "117.211.166.214", port: 3128}, {ip: "117.211.166.216", port: 3128}, {ip: "117.220.171.109", port: 50577}, {ip: "117.220.171.41", port: 45027}, {ip: "117.232.98.206", port: 8080}, {ip: "117.239.152.54", port: 36578}, {ip: "117.240.135.42", port: 52565}, {ip: "117.240.135.82", port: 37044}, {ip: "117.240.151.237", port: 56032}, {ip: "117.240.175.51", port: 3128}, {ip: "117.240.210.155", port: 53281}, {ip: "117.240.59.115", port: 36127}, {ip: "117.241.97.164", port: 35151}, {ip: "117.241.97.5", port: 59329}, {ip: "117.241.99.70", port: 58950}, {ip: "117.242.147.73", port: 53677}, {ip: "117.242.154.73", port: 33889}, {ip: "117.242.36.131", port: 35890}, {ip: "117.244.15.243", port: 3128}, {ip: "117.247.82.227", port: 54904}, {ip: "118.151.209.214", port: 50934}, {ip: "118.185.36.2", port: 52470}, {ip: "118.91.187.193", port: 8080}, {ip: "118.91.190.49", port: 48309}, {ip: "119.235.54.3", port: 8080}, {ip: "119.82.79.179", port: 8080}, {ip: "120.138.117.102", port: 59308}, {ip: "122.102.29.127", port: 23500}, {ip: "122.102.29.99", port: 23500}, {ip: "122.160.72.92", port: 33754}, {ip: "123.108.200.102", port: 82}, {ip: "123.108.200.113", port: 83}, {ip: "123.108.200.185", port: 83}, {ip: "123.108.200.217", port: 82}, {ip: "123.108.201.142", port: 82}, {ip: "123.108.201.197", port: 83}, {ip: "123.176.43.218", port: 40524}, {ip: "123.252.137.238", port: 52584}, {ip: "124.108.17.21", port: 8080}, {ip: "125.17.113.26", port: 8080}, {ip: "125.21.43.82", port: 8080}, {ip: "125.62.192.225", port: 82}, {ip: "125.62.192.33", port: 82}, {ip: "125.62.192.33", port: 84}, {ip: "125.62.194.1", port: 83}, {ip: "125.62.194.193", port: 83}, {ip: "125.62.194.193", port: 84}, {ip: "125.62.197.33", port: 84}, {ip: "125.62.212.1", port: 82}, {ip: "125.62.213.134", port: 82}, {ip: "125.62.213.161", port: 82}, {ip: "125.62.213.18", port: 83}, {ip: "125.62.213.201", port: 84}, {ip: "125.62.213.242", port: 83}, {ip: "125.62.213.49", port: 84}, {ip: "125.62.213.93", port: 82}, {ip: "125.62.214.185", port: 84}, {ip: "13.127.207.231", port: 3128}, {ip: "138.201.106.89", port: 3128}, {ip: "139.5.26.27", port: 53281}, {ip: "139.59.72.14", port: 3128}, {ip: "139.59.76.215", port: 3128}, {ip: "14.102.105.187", port: 44460}, {ip: "14.102.121.136", port: 23500}, {ip: "14.102.127.182", port: 31190}, {ip: "14.102.15.154", port: 45075}, {ip: "14.102.188.140", port: 8080}, {ip: "14.102.189.38", port: 53281}, {ip: "14.102.19.249", port: 39738}, {ip: "14.102.40.66", port: 49729}, {ip: "14.102.40.87", port: 49729}, {ip: "14.102.40.90", port: 49729}, {ip: "14.102.40.92", port: 49729}, {ip: "14.102.67.101", port: 30337}, {ip: "14.141.173.171", port: 55787}, {ip: "14.142.122.134", port: 8080}, {ip: "14.143.30.202", port: 23500}, {ip: "14.143.38.83", port: 48199}, {ip: "14.192.13.122", port: 39371}, {ip: "150.107.243.28", port: 35279}, {ip: "150.107.243.28", port: 8888}, {ip: "150.107.95.66", port: 33261}, {ip: "150.129.114.194", port: 6666}, {ip: "150.129.115.118", port: 8888}, {ip: "150.129.151.62", port: 6666}, {ip: "150.129.170.11", port: 8888}, {ip: "150.129.171.115", port: 6666}, {ip: "150.129.201.30", port: 6666}, {ip: "150.129.52.74", port: 6666}, {ip: "150.129.54.103", port: 23500}, {ip: "150.242.252.66", port: 34293}, {ip: "150.242.253.250", port: 42498}, {ip: "157.119.118.81", port: 38153}, {ip: "157.119.207.13", port: 6666}, {ip: "157.119.207.38", port: 53281}, {ip: "160.202.157.254", port: 8080}, {ip: "163.53.209.9", port: 33701}, {ip: "175.100.144.38", port: 30832}, {ip: "175.100.185.151", port: 53281}, {ip: "175.101.60.54", port: 45109}, {ip: "175.101.60.57", port: 45109}, {ip: "175.101.80.140", port: 8080}, {ip: "175.111.129.119", port: 45660}, {ip: "175.111.129.124", port: 37767}, {ip: "175.111.129.125", port: 44437}, {ip: "180.211.125.110", port: 47390}, {ip: "180.211.97.204", port: 42490}, {ip: "180.233.121.90", port: 43090}, {ip: "182.18.177.114", port: 56173}, {ip: "182.71.0.206", port: 8080}, {ip: "182.73.168.70", port: 57683}, {ip: "182.73.194.170", port: 8080}, {ip: "182.74.85.230", port: 51214}, {ip: "182.75.162.211", port: 8080}, {ip: "182.75.21.30", port: 39342}, {ip: "182.76.208.30", port: 43033}, {ip: "182.77.51.160", port: 8080}, {ip: "183.82.116.56", port: 8080}, {ip: "183.82.32.56", port: 49551}, {ip: "183.83.219.20", port: 58921}, {ip: "183.87.106.126", port: 23500}, {ip: "183.87.14.229", port: 53281}, {ip: "183.87.14.250", port: 44915}, {ip: "195.154.41.145", port: 58673}, {ip: "195.154.41.145", port: 61432}, {ip: "202.134.160.168", port: 8080}, {ip: "202.134.166.1", port: 8080}, {ip: "202.134.180.50", port: 8080}, {ip: "202.61.120.205", port: 52421}, {ip: "202.62.67.209", port: 53281}, {ip: "202.62.68.34", port: 31501}, {ip: "202.62.84.210", port: 53281}, {ip: "202.91.75.195", port: 54119}, {ip: "202.91.81.241", port: 45983}, {ip: "202.91.89.164", port: 35742}, {ip: "203.100.75.133", port: 8888}, {ip: "203.109.86.185", port: 8888}, {ip: "203.110.84.178", port: 33519}, {ip: "203.145.179.170", port: 36001}, {ip: "203.192.193.225", port: 8080}, {ip: "203.192.195.14", port: 31062}, {ip: "203.192.204.23", port: 54149}, {ip: "203.192.217.11", port: 8080}, {ip: "203.192.226.214", port: 53281}, {ip: "203.192.231.17", port: 8080}, {ip: "203.192.231.4", port: 8080}, {ip: "203.192.241.99", port: 38006}, {ip: "203.88.128.1", port: 32854}, {ip: "210.16.77.180", port: 31931}, {ip: "218.248.73.193", port: 808}, {ip: "220.225.138.226", port: 80}, {ip: "223.196.83.182", port: 53281}, {ip: "27.0.180.83", port: 40414}, {ip: "27.116.20.112", port: 46584}, {ip: "27.116.20.169", port: 36630}, {ip: "27.116.20.209", port: 36630}, {ip: "27.116.51.115", port: 8080}, {ip: "27.116.51.21", port: 36033}, {ip: "36.255.157.84", port: 47932}, {ip: "36.255.157.85", port: 55870}, {ip: "43.224.8.107", port: 6666}, {ip: "43.224.8.114", port: 50333}, {ip: "43.224.8.116", port: 6666}, {ip: "43.224.8.121", port: 6666}, {ip: "43.224.8.124", port: 6666}, {ip: "43.224.8.86", port: 6666}, {ip: "43.225.192.126", port: 60246}, {ip: "43.225.192.225", port: 50878}, {ip: "43.225.192.241", port: 50878}, {ip: "43.225.20.73", port: 8080}, {ip: "43.225.23.26", port: 8080}, {ip: "43.226.26.210", port: 8060}, {ip: "43.226.27.233", port: 8060}, {ip: "43.228.220.214", port: 59834}, {ip: "43.228.220.24", port: 50800}, {ip: "43.228.220.247", port: 58294}, {ip: "43.228.221.170", port: 44173}, {ip: "43.228.222.114", port: 56579}, {ip: "43.229.226.218", port: 56644}, {ip: "43.229.73.145", port: 47063}, {ip: "43.229.74.235", port: 23500}, {ip: "43.229.74.96", port: 53281}, {ip: "43.230.196.98", port: 36569}, {ip: "43.231.215.226", port: 35798}, {ip: "43.231.215.231", port: 35798}, {ip: "43.231.215.232", port: 35798}, {ip: "43.231.215.235", port: 35798}, {ip: "43.231.215.237", port: 35798}, {ip: "43.231.215.239", port: 35798}, {ip: "43.231.215.248", port: 35798}, {ip: "43.239.205.114", port: 38723}, {ip: "43.239.205.78", port: 41821}, {ip: "43.239.79.20", port: 3128}, {ip: "43.239.79.36", port: 3128}, {ip: "43.239.79.55", port: 3128}, {ip: "43.239.79.57", port: 44596}, {ip: "43.240.5.113", port: 54430}, {ip: "43.240.5.225", port: 31777}, {ip: "43.241.130.242", port: 8080}, {ip: "43.241.28.248", port: 8080}, {ip: "43.241.28.249", port: 8080}, {ip: "43.241.29.245", port: 8080}, {ip: "43.242.209.201", port: 8080}, {ip: "43.246.139.82", port: 8080}, {ip: "43.246.140.43", port: 53542}, {ip: "43.248.73.86", port: 53281}, {ip: "43.250.252.167", port: 43714}, {ip: "43.250.252.190", port: 33145}, {ip: "43.251.170.145", port: 54059}, {ip: "43.252.199.201", port: 54760}, {ip: "45.112.56.198", port: 48994}, {ip: "45.112.56.2", port: 55244}, {ip: "45.112.57.110", port: 46146}, {ip: "45.112.57.230", port: 61222}, {ip: "45.113.66.65", port: 52567}, {ip: "45.114.194.44", port: 45714}, {ip: "45.114.68.159", port: 34495}, {ip: "45.115.171.228", port: 39745}, {ip: "45.115.171.30", port: 47949}, {ip: "45.115.253.22", port: 47610}, {ip: "45.115.55.100", port: 8080}, {ip: "45.117.74.122", port: 53281}, {ip: "45.117.75.38", port: 8080}, {ip: "45.118.166.163", port: 41678}, {ip: "45.118.166.170", port: 53281}, {ip: "45.118.205.57", port: 23500}, {ip: "45.119.88.109", port: 39946}, {ip: "45.119.88.124", port: 55695}, {ip: "45.121.29.254", port: 54858}, {ip: "45.122.46.36", port: 32123}, {ip: "45.123.26.146", port: 53281}, {ip: "45.125.61.193", port: 32804}, {ip: "45.125.61.209", port: 32804}, {ip: "45.127.121.194", port: 53281}, {ip: "45.249.169.139", port: 8080}, {ip: "45.250.226.14", port: 3128}, {ip: "45.250.226.32", port: 31583}, {ip: "45.250.226.38", port: 8080}, {ip: "45.250.226.47", port: 8080}, {ip: "45.250.226.53", port: 8080}, {ip: "45.250.226.55", port: 8080}, {ip: "45.64.156.60", port: 8888}, {ip: "45.64.178.137", port: 23500}, {ip: "45.64.179.126", port: 53281}, {ip: "45.64.213.114", port: 54709}, {ip: "49.248.108.59", port: 57096}, {ip: "49.248.111.204", port: 8080}, {ip: "49.249.251.86", port: 53281}, {ip: "51.255.58.83", port: 8080}, {ip: "52.172.131.134", port: 3128}, {ip: "52.172.131.191", port: 3128}, {ip: "52.172.131.20", port: 3128}, {ip: "52.172.131.77", port: 3128}, {ip: "52.172.140.57", port: 3128}, {ip: "58.84.15.222", port: 53281}, {ip: "59.91.121.113", port: 31621}, {ip: "59.91.122.1", port: 54086}, {ip: "59.91.127.29", port: 53844}, {ip: "59.97.236.239", port: 50357}, {ip: "60.254.51.36", port: 37395}, {ip: "61.14.229.42", port: 8080}], - "CN" => [{ip: "101.132.122.230", port: 3128}, {ip: "111.230.183.90", port: 8000}, {ip: "112.115.57.20", port: 3128}, {ip: "112.27.167.74", port: 33641}, {ip: "116.192.171.51", port: 61885}, {ip: "117.131.88.30", port: 3128}, {ip: "117.187.18.136", port: 3128}, {ip: "117.35.51.77", port: 53281}, {ip: "118.24.147.205", port: 3128}, {ip: "119.254.94.95", port: 56942}, {ip: "119.27.177.169", port: 80}, {ip: "120.194.42.157", port: 38185}, {ip: "120.92.22.253", port: 3128}, {ip: "120.92.74.189", port: 3128}, {ip: "120.92.74.237", port: 3128}, {ip: "123.56.103.169", port: 3128}, {ip: "124.237.83.14", port: 53281}, {ip: "14.204.20.95", port: 8080}, {ip: "140.143.96.216", port: 80}, {ip: "140.207.50.246", port: 32883}, {ip: "171.221.239.11", port: 808}, {ip: "182.61.170.45", port: 3128}, {ip: "183.15.172.23", port: 53956}, {ip: "183.234.47.19", port: 39079}, {ip: "202.112.237.102", port: 3128}, {ip: "202.116.162.35", port: 8008}, {ip: "203.130.46.108", port: 9090}, {ip: "203.86.26.9", port: 3128}, {ip: "218.14.115.211", port: 3128}, {ip: "218.60.8.98", port: 3129}, {ip: "219.246.90.204", port: 3128}, {ip: "221.214.167.3", port: 44352}, {ip: "221.6.201.18", port: 9999}, {ip: "221.7.255.167", port: 8080}, {ip: "221.7.255.167", port: 80}, {ip: "221.7.255.168", port: 8080}, {ip: "221.7.255.168", port: 80}, {ip: "27.191.234.69", port: 9999}, {ip: "45.125.32.178", port: 3128}, {ip: "45.125.32.179", port: 3128}, {ip: "47.104.213.220", port: 8080}, {ip: "47.92.98.68", port: 3128}, {ip: "58.62.238.150", port: 45893}, {ip: "60.216.101.46", port: 32868}, {ip: "60.255.186.169", port: 8888}, {ip: "61.138.33.20", port: 808}], - "RU" => [{ip: "109.106.137.56", port: 30326}, {ip: "109.106.138.123", port: 60573}, {ip: "109.106.139.225", port: 45689}, {ip: "109.110.42.210", port: 41258}, {ip: "109.110.55.230", port: 21776}, {ip: "109.111.186.87", port: 61906}, {ip: "109.126.8.82", port: 60684}, {ip: "109.161.48.228", port: 53281}, {ip: "109.163.222.189", port: 39094}, {ip: "109.167.133.36", port: 49973}, {ip: "109.167.134.253", port: 30710}, {ip: "109.167.200.226", port: 51744}, {ip: "109.167.201.210", port: 35159}, {ip: "109.167.207.180", port: 38210}, {ip: "109.167.207.72", port: 8080}, {ip: "109.167.224.198", port: 51919}, {ip: "109.167.250.8", port: 46610}, {ip: "109.170.45.131", port: 54947}, {ip: "109.172.57.250", port: 23500}, {ip: "109.173.100.172", port: 53281}, {ip: "109.188.114.218", port: 34529}, {ip: "109.188.64.248", port: 47893}, {ip: "109.194.1.203", port: 8080}, {ip: "109.194.175.165", port: 61872}, {ip: "109.194.2.126", port: 61822}, {ip: "109.194.27.105", port: 23500}, {ip: "109.194.54.32", port: 8080}, {ip: "109.194.54.32", port: 80}, {ip: "109.194.78.93", port: 8080}, {ip: "109.195.150.128", port: 37564}, {ip: "109.195.177.144", port: 61507}, {ip: "109.195.189.172", port: 48642}, {ip: "109.195.36.195", port: 3128}, {ip: "109.195.53.135", port: 8080}, {ip: "109.195.67.106", port: 8080}, {ip: "109.195.71.118", port: 8080}, {ip: "109.197.151.118", port: 8080}, {ip: "109.197.159.190", port: 54345}, {ip: "109.201.96.171", port: 31773}, {ip: "109.201.97.204", port: 41258}, {ip: "109.201.97.235", port: 39125}, {ip: "109.202.45.72", port: 8080}, {ip: "109.206.140.74", port: 45991}, {ip: "109.206.148.31", port: 30797}, {ip: "109.225.41.174", port: 47234}, {ip: "109.227.202.17", port: 35790}, {ip: "109.235.211.154", port: 58856}, {ip: "109.236.211.171", port: 59449}, {ip: "109.236.211.186", port: 36853}, {ip: "109.236.211.242", port: 45800}, {ip: "109.236.71.42", port: 40164}, {ip: "109.248.218.241", port: 41258}, {ip: "109.248.62.207", port: 48089}, {ip: "109.60.136.138", port: 57941}, {ip: "109.60.138.223", port: 53281}, {ip: "109.60.154.31", port: 50727}, {ip: "109.63.200.4", port: 40764}, {ip: "109.68.187.22", port: 3128}, {ip: "109.69.75.5", port: 46347}, {ip: "109.71.181.170", port: 53983}, {ip: "109.73.14.214", port: 34857}, {ip: "109.74.114.182", port: 56618}, {ip: "109.74.132.190", port: 42663}, {ip: "109.74.142.138", port: 53281}, {ip: "109.74.143.222", port: 35029}, {ip: "109.74.143.45", port: 36529}, {ip: "109.75.140.158", port: 59916}, {ip: "109.95.84.114", port: 52125}, {ip: "128.0.30.33", port: 35957}, {ip: "128.68.187.151", port: 32231}, {ip: "128.69.194.68", port: 33411}, {ip: "128.74.175.248", port: 57178}, {ip: "130.255.12.24", port: 31004}, {ip: "134.0.106.61", port: 40352}, {ip: "134.19.147.72", port: 44812}, {ip: "134.90.181.7", port: 54353}, {ip: "141.101.253.108", port: 31369}, {ip: "145.255.137.20", port: 8087}, {ip: "145.255.28.2", port: 55923}, {ip: "145.255.28.4", port: 46239}, {ip: "145.255.6.171", port: 31252}, {ip: "146.120.111.39", port: 37327}, {ip: "146.120.176.17", port: 34635}, {ip: "146.120.2.165", port: 33288}, {ip: "146.120.2.31", port: 58613}, {ip: "146.120.227.3", port: 8080}, {ip: "146.120.3.214", port: 32476}, {ip: "146.120.4.2", port: 35237}, {ip: "146.120.70.176", port: 45722}, {ip: "146.158.1.63", port: 53281}, {ip: "149.255.112.194", port: 48968}, {ip: "149.255.24.39", port: 53256}, {ip: "149.255.3.132", port: 57264}, {ip: "158.255.51.213", port: 48379}, {ip: "158.46.127.222", port: 52574}, {ip: "158.46.248.38", port: 32231}, {ip: "158.46.255.118", port: 46175}, {ip: "158.46.255.162", port: 44410}, {ip: "158.46.43.137", port: 48236}, {ip: "158.46.43.144", port: 39120}, {ip: "158.58.130.185", port: 50016}, {ip: "158.58.130.222", port: 53281}, {ip: "158.58.131.219", port: 51531}, {ip: "158.58.131.27", port: 43733}, {ip: "158.58.131.9", port: 59167}, {ip: "158.58.132.12", port: 56962}, {ip: "158.58.133.106", port: 41258}, {ip: "158.58.133.13", port: 21213}, {ip: "158.58.133.187", port: 34128}, {ip: "158.58.133.41", port: 37239}, {ip: "158.58.133.88", port: 37292}, {ip: "158.58.135.183", port: 31891}, {ip: "176.100.144.83", port: 52876}, {ip: "176.100.76.214", port: 37213}, {ip: "176.101.0.47", port: 34471}, {ip: "176.101.89.226", port: 33470}, {ip: "176.106.12.65", port: 30120}, {ip: "176.107.255.6", port: 35970}, {ip: "176.107.80.110", port: 58901}, {ip: "176.107.80.53", port: 36391}, {ip: "176.110.121.9", port: 46322}, {ip: "176.110.121.90", port: 21776}, {ip: "176.111.10.136", port: 34320}, {ip: "176.111.249.183", port: 34895}, {ip: "176.111.97.18", port: 8080}, {ip: "176.112.106.230", port: 33996}, {ip: "176.112.110.40", port: 61142}, {ip: "176.113.116.70", port: 55589}, {ip: "176.113.116.75", port: 36455}, {ip: "176.113.126.127", port: 34743}, {ip: "176.113.127.11", port: 61813}, {ip: "176.113.27.192", port: 47337}, {ip: "176.114.196.134", port: 56042}, {ip: "176.115.197.118", port: 8080}, {ip: "176.117.216.122", port: 61361}, {ip: "176.117.255.182", port: 53100}, {ip: "176.120.200.69", port: 44331}, {ip: "176.120.202.243", port: 54989}, {ip: "176.120.209.209", port: 41258}, {ip: "176.120.209.86", port: 41258}, {ip: "176.120.214.185", port: 53281}, {ip: "176.121.48.18", port: 36486}, {ip: "176.121.48.48", port: 40619}, {ip: "176.123.129.14", port: 8080}, {ip: "176.124.123.93", port: 41258}, {ip: "176.14.247.73", port: 53281}, {ip: "176.15.164.128", port: 34355}, {ip: "176.192.110.66", port: 55772}, {ip: "176.192.111.174", port: 37209}, {ip: "176.192.124.98", port: 60787}, {ip: "176.192.126.139", port: 58042}, {ip: "176.192.15.116", port: 50755}, {ip: "176.192.15.26", port: 33526}, {ip: "176.192.19.38", port: 38495}, {ip: "176.192.20.146", port: 32231}, {ip: "176.192.33.122", port: 41528}, {ip: "176.192.5.238", port: 61227}, {ip: "176.192.61.226", port: 50875}, {ip: "176.192.62.210", port: 56510}, {ip: "176.192.8.206", port: 39422}, {ip: "176.193.142.10", port: 53281}, {ip: "176.193.15.94", port: 8080}, {ip: "176.193.224.44", port: 42171}, {ip: "176.193.67.174", port: 53281}, {ip: "176.196.195.170", port: 48129}, {ip: "176.196.198.154", port: 35252}, {ip: "176.196.198.202", port: 55903}, {ip: "176.196.225.158", port: 43742}, {ip: "176.196.238.210", port: 60449}, {ip: "176.196.238.234", port: 44648}, {ip: "176.196.239.46", port: 35656}, {ip: "176.196.240.34", port: 43810}, {ip: "176.196.246.6", port: 53281}, {ip: "176.196.254.206", port: 53801}, {ip: "176.196.84.138", port: 51336}, {ip: "176.197.103.198", port: 37492}, {ip: "176.197.142.98", port: 41258}, {ip: "176.197.144.134", port: 44215}, {ip: "176.197.145.246", port: 32649}, {ip: "176.197.190.34", port: 36446}, {ip: "176.197.229.250", port: 8080}, {ip: "176.197.99.142", port: 47278}, {ip: "176.212.114.139", port: 39581}, {ip: "176.212.185.16", port: 31673}, {ip: "176.212.185.19", port: 33373}, {ip: "176.213.142.220", port: 35658}, {ip: "176.214.80.153", port: 8080}, {ip: "176.215.1.108", port: 60339}, {ip: "176.215.170.147", port: 35604}, {ip: "176.215.189.68", port: 30631}, {ip: "176.215.191.244", port: 35481}, {ip: "176.215.197.128", port: 51011}, {ip: "176.215.197.50", port: 41885}, {ip: "176.215.252.139", port: 37202}, {ip: "176.215.252.2", port: 54886}, {ip: "176.221.10.249", port: 42583}, {ip: "176.227.188.66", port: 53281}, {ip: "176.56.23.14", port: 35340}, {ip: "176.62.180.228", port: 44551}, {ip: "176.62.185.54", port: 53883}, {ip: "176.62.185.72", port: 40358}, {ip: "176.62.188.152", port: 59645}, {ip: "176.74.13.110", port: 8080}, {ip: "176.99.140.94", port: 47838}, {ip: "178.130.29.226", port: 53295}, {ip: "178.140.116.185", port: 50376}, {ip: "178.140.8.221", port: 41452}, {ip: "178.140.95.77", port: 23500}, {ip: "178.155.8.48", port: 41358}, {ip: "178.161.150.46", port: 31765}, {ip: "178.161.164.90", port: 42704}, {ip: "178.161.192.170", port: 3128}, {ip: "178.170.254.178", port: 46788}, {ip: "178.19.247.25", port: 51480}, {ip: "178.205.106.11", port: 39137}, {ip: "178.207.10.226", port: 54628}, {ip: "178.207.153.46", port: 52814}, {ip: "178.208.146.236", port: 47888}, {ip: "178.213.13.136", port: 53281}, {ip: "178.213.225.33", port: 43690}, {ip: "178.215.145.106", port: 58381}, {ip: "178.215.146.120", port: 8080}, {ip: "178.217.69.7", port: 53281}, {ip: "178.218.104.8", port: 49707}, {ip: "178.219.157.187", port: 43354}, {ip: "178.219.183.163", port: 8080}, {ip: "178.219.183.241", port: 48114}, {ip: "178.219.37.70", port: 8080}, {ip: "178.237.180.34", port: 57307}, {ip: "178.237.187.50", port: 41421}, {ip: "178.238.123.2", port: 41258}, {ip: "178.252.208.62", port: 45957}, {ip: "178.252.70.228", port: 37390}, {ip: "178.252.75.100", port: 33065}, {ip: "178.252.75.80", port: 53281}, {ip: "178.44.113.205", port: 53281}, {ip: "178.46.188.202", port: 39864}, {ip: "178.49.191.133", port: 46088}, {ip: "178.57.101.212", port: 38020}, {ip: "178.57.101.235", port: 31309}, {ip: "178.57.101.83", port: 45015}, {ip: "178.64.190.133", port: 46688}, {ip: "178.75.1.111", port: 50411}, {ip: "178.75.1.132", port: 41144}, {ip: "178.75.27.131", port: 41879}, {ip: "178.75.33.188", port: 59330}, {ip: "185.105.168.37", port: 61431}, {ip: "185.108.160.229", port: 41258}, {ip: "185.108.210.131", port: 47713}, {ip: "185.11.61.64", port: 38813}, {ip: "185.116.202.225", port: 56365}, {ip: "185.118.167.24", port: 3128}, {ip: "185.118.167.98", port: 3128}, {ip: "185.129.57.126", port: 32266}, {ip: "185.13.35.178", port: 40654}, {ip: "185.134.150.160", port: 8080}, {ip: "185.144.30.112", port: 3128}, {ip: "185.144.30.134", port: 3128}, {ip: "185.15.189.67", port: 30215}, {ip: "185.158.112.209", port: 3128}, {ip: "185.17.203.153", port: 52132}, {ip: "185.175.119.137", port: 41258}, {ip: "185.175.119.189", port: 41258}, {ip: "185.18.111.194", port: 41258}, {ip: "185.189.252.121", port: 45222}, {ip: "185.189.253.21", port: 56630}, {ip: "185.19.176.237", port: 53281}, {ip: "185.190.40.115", port: 31747}, {ip: "185.2.88.150", port: 36798}, {ip: "185.2.88.202", port: 44878}, {ip: "185.204.2.27", port: 60168}, {ip: "185.216.195.134", port: 61287}, {ip: "185.22.172.94", port: 10010}, {ip: "185.22.172.94", port: 1448}, {ip: "185.22.174.65", port: 10010}, {ip: "185.22.174.65", port: 1448}, {ip: "185.23.64.100", port: 3130}, {ip: "185.23.82.39", port: 59248}, {ip: "185.233.94.105", port: 59288}, {ip: "185.233.94.146", port: 57736}, {ip: "185.251.241.40", port: 51689}, {ip: "185.3.68.54", port: 53500}, {ip: "185.31.160.183", port: 8080}, {ip: "185.31.162.152", port: 8080}, {ip: "185.31.162.235", port: 8080}, {ip: "185.31.162.27", port: 8080}, {ip: "185.31.163.21", port: 35786}, {ip: "185.32.120.177", port: 60724}, {ip: "185.34.20.164", port: 53700}, {ip: "185.34.20.170", port: 49116}, {ip: "185.34.23.43", port: 63238}, {ip: "185.34.23.78", port: 35214}, {ip: "185.46.14.138", port: 46171}, {ip: "185.46.16.31", port: 61400}, {ip: "185.51.124.118", port: 51736}, {ip: "185.51.60.141", port: 39935}, {ip: "185.54.178.185", port: 8080}, {ip: "185.55.0.254", port: 36671}, {ip: "185.61.92.228", port: 33060}, {ip: "185.61.93.67", port: 49107}, {ip: "185.64.231.250", port: 32231}, {ip: "185.7.233.66", port: 53504}, {ip: "185.72.225.10", port: 56285}, {ip: "185.75.5.158", port: 60819}, {ip: "185.85.219.74", port: 61068}, {ip: "185.9.86.186", port: 39345}, {ip: "185.91.252.17", port: 53133}, {ip: "188.0.190.75", port: 59378}, {ip: "188.0.20.45", port: 53281}, {ip: "188.0.27.8", port: 8854}, {ip: "188.126.44.193", port: 41211}, {ip: "188.126.62.225", port: 41258}, {ip: "188.127.233.134", port: 60077}, {ip: "188.133.136.10", port: 47113}, {ip: "188.133.176.58", port: 8080}, {ip: "188.134.8.187", port: 54837}, {ip: "188.134.92.52", port: 39041}, {ip: "188.162.235.236", port: 40129}, {ip: "188.168.138.154", port: 31501}, {ip: "188.168.27.132", port: 59041}, {ip: "188.168.28.163", port: 37409}, {ip: "188.168.58.130", port: 40917}, {ip: "188.168.75.254", port: 56899}, {ip: "188.17.152.172", port: 55820}, {ip: "188.17.156.26", port: 30773}, {ip: "188.170.117.86", port: 60736}, {ip: "188.170.233.150", port: 60380}, {ip: "188.170.41.6", port: 60332}, {ip: "188.18.52.137", port: 8080}, {ip: "188.186.180.193", port: 45973}, {ip: "188.186.181.155", port: 30567}, {ip: "188.186.181.187", port: 38576}, {ip: "188.186.186.146", port: 55248}, {ip: "188.187.1.41", port: 50030}, {ip: "188.187.189.142", port: 38264}, {ip: "188.187.62.10", port: 30791}, {ip: "188.227.49.101", port: 50536}, {ip: "188.234.151.103", port: 8080}, {ip: "188.234.240.190", port: 34242}, {ip: "188.235.11.88", port: 57143}, {ip: "188.235.130.187", port: 58196}, {ip: "188.235.137.196", port: 23500}, {ip: "188.235.148.209", port: 30554}, {ip: "188.235.8.5", port: 33746}, {ip: "188.242.123.119", port: 46801}, {ip: "188.242.249.116", port: 8080}, {ip: "188.242.7.209", port: 45662}, {ip: "188.244.175.2", port: 8080}, {ip: "188.244.208.201", port: 50021}, {ip: "188.255.82.136", port: 53281}, {ip: "188.32.112.178", port: 40844}, {ip: "188.32.2.213", port: 45596}, {ip: "188.32.79.228", port: 44687}, {ip: "188.35.167.7", port: 45619}, {ip: "188.43.17.205", port: 31925}, {ip: "188.43.39.81", port: 36004}, {ip: "188.43.4.117", port: 60577}, {ip: "188.43.52.219", port: 53469}, {ip: "188.65.131.170", port: 41665}, {ip: "188.68.105.88", port: 42058}, {ip: "188.68.95.166", port: 41258}, {ip: "188.92.106.214", port: 3128}, {ip: "188.92.242.180", port: 52048}, {ip: "188.93.242.213", port: 49774}, {ip: "192.124.176.77", port: 40654}, {ip: "192.162.193.243", port: 36910}, {ip: "192.162.214.11", port: 41258}, {ip: "193.105.107.131", port: 38977}, {ip: "193.106.170.133", port: 38591}, {ip: "193.106.68.146", port: 55821}, {ip: "193.107.228.222", port: 57418}, {ip: "193.150.107.150", port: 38521}, {ip: "193.150.117.31", port: 8000}, {ip: "193.151.196.58", port: 51225}, {ip: "193.169.1.171", port: 44258}, {ip: "193.169.97.125", port: 50030}, {ip: "193.189.89.144", port: 36837}, {ip: "193.232.113.244", port: 40412}, {ip: "193.232.234.130", port: 61932}, {ip: "193.233.9.167", port: 52436}, {ip: "193.242.177.105", port: 53281}, {ip: "193.242.178.254", port: 33633}, {ip: "193.242.178.50", port: 52376}, {ip: "193.242.178.90", port: 8080}, {ip: "193.33.100.110", port: 55305}, {ip: "193.33.101.152", port: 34611}, {ip: "193.33.166.16", port: 48052}, {ip: "193.33.233.154", port: 3128}, {ip: "193.41.79.210", port: 8080}, {ip: "193.9.244.198", port: 43177}, {ip: "194.114.128.149", port: 61213}, {ip: "194.126.203.100", port: 31604}, {ip: "194.135.109.118", port: 43857}, {ip: "194.135.15.146", port: 59328}, {ip: "194.135.216.178", port: 56805}, {ip: "194.135.238.190", port: 49476}, {ip: "194.135.75.74", port: 41258}, {ip: "194.146.201.67", port: 53281}, {ip: "194.186.162.254", port: 41282}, {ip: "194.186.163.246", port: 59671}, {ip: "194.186.18.46", port: 56408}, {ip: "194.186.20.62", port: 21231}, {ip: "194.186.234.162", port: 44159}, {ip: "194.186.240.5", port: 44720}, {ip: "194.190.105.252", port: 39334}, {ip: "194.190.170.204", port: 49251}, {ip: "194.190.171.214", port: 43960}, {ip: "194.190.28.254", port: 46627}, {ip: "194.190.31.142", port: 51898}, {ip: "194.58.69.87", port: 3128}, {ip: "194.8.136.41", port: 45171}, {ip: "194.85.138.70", port: 49020}, {ip: "194.87.148.156", port: 61527}, {ip: "194.9.27.82", port: 42720}, {ip: "195.122.232.179", port: 8080}, {ip: "195.122.236.246", port: 8080}, {ip: "195.133.232.58", port: 41733}, {ip: "195.135.212.186", port: 38852}, {ip: "195.14.114.116", port: 59530}, {ip: "195.14.114.24", port: 56897}, {ip: "195.144.219.155", port: 54245}, {ip: "195.154.41.145", port: 40184}, {ip: "195.154.41.145", port: 41257}, {ip: "195.154.41.145", port: 46469}, {ip: "195.158.250.97", port: 41582}, {ip: "195.16.48.142", port: 36083}, {ip: "195.191.183.169", port: 47238}, {ip: "195.206.255.17", port: 55560}, {ip: "195.206.34.238", port: 31499}, {ip: "195.206.42.190", port: 31753}, {ip: "195.206.42.99", port: 32570}, {ip: "195.206.45.112", port: 53281}, {ip: "195.208.11.66", port: 8080}, {ip: "195.208.132.214", port: 53281}, {ip: "195.208.15.22", port: 8080}, {ip: "195.208.166.10", port: 8080}, {ip: "195.208.172.70", port: 8080}, {ip: "195.208.36.25", port: 53281}, {ip: "195.208.45.218", port: 43655}, {ip: "195.209.141.67", port: 31927}, {ip: "195.209.176.2", port: 8080}, {ip: "195.210.144.166", port: 30088}, {ip: "195.211.160.88", port: 44464}, {ip: "195.211.197.125", port: 8000}, {ip: "195.211.204.84", port: 31354}, {ip: "195.218.144.150", port: 41258}, {ip: "195.218.144.182", port: 31705}, {ip: "195.218.173.242", port: 45919}, {ip: "195.239.161.222", port: 50712}, {ip: "195.239.178.110", port: 32004}, {ip: "195.3.141.8", port: 21231}, {ip: "195.34.15.98", port: 34161}, {ip: "195.42.181.243", port: 53281}, {ip: "195.46.168.147", port: 8080}, {ip: "195.46.187.240", port: 39301}, {ip: "195.54.41.186", port: 42776}, {ip: "195.64.223.116", port: 3128}, {ip: "195.68.150.46", port: 21213}, {ip: "195.69.217.15", port: 8080}, {ip: "195.9.102.154", port: 58251}, {ip: "195.9.112.102", port: 35756}, {ip: "195.9.165.229", port: 50173}, {ip: "195.9.168.178", port: 38741}, {ip: "195.9.188.78", port: 53281}, {ip: "195.9.209.10", port: 35242}, {ip: "195.9.217.70", port: 44228}, {ip: "195.9.223.246", port: 52098}, {ip: "195.9.237.38", port: 8080}, {ip: "195.9.237.66", port: 8080}, {ip: "195.9.7.110", port: 54599}, {ip: "195.9.91.66", port: 33199}, {ip: "195.9.99.66", port: 57280}, {ip: "195.91.132.20", port: 19600}, {ip: "195.91.200.141", port: 49152}, {ip: "195.91.200.216", port: 8080}, {ip: "195.91.253.147", port: 61533}, {ip: "195.98.183.82", port: 30953}, {ip: "195.98.189.242", port: 57028}, {ip: "195.98.74.141", port: 38903}, {ip: "2.92.242.230", port: 40328}, {ip: "2.92.244.193", port: 57877}, {ip: "212.104.82.246", port: 36495}, {ip: "212.107.238.13", port: 40430}, {ip: "212.119.229.18", port: 33852}, {ip: "212.13.103.54", port: 45536}, {ip: "212.13.97.122", port: 30466}, {ip: "212.19.21.19", port: 53264}, {ip: "212.19.21.63", port: 51823}, {ip: "212.19.5.157", port: 58442}, {ip: "212.19.8.135", port: 60056}, {ip: "212.19.8.223", port: 30281}, {ip: "212.19.8.239", port: 55602}, {ip: "212.192.202.207", port: 4550}, {ip: "212.22.80.224", port: 34822}, {ip: "212.23.88.243", port: 48397}, {ip: "212.24.45.194", port: 41258}, {ip: "212.26.247.178", port: 38418}, {ip: "212.3.152.143", port: 8080}, {ip: "212.3.152.143", port: 80}, {ip: "212.3.156.65", port: 54425}, {ip: "212.32.202.174", port: 47358}, {ip: "212.33.228.161", port: 37971}, {ip: "212.33.243.83", port: 38605}, {ip: "212.34.53.126", port: 44369}, {ip: "212.44.153.254", port: 56401}, {ip: "212.5.107.81", port: 56481}, {ip: "212.55.100.204", port: 53886}, {ip: "212.7.230.7", port: 51405}, {ip: "212.74.213.86", port: 46020}, {ip: "212.75.202.74", port: 54619}, {ip: "212.75.215.70", port: 32351}, {ip: "212.77.130.65", port: 30493}, {ip: "212.77.138.161", port: 41258}, {ip: "213.108.221.201", port: 32800}, {ip: "213.109.5.230", port: 33138}, {ip: "213.109.6.85", port: 31759}, {ip: "213.109.7.135", port: 59918}, {ip: "213.128.9.204", port: 35549}, {ip: "213.134.196.12", port: 38723}, {ip: "213.135.146.225", port: 40732}, {ip: "213.135.78.146", port: 50993}, {ip: "213.135.78.33", port: 50993}, {ip: "213.142.197.198", port: 46385}, {ip: "213.148.167.32", port: 40881}, {ip: "213.168.37.86", port: 8080}, {ip: "213.170.101.102", port: 53151}, {ip: "213.171.42.186", port: 3128}, {ip: "213.187.118.184", port: 53281}, {ip: "213.21.23.98", port: 4550}, {ip: "213.21.23.98", port: 53281}, {ip: "213.21.53.132", port: 58960}, {ip: "213.210.67.166", port: 53281}, {ip: "213.219.232.106", port: 41100}, {ip: "213.222.234.196", port: 8080}, {ip: "213.222.244.150", port: 53611}, {ip: "213.234.0.242", port: 56503}, {ip: "213.234.24.150", port: 32688}, {ip: "213.242.254.141", port: 46869}, {ip: "213.247.192.131", port: 41258}, {ip: "213.251.226.208", port: 56900}, {ip: "213.251.243.12", port: 21231}, {ip: "213.251.243.98", port: 46346}, {ip: "213.33.155.80", port: 44387}, {ip: "213.33.199.194", port: 36411}, {ip: "213.33.224.82", port: 8080}, {ip: "213.59.146.220", port: 49774}, {ip: "213.59.153.19", port: 53281}, {ip: "213.59.156.249", port: 44528}, {ip: "213.59.195.6", port: 8080}, {ip: "213.59.206.34", port: 58439}, {ip: "213.80.165.26", port: 31532}, {ip: "213.87.42.114", port: 46785}, {ip: "213.87.42.16", port: 56822}, {ip: "213.87.42.46", port: 38431}, {ip: "213.87.42.49", port: 33980}, {ip: "217.10.45.103", port: 8080}, {ip: "217.10.45.103", port: 8081}, {ip: "217.107.193.32", port: 50483}, {ip: "217.107.197.39", port: 33628}, {ip: "217.116.155.74", port: 8080}, {ip: "217.116.60.66", port: 21231}, {ip: "217.119.18.138", port: 40830}, {ip: "217.12.246.238", port: 58902}, {ip: "217.13.219.168", port: 43596}, {ip: "217.15.195.141", port: 59811}, {ip: "217.15.49.195", port: 58906}, {ip: "217.150.77.31", port: 53281}, {ip: "217.18.139.18", port: 41401}, {ip: "217.195.219.174", port: 42646}, {ip: "217.195.87.58", port: 41258}, {ip: "217.197.120.134", port: 44039}, {ip: "217.197.239.54", port: 34463}, {ip: "217.197.240.87", port: 41560}, {ip: "217.21.220.157", port: 8081}, {ip: "217.23.74.29", port: 37789}, {ip: "217.23.74.42", port: 58843}, {ip: "217.24.185.232", port: 54058}, {ip: "217.24.189.131", port: 57005}, {ip: "217.25.221.191", port: 56635}, {ip: "217.70.29.45", port: 8080}, {ip: "217.74.161.42", port: 34175}, {ip: "217.74.163.38", port: 54496}, {ip: "217.76.185.31", port: 57879}, {ip: "217.76.47.29", port: 43483}, {ip: "217.79.3.94", port: 8080}, {ip: "217.8.84.76", port: 46378}, {ip: "222.74.61.98", port: 53281}, {ip: "31.10.4.138", port: 50022}, {ip: "31.13.147.248", port: 46733}, {ip: "31.13.22.142", port: 40100}, {ip: "31.130.91.37", port: 30517}, {ip: "31.131.191.250", port: 41258}, {ip: "31.131.67.14", port: 8080}, {ip: "31.132.127.142", port: 35432}, {ip: "31.132.218.252", port: 32423}, {ip: "31.132.236.42", port: 33063}, {ip: "31.132.96.74", port: 50740}, {ip: "31.132.97.154", port: 61751}, {ip: "31.133.120.5", port: 41995}, {ip: "31.135.241.124", port: 47531}, {ip: "31.135.93.56", port: 44044}, {ip: "31.148.122.86", port: 44789}, {ip: "31.148.32.183", port: 51166}, {ip: "31.148.48.151", port: 41917}, {ip: "31.148.71.35", port: 50897}, {ip: "31.15.89.69", port: 36379}, {ip: "31.173.17.118", port: 51317}, {ip: "31.173.209.6", port: 47995}, {ip: "31.173.211.114", port: 32231}, {ip: "31.173.68.6", port: 41258}, {ip: "31.173.90.110", port: 8080}, {ip: "31.193.124.70", port: 53281}, {ip: "31.200.195.147", port: 43592}, {ip: "31.200.228.169", port: 37293}, {ip: "31.207.195.244", port: 80}, {ip: "31.210.209.59", port: 8080}, {ip: "31.210.211.147", port: 8080}, {ip: "31.210.218.228", port: 57971}, {ip: "31.220.183.217", port: 53281}, {ip: "31.28.0.54", port: 42993}, {ip: "31.28.99.25", port: 32429}, {ip: "31.29.212.82", port: 35066}, {ip: "31.42.254.24", port: 30912}, {ip: "31.44.249.31", port: 8080}, {ip: "31.44.90.112", port: 58523}, {ip: "31.47.189.14", port: 38473}, {ip: "35.199.102.178", port: 8118}, {ip: "37.110.148.182", port: 47516}, {ip: "37.110.157.118", port: 41258}, {ip: "37.113.129.98", port: 41665}, {ip: "37.123.222.124", port: 8080}, {ip: "37.131.196.63", port: 55099}, {ip: "37.139.85.66", port: 40777}, {ip: "37.145.118.34", port: 37235}, {ip: "37.145.33.107", port: 31876}, {ip: "37.146.200.88", port: 8080}, {ip: "37.19.1.253", port: 52410}, {ip: "37.192.103.164", port: 34835}, {ip: "37.192.177.93", port: 33314}, {ip: "37.192.194.50", port: 50165}, {ip: "37.192.32.213", port: 36344}, {ip: "37.192.99.151", port: 51417}, {ip: "37.193.142.175", port: 33660}, {ip: "37.193.175.138", port: 40059}, {ip: "37.205.83.91", port: 35888}, {ip: "37.233.85.155", port: 53281}, {ip: "37.235.167.66", port: 53281}, {ip: "37.235.64.48", port: 55944}, {ip: "37.235.64.60", port: 46720}, {ip: "37.235.64.63", port: 49904}, {ip: "37.235.65.2", port: 47816}, {ip: "37.235.67.178", port: 34450}, {ip: "37.28.170.69", port: 53281}, {ip: "37.9.134.125", port: 49080}, {ip: "37.9.134.133", port: 41262}, {ip: "46.0.203.186", port: 8080}, {ip: "46.146.197.19", port: 40280}, {ip: "46.146.202.158", port: 59168}, {ip: "46.146.223.235", port: 8080}, {ip: "46.146.244.97", port: 44327}, {ip: "46.147.192.133", port: 39692}, {ip: "46.148.202.86", port: 32231}, {ip: "46.148.62.89", port: 34115}, {ip: "46.149.73.148", port: 45024}, {ip: "46.150.174.90", port: 53281}, {ip: "46.151.10.69", port: 8080}, {ip: "46.151.156.198", port: 56013}, {ip: "46.151.157.115", port: 50893}, {ip: "46.16.226.10", port: 8080}, {ip: "46.163.131.55", port: 48306}, {ip: "46.173.191.51", port: 53281}, {ip: "46.174.10.158", port: 37828}, {ip: "46.174.222.61", port: 34977}, {ip: "46.180.96.79", port: 42319}, {ip: "46.181.151.79", port: 39386}, {ip: "46.182.131.240", port: 51556}, {ip: "46.182.133.230", port: 52494}, {ip: "46.188.59.22", port: 59705}, {ip: "46.188.82.57", port: 41237}, {ip: "46.21.72.68", port: 8080}, {ip: "46.21.74.130", port: 8080}, {ip: "46.21.74.226", port: 55845}, {ip: "46.22.48.61", port: 38049}, {ip: "46.227.162.128", port: 51419}, {ip: "46.227.162.98", port: 51558}, {ip: "46.229.187.169", port: 53281}, {ip: "46.229.67.198", port: 47437}, {ip: "46.241.120.230", port: 51178}, {ip: "46.243.179.221", port: 41598}, {ip: "46.254.217.54", port: 53281}, {ip: "46.254.217.67", port: 34393}, {ip: "46.254.24.214", port: 41056}, {ip: "46.254.240.106", port: 8080}, {ip: "46.28.228.210", port: 36543}, {ip: "46.29.12.231", port: 53281}, {ip: "46.29.8.194", port: 53281}, {ip: "46.32.68.188", port: 39707}, {ip: "46.39.224.112", port: 36765}, {ip: "46.39.224.208", port: 32154}, {ip: "46.39.238.50", port: 54795}, {ip: "46.46.32.82", port: 51225}, {ip: "46.47.246.82", port: 35587}, {ip: "46.52.213.194", port: 39673}, {ip: "46.52.232.183", port: 31545}, {ip: "46.63.162.171", port: 8080}, {ip: "46.72.179.146", port: 45533}, {ip: "46.73.33.253", port: 8080}, {ip: "5.100.120.176", port: 31117}, {ip: "5.128.199.11", port: 35478}, {ip: "5.128.32.12", port: 51959}, {ip: "5.129.155.3", port: 51390}, {ip: "5.129.16.27", port: 48935}, {ip: "5.129.208.115", port: 42254}, {ip: "5.129.61.30", port: 60760}, {ip: "5.130.73.28", port: 33582}, {ip: "5.134.217.58", port: 45915}, {ip: "5.140.212.175", port: 22129}, {ip: "5.140.233.145", port: 47071}, {ip: "5.140.233.194", port: 59122}, {ip: "5.141.80.131", port: 8080}, {ip: "5.141.81.65", port: 61853}, {ip: "5.16.11.190", port: 8080}, {ip: "5.16.15.234", port: 8080}, {ip: "5.166.56.60", port: 34445}, {ip: "5.167.51.235", port: 8080}, {ip: "5.167.53.223", port: 36355}, {ip: "5.167.54.233", port: 31069}, {ip: "5.167.96.238", port: 3128}, {ip: "5.17.171.222", port: 40168}, {ip: "5.189.196.249", port: 42794}, {ip: "5.189.241.22", port: 44161}, {ip: "5.19.137.242", port: 44934}, {ip: "5.19.142.82", port: 57506}, {ip: "5.19.165.235", port: 30793}, {ip: "5.19.4.41", port: 56058}, {ip: "5.228.211.189", port: 49981}, {ip: "5.23.102.194", port: 52803}, {ip: "5.35.93.157", port: 31773}, {ip: "5.39.165.4", port: 53926}, {ip: "5.59.137.90", port: 34206}, {ip: "5.59.137.90", port: 8888}, {ip: "5.59.142.64", port: 59151}, {ip: "5.59.55.50", port: 31935}, {ip: "5.8.203.152", port: 48505}, {ip: "5.8.207.160", port: 57192}, {ip: "5.8.209.195", port: 34131}, {ip: "62.106.122.92", port: 53544}, {ip: "62.117.92.180", port: 4550}, {ip: "62.117.92.180", port: 53281}, {ip: "62.122.97.66", port: 59143}, {ip: "62.133.163.254", port: 34447}, {ip: "62.133.171.79", port: 35335}, {ip: "62.140.238.114", port: 30692}, {ip: "62.148.129.89", port: 35912}, {ip: "62.148.151.253", port: 53570}, {ip: "62.152.73.86", port: 42042}, {ip: "62.152.85.158", port: 31156}, {ip: "62.165.54.153", port: 55522}, {ip: "62.173.140.14", port: 8080}, {ip: "62.173.155.206", port: 41258}, {ip: "62.182.206.19", port: 37715}, {ip: "62.213.109.126", port: 56181}, {ip: "62.213.14.166", port: 8080}, {ip: "62.213.87.172", port: 8080}, {ip: "62.76.123.224", port: 8080}, {ip: "77.108.78.22", port: 38564}, {ip: "77.220.209.15", port: 53281}, {ip: "77.221.198.190", port: 8080}, {ip: "77.221.220.133", port: 44331}, {ip: "77.232.137.35", port: 59578}, {ip: "77.232.153.248", port: 60950}, {ip: "77.232.166.101", port: 49790}, {ip: "77.233.10.37", port: 54210}, {ip: "77.236.247.109", port: 8080}, {ip: "77.238.129.15", port: 8080}, {ip: "77.244.27.109", port: 47554}, {ip: "77.247.209.222", port: 43410}, {ip: "77.37.142.203", port: 53281}, {ip: "77.37.192.63", port: 46677}, {ip: "77.37.192.65", port: 52187}, {ip: "77.39.29.29", port: 49243}, {ip: "77.41.132.43", port: 41258}, {ip: "77.50.106.161", port: 8080}, {ip: "77.51.210.247", port: 8080}, {ip: "77.75.6.34", port: 8080}, {ip: "77.87.102.7", port: 42601}, {ip: "77.94.107.148", port: 30609}, {ip: "77.94.121.212", port: 36896}, {ip: "77.94.121.51", port: 45293}, {ip: "77.94.122.19", port: 40856}, {ip: "77.95.95.166", port: 36368}, {ip: "78.107.7.8", port: 32572}, {ip: "78.109.47.7", port: 8080}, {ip: "78.110.154.177", port: 59888}, {ip: "78.111.249.137", port: 55081}, {ip: "78.140.201.226", port: 8090}, {ip: "78.140.6.68", port: 53281}, {ip: "78.140.7.239", port: 48647}, {ip: "78.153.4.122", port: 9001}, {ip: "78.155.172.4", port: 44052}, {ip: "78.156.225.170", port: 41258}, {ip: "78.156.243.146", port: 59730}, {ip: "78.29.14.201", port: 39001}, {ip: "78.36.194.84", port: 8080}, {ip: "78.36.203.200", port: 30967}, {ip: "78.41.101.200", port: 3128}, {ip: "78.81.24.112", port: 8080}, {ip: "78.81.24.112", port: 80}, {ip: "78.85.22.213", port: 32033}, {ip: "78.85.22.54", port: 39094}, {ip: "78.85.36.203", port: 8080}, {ip: "78.85.38.205", port: 54806}, {ip: "79.104.219.125", port: 3128}, {ip: "79.104.45.234", port: 34348}, {ip: "79.104.55.134", port: 8080}, {ip: "79.111.13.155", port: 50625}, {ip: "79.120.13.7", port: 3128}, {ip: "79.120.32.114", port: 54451}, {ip: "79.122.210.236", port: 59987}, {ip: "79.132.125.47", port: 41258}, {ip: "79.133.121.179", port: 53281}, {ip: "79.136.232.174", port: 58992}, {ip: "79.137.181.170", port: 8080}, {ip: "79.137.254.51", port: 44824}, {ip: "79.143.225.152", port: 35285}, {ip: "79.164.100.0", port: 44331}, {ip: "79.171.13.166", port: 33117}, {ip: "79.171.13.182", port: 39282}, {ip: "79.172.63.72", port: 8080}, {ip: "79.173.124.194", port: 47832}, {ip: "79.173.124.207", port: 53281}, {ip: "79.173.124.223", port: 33035}, {ip: "79.174.186.168", port: 45710}, {ip: "79.175.51.13", port: 54853}, {ip: "79.175.57.77", port: 55477}, {ip: "79.175.57.98", port: 60666}, {ip: "79.175.7.214", port: 56338}, {ip: "80.234.107.118", port: 56952}, {ip: "80.237.20.131", port: 39537}, {ip: "80.237.6.1", port: 34880}, {ip: "80.240.115.254", port: 38745}, {ip: "80.240.252.237", port: 45237}, {ip: "80.243.14.182", port: 49320}, {ip: "80.243.3.242", port: 36421}, {ip: "80.243.8.66", port: 51981}, {ip: "80.244.224.62", port: 8080}, {ip: "80.245.125.138", port: 39035}, {ip: "80.245.250.218", port: 49659}, {ip: "80.251.114.207", port: 47049}, {ip: "80.251.48.215", port: 45157}, {ip: "80.254.102.202", port: 8080}, {ip: "80.254.121.66", port: 41055}, {ip: "80.254.125.236", port: 80}, {ip: "80.64.105.3", port: 8080}, {ip: "80.65.22.25", port: 8080}, {ip: "80.65.27.125", port: 39789}, {ip: "80.72.121.185", port: 52379}, {ip: "80.73.66.134", port: 48825}, {ip: "80.76.105.218", port: 48597}, {ip: "80.76.187.226", port: 37643}, {ip: "80.79.76.170", port: 55437}, {ip: "80.82.55.71", port: 8080}, {ip: "80.82.55.71", port: 80}, {ip: "80.85.156.246", port: 3128}, {ip: "80.89.133.210", port: 3128}, {ip: "80.91.17.113", port: 41258}, {ip: "81.1.129.14", port: 51108}, {ip: "81.162.61.166", port: 40392}, {ip: "81.163.36.210", port: 34197}, {ip: "81.163.38.112", port: 41258}, {ip: "81.163.53.130", port: 41258}, {ip: "81.163.53.168", port: 41258}, {ip: "81.163.55.134", port: 41258}, {ip: "81.163.57.121", port: 41258}, {ip: "81.163.57.46", port: 41258}, {ip: "81.163.60.127", port: 41258}, {ip: "81.163.62.136", port: 41258}, {ip: "81.163.62.221", port: 51704}, {ip: "81.163.62.61", port: 41258}, {ip: "81.18.139.99", port: 42461}, {ip: "81.211.0.90", port: 42108}, {ip: "81.211.21.38", port: 39812}, {ip: "81.211.8.102", port: 49344}, {ip: "81.211.94.74", port: 44201}, {ip: "81.23.111.154", port: 51725}, {ip: "81.23.112.98", port: 55269}, {ip: "81.23.118.106", port: 60427}, {ip: "81.23.177.245", port: 8080}, {ip: "81.24.126.166", port: 8080}, {ip: "81.24.82.246", port: 30374}, {ip: "81.25.51.104", port: 33977}, {ip: "81.26.142.111", port: 41258}, {ip: "81.30.176.28", port: 23500}, {ip: "81.30.216.147", port: 41258}, {ip: "81.5.119.67", port: 45694}, {ip: "81.95.131.10", port: 44292}, {ip: "81.95.139.186", port: 53281}, {ip: "82.114.125.22", port: 8080}, {ip: "82.140.243.215", port: 32365}, {ip: "82.142.149.162", port: 34527}, {ip: "82.144.72.137", port: 41258}, {ip: "82.144.74.236", port: 41258}, {ip: "82.144.81.64", port: 39632}, {ip: "82.147.116.201", port: 41234}, {ip: "82.147.120.45", port: 45867}, {ip: "82.147.120.47", port: 59694}, {ip: "82.147.67.70", port: 48359}, {ip: "82.149.221.190", port: 8080}, {ip: "82.151.202.77", port: 45723}, {ip: "82.151.208.20", port: 8080}, {ip: "82.162.141.114", port: 57121}, {ip: "82.162.58.181", port: 48326}, {ip: "82.162.60.47", port: 8080}, {ip: "82.193.153.142", port: 36619}, {ip: "82.200.99.150", port: 60779}, {ip: "82.202.177.46", port: 36121}, {ip: "83.151.14.6", port: 3128}, {ip: "83.167.29.169", port: 61385}, {ip: "83.167.73.78", port: 35865}, {ip: "83.169.202.2", port: 3128}, {ip: "83.171.122.21", port: 8080}, {ip: "83.174.203.222", port: 34381}, {ip: "83.174.221.23", port: 41258}, {ip: "83.174.233.94", port: 30176}, {ip: "83.219.1.80", port: 61530}, {ip: "83.219.133.215", port: 41258}, {ip: "83.219.143.17", port: 21776}, {ip: "83.220.241.153", port: 31561}, {ip: "83.221.216.110", port: 47326}, {ip: "83.222.212.97", port: 53281}, {ip: "83.234.206.165", port: 36675}, {ip: "83.239.78.134", port: 53281}, {ip: "83.242.255.41", port: 8080}, {ip: "83.246.139.24", port: 8080}, {ip: "83.97.108.15", port: 48651}, {ip: "83.97.108.8", port: 41258}, {ip: "83.97.111.202", port: 41258}, {ip: "84.201.253.7", port: 44518}, {ip: "84.22.154.76", port: 8080}, {ip: "84.52.110.36", port: 38674}, {ip: "84.52.124.217", port: 31004}, {ip: "84.52.66.145", port: 51542}, {ip: "84.52.74.194", port: 8080}, {ip: "84.52.76.91", port: 41258}, {ip: "84.52.77.227", port: 41806}, {ip: "84.52.79.166", port: 43548}, {ip: "84.52.84.157", port: 44331}, {ip: "84.52.88.125", port: 32666}, {ip: "84.52.88.145", port: 42053}, {ip: "84.52.98.170", port: 38457}, {ip: "84.53.238.218", port: 55173}, {ip: "84.54.249.29", port: 41258}, {ip: "85.113.48.148", port: 8080}, {ip: "85.113.49.220", port: 8080}, {ip: "85.117.77.75", port: 35439}, {ip: "85.12.193.210", port: 58470}, {ip: "85.143.143.30", port: 38697}, {ip: "85.15.176.254", port: 41258}, {ip: "85.15.179.5", port: 8080}, {ip: "85.15.189.121", port: 59647}, {ip: "85.15.189.80", port: 32068}, {ip: "85.15.70.205", port: 58876}, {ip: "85.173.165.36", port: 61827}, {ip: "85.173.244.102", port: 53281}, {ip: "85.174.227.52", port: 59280}, {ip: "85.174.231.130", port: 55223}, {ip: "85.175.194.9", port: 46033}, {ip: "85.175.219.118", port: 30657}, {ip: "85.175.72.243", port: 48099}, {ip: "85.175.96.74", port: 54879}, {ip: "85.192.179.70", port: 59802}, {ip: "85.192.184.133", port: 8080}, {ip: "85.192.184.133", port: 80}, {ip: "85.202.235.61", port: 46795}, {ip: "85.21.233.198", port: 42157}, {ip: "85.21.240.193", port: 55820}, {ip: "85.21.63.219", port: 53281}, {ip: "85.234.125.219", port: 58016}, {ip: "85.234.126.107", port: 55555}, {ip: "85.234.37.148", port: 8080}, {ip: "85.235.163.54", port: 35451}, {ip: "85.235.190.18", port: 42494}, {ip: "85.235.41.169", port: 3128}, {ip: "85.236.172.134", port: 48802}, {ip: "85.237.56.193", port: 8080}, {ip: "85.30.233.79", port: 49698}, {ip: "85.91.119.6", port: 8080}, {ip: "85.93.153.54", port: 53964}, {ip: "85.93.153.54", port: 8888}, {ip: "85.93.154.150", port: 49410}, {ip: "85.95.152.115", port: 8080}, {ip: "86.102.111.242", port: 41231}, {ip: "86.102.116.30", port: 8080}, {ip: "86.110.29.7", port: 38903}, {ip: "86.110.29.82", port: 39207}, {ip: "86.110.30.146", port: 38109}, {ip: "86.110.30.202", port: 51702}, {ip: "86.62.87.130", port: 35214}, {ip: "87.103.196.39", port: 61851}, {ip: "87.103.196.39", port: 8888}, {ip: "87.117.3.129", port: 3128}, {ip: "87.225.104.27", port: 53603}, {ip: "87.225.108.195", port: 8080}, {ip: "87.225.91.64", port: 54564}, {ip: "87.228.103.111", port: 8080}, {ip: "87.228.103.43", port: 8080}, {ip: "87.229.143.10", port: 48872}, {ip: "87.229.143.46", port: 8080}, {ip: "87.229.196.30", port: 47276}, {ip: "87.229.215.38", port: 36851}, {ip: "87.229.236.166", port: 41258}, {ip: "87.240.58.30", port: 34037}, {ip: "87.249.205.103", port: 8080}, {ip: "87.249.21.140", port: 41258}, {ip: "87.249.21.193", port: 43079}, {ip: "87.249.22.114", port: 8080}, {ip: "87.249.247.200", port: 59047}, {ip: "87.249.251.106", port: 45480}, {ip: "87.249.30.210", port: 8080}, {ip: "87.251.188.218", port: 30032}, {ip: "87.255.13.217", port: 8080}, {ip: "87.255.6.76", port: 8080}, {ip: "87.76.10.119", port: 4550}, {ip: "87.76.10.119", port: 53281}, {ip: "88.135.15.234", port: 60977}, {ip: "88.147.159.167", port: 53281}, {ip: "88.200.225.32", port: 38583}, {ip: "88.204.59.143", port: 60585}, {ip: "88.204.59.177", port: 32666}, {ip: "88.206.114.229", port: 58571}, {ip: "88.82.73.242", port: 51820}, {ip: "88.84.209.69", port: 30819}, {ip: "88.84.222.218", port: 37736}, {ip: "88.87.70.84", port: 57225}, {ip: "88.87.72.181", port: 39928}, {ip: "88.87.72.72", port: 8080}, {ip: "88.87.79.20", port: 8080}, {ip: "88.87.81.217", port: 30754}, {ip: "88.87.85.187", port: 61812}, {ip: "88.87.85.220", port: 51078}, {ip: "88.87.89.57", port: 56362}, {ip: "88.87.91.163", port: 48513}, {ip: "88.87.93.20", port: 33277}, {ip: "89.104.127.174", port: 8080}, {ip: "89.105.153.245", port: 8888}, {ip: "89.109.12.82", port: 47972}, {ip: "89.109.14.179", port: 60454}, {ip: "89.109.177.238", port: 41258}, {ip: "89.109.21.43", port: 9090}, {ip: "89.109.233.227", port: 8080}, {ip: "89.109.239.183", port: 41041}, {ip: "89.109.41.239", port: 52866}, {ip: "89.109.54.137", port: 36469}, {ip: "89.109.8.160", port: 21231}, {ip: "89.110.53.72", port: 8080}, {ip: "89.169.189.173", port: 8080}, {ip: "89.169.45.133", port: 53281}, {ip: "89.17.32.157", port: 8080}, {ip: "89.17.37.218", port: 52957}, {ip: "89.175.129.145", port: 59916}, {ip: "89.175.188.58", port: 58288}, {ip: "89.178.234.177", port: 8080}, {ip: "89.179.125.123", port: 32231}, {ip: "89.185.93.35", port: 3128}, {ip: "89.188.111.101", port: 41258}, {ip: "89.188.125.51", port: 33273}, {ip: "89.189.130.103", port: 32626}, {ip: "89.189.159.214", port: 42530}, {ip: "89.189.174.121", port: 52636}, {ip: "89.189.176.17", port: 40990}, {ip: "89.189.183.183", port: 8080}, {ip: "89.189.189.115", port: 46258}, {ip: "89.19.178.240", port: 60486}, {ip: "89.19.199.152", port: 53281}, {ip: "89.207.92.146", port: 37766}, {ip: "89.22.150.162", port: 51228}, {ip: "89.22.150.249", port: 54441}, {ip: "89.22.156.16", port: 46995}, {ip: "89.222.217.168", port: 42658}, {ip: "89.23.18.29", port: 53281}, {ip: "89.23.193.68", port: 41258}, {ip: "89.23.193.68", port: 4550}, {ip: "89.249.251.21", port: 3128}, {ip: "89.250.149.114", port: 60981}, {ip: "89.250.17.209", port: 8080}, {ip: "89.250.19.173", port: 8080}, {ip: "89.250.218.14", port: 60411}, {ip: "89.250.220.40", port: 32141}, {ip: "89.251.146.11", port: 58631}, {ip: "89.251.70.155", port: 37195}, {ip: "90.150.87.172", port: 81}, {ip: "90.150.90.13", port: 8080}, {ip: "90.150.90.13", port: 80}, {ip: "90.154.125.173", port: 33078}, {ip: "90.188.239.182", port: 58585}, {ip: "90.188.38.81", port: 60585}, {ip: "90.189.151.183", port: 32601}, {ip: "91.103.196.170", port: 41258}, {ip: "91.103.208.114", port: 57063}, {ip: "91.107.117.180", port: 47172}, {ip: "91.107.8.15", port: 30727}, {ip: "91.122.100.222", port: 44331}, {ip: "91.122.207.229", port: 8080}, {ip: "91.123.18.95", port: 53927}, {ip: "91.142.149.51", port: 8080}, {ip: "91.144.139.93", port: 3128}, {ip: "91.144.142.19", port: 44617}, {ip: "91.144.142.36", port: 39050}, {ip: "91.144.147.248", port: 37632}, {ip: "91.144.147.46", port: 8080}, {ip: "91.146.16.54", port: 57902}, {ip: "91.185.32.36", port: 61710}, {ip: "91.186.105.250", port: 55245}, {ip: "91.190.116.194", port: 38783}, {ip: "91.190.80.100", port: 31659}, {ip: "91.190.85.97", port: 34286}, {ip: "91.191.190.124", port: 44104}, {ip: "91.194.121.98", port: 57205}, {ip: "91.195.130.160", port: 23500}, {ip: "91.197.105.32", port: 45228}, {ip: "91.197.174.108", port: 8080}, {ip: "91.197.204.139", port: 39415}, {ip: "91.201.116.189", port: 53281}, {ip: "91.202.27.179", port: 39172}, {ip: "91.203.36.188", port: 8080}, {ip: "91.204.139.66", port: 35623}, {ip: "91.205.131.102", port: 8080}, {ip: "91.205.131.168", port: 8080}, {ip: "91.205.131.232", port: 33247}, {ip: "91.205.131.27", port: 59420}, {ip: "91.205.146.25", port: 37501}, {ip: "91.205.53.82", port: 39238}, {ip: "91.209.59.236", port: 41258}, {ip: "91.210.94.212", port: 52635}, {ip: "91.211.106.45", port: 40496}, {ip: "91.211.52.157", port: 30186}, {ip: "91.213.23.110", port: 8080}, {ip: "91.215.22.51", port: 53305}, {ip: "91.217.202.174", port: 8080}, {ip: "91.217.42.3", port: 8080}, {ip: "91.217.42.4", port: 8080}, {ip: "91.219.136.148", port: 8080}, {ip: "91.220.135.146", port: 41258}, {ip: "91.222.167.213", port: 38057}, {ip: "91.224.207.150", port: 9999}, {ip: "91.226.140.71", port: 33199}, {ip: "91.232.146.7", port: 47924}, {ip: "91.233.45.179", port: 8080}, {ip: "91.235.186.91", port: 37757}, {ip: "91.235.7.216", port: 59067}, {ip: "91.237.202.79", port: 53281}, {ip: "91.240.74.4", port: 33149}, {ip: "91.247.149.115", port: 53281}, {ip: "91.247.250.252", port: 8080}, {ip: "92.124.128.76", port: 60039}, {ip: "92.124.195.22", port: 3128}, {ip: "92.126.193.180", port: 8080}, {ip: "92.126.206.219", port: 8080}, {ip: "92.241.110.223", port: 53281}, {ip: "92.243.163.154", port: 30231}, {ip: "92.246.220.206", port: 52675}, {ip: "92.248.163.108", port: 36202}, {ip: "92.252.240.1", port: 53281}, {ip: "92.255.164.187", port: 3128}, {ip: "92.255.164.82", port: 30206}, {ip: "92.255.169.13", port: 53281}, {ip: "92.255.183.184", port: 50082}, {ip: "92.255.195.57", port: 53281}, {ip: "92.255.196.91", port: 8080}, {ip: "92.255.199.133", port: 8080}, {ip: "92.255.200.251", port: 33844}, {ip: "92.255.202.252", port: 43627}, {ip: "92.255.205.227", port: 35341}, {ip: "92.255.229.146", port: 55785}, {ip: "92.255.248.230", port: 45906}, {ip: "92.255.5.2", port: 41012}, {ip: "92.38.32.36", port: 56113}, {ip: "92.38.45.56", port: 38299}, {ip: "92.38.45.97", port: 56267}, {ip: "92.39.129.114", port: 30674}, {ip: "92.39.138.98", port: 31150}, {ip: "92.50.142.70", port: 8080}, {ip: "92.51.16.155", port: 46202}, {ip: "92.55.30.196", port: 60729}, {ip: "92.55.59.63", port: 33030}, {ip: "92.63.184.167", port: 51095}, {ip: "93.100.215.233", port: 30635}, {ip: "93.153.201.134", port: 40158}, {ip: "93.157.163.72", port: 61064}, {ip: "93.170.109.210", port: 40075}, {ip: "93.170.112.200", port: 47995}, {ip: "93.170.113.159", port: 30476}, {ip: "93.170.113.192", port: 38488}, {ip: "93.170.113.253", port: 41282}, {ip: "93.170.204.151", port: 55065}, {ip: "93.170.247.122", port: 59573}, {ip: "93.170.247.153", port: 34183}, {ip: "93.170.254.103", port: 59754}, {ip: "93.170.82.129", port: 30704}, {ip: "93.170.95.158", port: 54691}, {ip: "93.170.95.22", port: 40194}, {ip: "93.171.157.243", port: 53059}, {ip: "93.171.157.71", port: 34767}, {ip: "93.171.190.231", port: 8080}, {ip: "93.171.98.195", port: 44283}, {ip: "93.183.125.155", port: 31004}, {ip: "93.183.86.185", port: 53281}, {ip: "93.185.193.67", port: 49977}, {ip: "93.186.98.56", port: 43511}, {ip: "93.188.124.70", port: 43050}, {ip: "93.188.208.145", port: 35203}, {ip: "93.188.45.157", port: 8080}, {ip: "93.189.148.226", port: 8080}, {ip: "93.189.222.107", port: 52279}, {ip: "93.81.246.5", port: 53281}, {ip: "93.91.112.247", port: 41258}, {ip: "93.91.162.17", port: 50672}, {ip: "93.91.172.182", port: 41258}, {ip: "93.95.162.227", port: 8080}, {ip: "94.102.124.183", port: 54612}, {ip: "94.102.124.207", port: 49790}, {ip: "94.102.127.250", port: 34414}, {ip: "94.102.127.79", port: 37434}, {ip: "94.124.193.242", port: 34962}, {ip: "94.127.217.66", port: 40115}, {ip: "94.137.232.234", port: 43948}, {ip: "94.137.232.59", port: 46408}, {ip: "94.139.118.126", port: 46058}, {ip: "94.143.42.30", port: 8080}, {ip: "94.143.45.122", port: 31151}, {ip: "94.154.85.214", port: 8080}, {ip: "94.159.48.82", port: 60529}, {ip: "94.180.106.94", port: 32767}, {ip: "94.180.108.102", port: 30335}, {ip: "94.180.118.195", port: 34449}, {ip: "94.180.245.109", port: 31046}, {ip: "94.180.246.74", port: 54475}, {ip: "94.180.249.187", port: 38051}, {ip: "94.181.182.115", port: 8080}, {ip: "94.181.46.207", port: 32600}, {ip: "94.19.90.62", port: 3128}, {ip: "94.190.9.131", port: 53281}, {ip: "94.198.132.106", port: 59950}, {ip: "94.199.109.124", port: 36447}, {ip: "94.228.245.58", port: 37697}, {ip: "94.228.250.58", port: 42688}, {ip: "94.230.119.144", port: 43305}, {ip: "94.230.243.6", port: 8080}, {ip: "94.230.251.76", port: 3128}, {ip: "94.232.11.178", port: 31624}, {ip: "94.232.57.231", port: 51064}, {ip: "94.24.233.54", port: 49549}, {ip: "94.24.233.74", port: 32231}, {ip: "94.24.244.170", port: 48936}, {ip: "94.24.249.234", port: 59316}, {ip: "94.242.55.108", port: 10010}, {ip: "94.242.55.108", port: 1448}, {ip: "94.242.57.136", port: 10010}, {ip: "94.242.57.136", port: 1448}, {ip: "94.242.58.108", port: 10010}, {ip: "94.242.58.108", port: 1448}, {ip: "94.242.58.14", port: 10010}, {ip: "94.242.58.14", port: 1448}, {ip: "94.242.58.142", port: 10010}, {ip: "94.242.58.142", port: 1448}, {ip: "94.242.59.245", port: 10010}, {ip: "94.242.59.245", port: 1448}, {ip: "94.243.140.162", port: 40960}, {ip: "94.247.241.70", port: 53640}, {ip: "94.247.62.165", port: 33176}, {ip: "94.25.104.250", port: 43893}, {ip: "94.25.30.55", port: 39141}, {ip: "94.251.19.158", port: 81}, {ip: "94.251.6.193", port: 81}, {ip: "94.253.13.228", port: 54935}, {ip: "94.253.14.187", port: 55045}, {ip: "94.253.91.52", port: 54015}, {ip: "94.28.57.100", port: 8080}, {ip: "94.28.94.154", port: 46966}, {ip: "94.73.217.125", port: 40858}, {ip: "95.128.142.106", port: 8080}, {ip: "95.129.149.79", port: 50439}, {ip: "95.140.19.9", port: 8080}, {ip: "95.140.20.94", port: 33994}, {ip: "95.140.21.66", port: 4550}, {ip: "95.140.27.135", port: 45992}, {ip: "95.140.95.84", port: 8080}, {ip: "95.143.220.5", port: 45939}, {ip: "95.154.137.66", port: 41258}, {ip: "95.154.152.162", port: 43560}, {ip: "95.154.159.119", port: 44242}, {ip: "95.154.70.151", port: 53281}, {ip: "95.154.70.49", port: 30656}, {ip: "95.154.71.77", port: 30865}, {ip: "95.154.72.12", port: 32641}, {ip: "95.154.73.233", port: 58000}, {ip: "95.154.75.33", port: 33891}, {ip: "95.154.75.55", port: 8080}, {ip: "95.154.82.254", port: 52484}, {ip: "95.156.95.158", port: 59310}, {ip: "95.161.157.227", port: 43170}, {ip: "95.161.182.146", port: 33877}, {ip: "95.161.189.26", port: 61522}, {ip: "95.161.231.10", port: 32189}, {ip: "95.163.128.130", port: 46266}, {ip: "95.165.131.204", port: 45848}, {ip: "95.165.149.106", port: 45921}, {ip: "95.165.153.88", port: 44255}, {ip: "95.165.163.146", port: 8888}, {ip: "95.165.172.90", port: 60496}, {ip: "95.165.182.18", port: 38950}, {ip: "95.165.203.222", port: 33805}, {ip: "95.165.222.90", port: 60776}, {ip: "95.165.244.122", port: 58162}, {ip: "95.167.123.54", port: 58664}, {ip: "95.167.178.30", port: 52103}, {ip: "95.167.241.242", port: 49636}, {ip: "95.167.65.6", port: 32870}, {ip: "95.169.115.43", port: 54856}, {ip: "95.170.113.165", port: 41153}, {ip: "95.171.1.92", port: 35956}, {ip: "95.172.49.10", port: 52217}, {ip: "95.172.52.230", port: 35989}, {ip: "95.172.59.30", port: 48526}, {ip: "95.172.62.194", port: 42971}, {ip: "95.174.104.145", port: 32087}, {ip: "95.174.124.5", port: 41258}, {ip: "95.181.131.199", port: 58010}, {ip: "95.181.134.136", port: 59434}, {ip: "95.181.143.106", port: 54879}, {ip: "95.181.35.30", port: 40804}, {ip: "95.181.49.154", port: 32150}, {ip: "95.181.56.178", port: 39144}, {ip: "95.181.58.170", port: 53929}, {ip: "95.181.75.228", port: 53281}, {ip: "95.188.74.194", port: 57122}, {ip: "95.189.112.214", port: 35508}, {ip: "95.189.78.124", port: 48404}, {ip: "95.213.138.203", port: 21231}, {ip: "95.215.228.130", port: 42493}, {ip: "95.24.5.161", port: 51585}, {ip: "95.24.84.246", port: 35934}, {ip: "95.27.166.48", port: 35165}, {ip: "95.27.168.220", port: 43258}, {ip: "95.30.250.37", port: 34463}, {ip: "95.31.1.50", port: 53847}, {ip: "95.31.10.247", port: 30711}, {ip: "95.31.104.69", port: 32532}, {ip: "95.31.13.38", port: 57301}, {ip: "95.31.13.55", port: 43632}, {ip: "95.31.197.77", port: 41651}, {ip: "95.31.2.199", port: 33632}, {ip: "95.31.244.19", port: 36360}, {ip: "95.31.252.16", port: 49119}, {ip: "95.31.4.125", port: 55361}, {ip: "95.31.88.10", port: 53281}, {ip: "95.46.225.63", port: 31468}, {ip: "95.53.254.194", port: 51142}, {ip: "95.64.253.177", port: 53643}, {ip: "95.66.136.240", port: 8080}, {ip: "95.66.140.121", port: 52212}, {ip: "95.66.142.18", port: 49018}, {ip: "95.66.173.90", port: 61359}, {ip: "95.68.242.211", port: 59236}, {ip: "95.68.242.38", port: 36855}, {ip: "95.68.252.20", port: 8080}, {ip: "95.71.125.50", port: 49882}, {ip: "95.71.126.250", port: 55705}, {ip: "95.71.127.99", port: 59369}, {ip: "95.73.62.13", port: 32185}, {ip: "95.78.125.64", port: 39921}, {ip: "95.78.157.140", port: 42161}, {ip: "95.78.160.156", port: 54129}, {ip: "95.78.172.184", port: 8080}, {ip: "95.78.172.50", port: 60695}, {ip: "95.78.177.63", port: 46184}, {ip: "95.78.228.55", port: 49164}, {ip: "95.78.232.102", port: 57165}, {ip: "95.78.245.148", port: 33622}, {ip: "95.78.247.36", port: 23500}, {ip: "95.79.101.135", port: 59841}, {ip: "95.79.106.202", port: 39556}, {ip: "95.79.116.221", port: 32923}, {ip: "95.79.26.141", port: 38872}, {ip: "95.79.28.168", port: 53491}, {ip: "95.79.36.55", port: 44861}, {ip: "95.79.48.198", port: 4550}, {ip: "95.79.48.198", port: 51307}, {ip: "95.79.51.209", port: 4550}, {ip: "95.79.53.112", port: 8080}, {ip: "95.79.53.53", port: 39276}, {ip: "95.79.54.104", port: 45926}, {ip: "95.79.54.108", port: 35018}, {ip: "95.79.54.143", port: 32658}, {ip: "95.79.55.196", port: 53281}, {ip: "95.79.99.148", port: 3128}, {ip: "95.80.109.246", port: 8080}, {ip: "95.80.119.57", port: 41771}, {ip: "95.80.65.39", port: 43555}, {ip: "95.80.77.98", port: 56601}, {ip: "95.80.87.178", port: 44122}, {ip: "95.80.93.44", port: 41258}, {ip: "95.80.98.41", port: 8080}, {ip: "95.82.251.187", port: 36145}, {ip: "95.83.156.250", port: 58438}, {ip: "95.84.128.25", port: 33765}, {ip: "95.84.154.151", port: 33654}, {ip: "95.84.154.73", port: 57423}, {ip: "95.84.164.92", port: 60071}, {ip: "95.84.168.111", port: 36740}, {ip: "95.84.168.158", port: 38775}, {ip: "95.84.168.230", port: 32147}, {ip: "95.84.190.160", port: 34429}, {ip: "95.84.198.135", port: 51256}, {ip: "95.84.198.24", port: 51251}], - "CA" => [{ip: "138.197.174.62", port: 8080}, {ip: "142.59.9.85", port: 31419}, {ip: "144.172.216.109", port: 57017}, {ip: "144.217.161.149", port: 8080}, {ip: "144.217.190.246", port: 30451}, {ip: "149.248.131.81", port: 41897}, {ip: "149.56.66.84", port: 53281}, {ip: "158.69.206.181", port: 8888}, {ip: "159.203.22.190", port: 8080}, {ip: "159.203.23.98", port: 3128}, {ip: "159.203.44.119", port: 8080}, {ip: "159.203.46.243", port: 8080}, {ip: "159.89.114.227", port: 3128}, {ip: "162.223.47.160", port: 8080}, {ip: "163.172.157.124", port: 8118}, {ip: "167.114.79.139", port: 56986}, {ip: "167.99.176.159", port: 8080}, {ip: "167.99.179.29", port: 8888}, {ip: "167.99.188.66", port: 8080}, {ip: "167.99.189.243", port: 3128}, {ip: "167.99.189.243", port: 8000}, {ip: "167.99.189.243", port: 8080}, {ip: "173.231.106.226", port: 8080}, {ip: "184.161.154.29", port: 35160}, {ip: "184.67.108.118", port: 50311}, {ip: "184.67.236.222", port: 8080}, {ip: "184.70.102.82", port: 61825}, {ip: "184.75.215.13", port: 32062}, {ip: "192.199.53.131", port: 31637}, {ip: "192.226.204.118", port: 35155}, {ip: "198.27.78.80", port: 3128}, {ip: "205.189.41.247", port: 8080}, {ip: "207.134.166.50", port: 59929}, {ip: "208.97.119.150", port: 55582}, {ip: "216.104.97.27", port: 55892}, {ip: "24.202.169.160", port: 48022}, {ip: "24.226.159.195", port: 42323}, {ip: "24.37.245.42", port: 30671}, {ip: "24.37.9.6", port: 54154}, {ip: "24.57.202.234", port: 37235}, {ip: "45.62.247.23", port: 3128}, {ip: "45.73.90.225", port: 50963}, {ip: "54.39.138.144", port: 3128}, {ip: "54.39.138.145", port: 3128}, {ip: "54.39.138.146", port: 3128}, {ip: "54.39.138.147", port: 3128}, {ip: "54.39.138.148", port: 3128}, {ip: "54.39.138.150", port: 3128}, {ip: "54.39.138.151", port: 3128}, {ip: "54.39.138.152", port: 3128}, {ip: "54.39.138.153", port: 3128}, {ip: "54.39.138.154", port: 3128}, {ip: "54.39.138.155", port: 3128}, {ip: "54.39.138.156", port: 3128}, {ip: "54.39.138.157", port: 3128}, {ip: "54.39.16.236", port: 31289}, {ip: "54.39.186.230", port: 8080}, {ip: "54.39.19.46", port: 31289}, {ip: "54.39.20.167", port: 3128}, {ip: "54.39.53.104", port: 3128}, {ip: "54.39.97.250", port: 3128}, {ip: "64.137.191.20", port: 3128}, {ip: "66.70.167.113", port: 3128}, {ip: "66.70.167.116", port: 3128}, {ip: "66.70.167.117", port: 3128}, {ip: "66.70.167.119", port: 3128}, {ip: "66.70.167.120", port: 3128}, {ip: "66.70.167.123", port: 3128}, {ip: "66.70.167.125", port: 3128}, {ip: "66.70.188.148", port: 3128}, {ip: "68.171.65.230", port: 8081}, {ip: "68.171.68.0", port: 8081}, {ip: "69.70.211.66", port: 56282}, {ip: "70.35.213.229", port: 36127}, {ip: "70.64.208.239", port: 36122}, {ip: "70.65.233.174", port: 8080}, {ip: "70.81.183.36", port: 47868}, {ip: "70.83.106.82", port: 8888}, {ip: "70.83.42.205", port: 53130}, {ip: "72.139.24.66", port: 38861}, {ip: "72.38.127.210", port: 35915}, {ip: "72.38.188.134", port: 47764}, {ip: "74.15.191.160", port: 41564}, {ip: "74.221.20.242", port: 39766}, {ip: "96.125.128.99", port: 53015}], - "JP" => [{ip: "117.104.128.22", port: 57136}, {ip: "117.104.131.83", port: 36588}, {ip: "140.227.10.14", port: 3128}, {ip: "140.227.11.133", port: 3128}, {ip: "140.227.13.204", port: 3128}, {ip: "140.227.206.20", port: 3128}, {ip: "140.227.207.20", port: 3128}, {ip: "140.227.209.21", port: 3128}, {ip: "140.227.210.13", port: 3128}, {ip: "140.227.210.20", port: 3128}, {ip: "140.227.26.104", port: 3128}, {ip: "140.227.29.94", port: 3128}, {ip: "140.227.31.235", port: 3128}, {ip: "140.227.31.77", port: 3128}, {ip: "140.227.33.203", port: 3128}, {ip: "140.227.33.30", port: 3128}, {ip: "140.227.53.126", port: 3128}, {ip: "140.227.53.143", port: 3128}, {ip: "140.227.53.4", port: 3128}, {ip: "140.227.54.29", port: 3128}, {ip: "140.227.56.164", port: 3128}, {ip: "140.227.57.151", port: 3128}, {ip: "140.227.58.74", port: 3128}, {ip: "140.227.59.156", port: 3128}, {ip: "140.227.59.67", port: 3128}, {ip: "140.227.60.114", port: 3128}, {ip: "140.227.60.146", port: 3128}, {ip: "140.227.60.162", port: 3128}, {ip: "140.227.62.157", port: 3128}, {ip: "140.227.63.153", port: 3128}, {ip: "140.227.64.147", port: 3128}, {ip: "140.227.68.82", port: 3128}, {ip: "140.227.71.120", port: 3128}, {ip: "140.227.72.172", port: 3128}, {ip: "140.227.73.77", port: 3128}, {ip: "140.227.73.83", port: 3128}, {ip: "140.227.74.138", port: 3128}, {ip: "140.227.74.164", port: 3128}, {ip: "140.227.75.107", port: 3128}, {ip: "140.227.75.198", port: 3128}, {ip: "140.227.76.106", port: 3128}, {ip: "140.227.77.174", port: 3128}, {ip: "140.227.77.202", port: 3128}, {ip: "140.227.78.185", port: 3128}, {ip: "140.227.79.108", port: 3128}, {ip: "140.227.80.177", port: 3128}, {ip: "140.227.81.53", port: 3128}, {ip: "157.65.166.51", port: 3128}, {ip: "157.65.167.118", port: 3128}, {ip: "157.65.167.8", port: 3128}, {ip: "157.65.168.145", port: 3128}, {ip: "157.65.169.60", port: 3128}, {ip: "157.65.169.86", port: 3128}, {ip: "157.65.171.20", port: 3128}, {ip: "157.65.171.223", port: 3128}, {ip: "157.65.171.86", port: 3128}, {ip: "157.65.24.39", port: 3128}, {ip: "157.65.28.92", port: 3128}, {ip: "157.65.29.23", port: 3128}, {ip: "157.65.29.248", port: 3128}, {ip: "157.65.31.220", port: 3128}, {ip: "159.28.206.223", port: 8080}, {ip: "163.44.167.180", port: 8888}, {ip: "163.44.173.238", port: 3128}, {ip: "45.77.131.135", port: 8118}, {ip: "47.94.11.186", port: 1080}, {ip: "52.81.8.156", port: 1080}, {ip: "61.118.35.94", port: 55725}], - "IT" => [{ip: "109.104.252.24", port: 47218}, {ip: "109.168.64.157", port: 34023}, {ip: "109.232.137.111", port: 50247}, {ip: "109.232.137.244", port: 57477}, {ip: "109.239.252.183", port: 52350}, {ip: "109.70.201.97", port: 53517}, {ip: "128.127.1.69", port: 39655}, {ip: "151.3.53.246", port: 53281}, {ip: "176.31.82.212", port: 8080}, {ip: "178.20.39.105", port: 36227}, {ip: "185.122.44.218", port: 57794}, {ip: "185.132.228.118", port: 55583}, {ip: "185.132.230.9", port: 54511}, {ip: "185.132.68.74", port: 36025}, {ip: "185.132.68.94", port: 36025}, {ip: "185.139.30.93", port: 40780}, {ip: "185.152.44.137", port: 32231}, {ip: "185.178.93.1", port: 41258}, {ip: "185.178.95.121", port: 41258}, {ip: "185.213.115.132", port: 61288}, {ip: "185.27.72.12", port: 31133}, {ip: "185.36.75.62", port: 8080}, {ip: "185.41.215.81", port: 42801}, {ip: "185.49.58.88", port: 56006}, {ip: "185.67.236.199", port: 43388}, {ip: "185.68.195.103", port: 8080}, {ip: "185.68.195.104", port: 8080}, {ip: "185.68.195.89", port: 8080}, {ip: "185.72.42.37", port: 60426}, {ip: "185.73.136.250", port: 31741}, {ip: "185.75.110.8", port: 59374}, {ip: "185.94.89.179", port: 41258}, {ip: "193.109.45.171", port: 36466}, {ip: "193.109.45.173", port: 36466}, {ip: "194.243.194.60", port: 80}, {ip: "195.32.14.154", port: 32814}, {ip: "195.32.14.155", port: 39672}, {ip: "195.32.14.225", port: 60625}, {ip: "2.239.208.102", port: 42091}, {ip: "212.43.123.18", port: 41258}, {ip: "212.66.127.228", port: 41258}, {ip: "213.137.36.167", port: 41258}, {ip: "213.203.134.10", port: 41258}, {ip: "217.61.172.12", port: 41369}, {ip: "31.223.254.205", port: 53725}, {ip: "37.130.217.128", port: 41258}, {ip: "37.130.221.122", port: 41258}, {ip: "46.227.158.160", port: 42538}, {ip: "46.232.143.126", port: 41258}, {ip: "46.232.143.253", port: 41258}, {ip: "46.255.81.82", port: 44722}, {ip: "5.42.148.110", port: 40928}, {ip: "5.8.114.240", port: 60560}, {ip: "5.97.104.141", port: 58877}, {ip: "62.196.124.229", port: 51449}, {ip: "62.196.125.170", port: 39036}, {ip: "62.196.125.171", port: 39036}, {ip: "77.239.133.146", port: 3128}, {ip: "77.239.133.146", port: 80}, {ip: "79.135.46.62", port: 41258}, {ip: "80.211.27.41", port: 8118}, {ip: "80.211.89.241", port: 443}, {ip: "80.23.146.50", port: 53281}, {ip: "80.86.54.60", port: 56878}, {ip: "82.85.180.130", port: 34864}, {ip: "83.216.184.91", port: 31470}, {ip: "88.86.190.121", port: 58020}, {ip: "89.119.227.211", port: 39767}, {ip: "89.207.111.62", port: 41258}, {ip: "91.214.61.221", port: 36994}, {ip: "92.245.161.204", port: 53281}, {ip: "93.147.181.90", port: 54949}, {ip: "93.33.234.116", port: 56793}, {ip: "93.39.112.247", port: 31669}, {ip: "93.67.154.125", port: 8080}, {ip: "93.67.154.125", port: 80}, {ip: "94.138.191.38", port: 41258}, {ip: "95.169.95.242", port: 53803}, {ip: "95.210.191.156", port: 59802}, {ip: "95.210.251.29", port: 53281}, {ip: "95.87.127.133", port: 43730}], - "TH" => [{ip: "1.10.184.166", port: 57330}, {ip: "1.10.185.133", port: 51287}, {ip: "1.10.185.8", port: 30267}, {ip: "1.10.186.100", port: 55011}, {ip: "1.10.186.102", port: 34657}, {ip: "1.10.186.105", port: 57703}, {ip: "1.10.186.114", port: 43904}, {ip: "1.10.186.12", port: 39736}, {ip: "1.10.186.128", port: 56211}, {ip: "1.10.186.129", port: 56558}, {ip: "1.10.186.130", port: 55069}, {ip: "1.10.186.15", port: 56618}, {ip: "1.10.186.156", port: 42755}, {ip: "1.10.186.163", port: 30544}, {ip: "1.10.186.17", port: 58527}, {ip: "1.10.186.172", port: 54860}, {ip: "1.10.186.173", port: 50877}, {ip: "1.10.186.178", port: 40492}, {ip: "1.10.186.18", port: 60507}, {ip: "1.10.186.180", port: 46096}, {ip: "1.10.186.181", port: 41345}, {ip: "1.10.186.185", port: 47712}, {ip: "1.10.186.209", port: 32431}, {ip: "1.10.186.21", port: 35862}, {ip: "1.10.186.211", port: 48744}, {ip: "1.10.186.212", port: 48011}, {ip: "1.10.186.228", port: 55466}, {ip: "1.10.186.240", port: 48962}, {ip: "1.10.186.245", port: 34360}, {ip: "1.10.186.35", port: 42540}, {ip: "1.10.186.43", port: 34453}, {ip: "1.10.186.45", port: 59931}, {ip: "1.10.186.48", port: 37765}, {ip: "1.10.186.52", port: 31771}, {ip: "1.10.186.63", port: 41633}, {ip: "1.10.186.67", port: 58888}, {ip: "1.10.186.87", port: 59606}, {ip: "1.10.186.93", port: 53711}, {ip: "1.10.187.118", port: 62000}, {ip: "1.10.187.132", port: 58948}, {ip: "1.10.187.137", port: 38953}, {ip: "1.10.187.148", port: 51141}, {ip: "1.10.187.150", port: 57245}, {ip: "1.10.187.172", port: 47493}, {ip: "1.10.187.188", port: 30851}, {ip: "1.10.187.201", port: 34344}, {ip: "1.10.187.208", port: 33806}, {ip: "1.10.187.22", port: 35670}, {ip: "1.10.187.225", port: 43057}, {ip: "1.10.187.234", port: 61472}, {ip: "1.10.187.241", port: 48591}, {ip: "1.10.187.245", port: 59548}, {ip: "1.10.187.34", port: 51635}, {ip: "1.10.187.43", port: 38715}, {ip: "1.10.187.56", port: 38721}, {ip: "1.10.187.6", port: 34409}, {ip: "1.10.187.72", port: 39678}, {ip: "1.10.187.85", port: 60009}, {ip: "1.10.188.100", port: 50404}, {ip: "1.10.188.118", port: 47188}, {ip: "1.10.188.12", port: 44873}, {ip: "1.10.188.121", port: 47890}, {ip: "1.10.188.128", port: 31351}, {ip: "1.10.188.141", port: 60882}, {ip: "1.10.188.144", port: 45927}, {ip: "1.10.188.146", port: 52937}, {ip: "1.10.188.181", port: 51093}, {ip: "1.10.188.184", port: 50983}, {ip: "1.10.188.194", port: 31599}, {ip: "1.10.188.195", port: 33150}, {ip: "1.10.188.202", port: 61629}, {ip: "1.10.188.21", port: 58235}, {ip: "1.10.188.214", port: 46563}, {ip: "1.10.188.218", port: 35749}, {ip: "1.10.188.220", port: 43560}, {ip: "1.10.188.222", port: 35453}, {ip: "1.10.188.43", port: 61765}, {ip: "1.10.188.54", port: 58220}, {ip: "1.10.188.68", port: 48762}, {ip: "1.10.188.73", port: 44823}, {ip: "1.10.188.76", port: 38394}, {ip: "1.10.188.8", port: 39915}, {ip: "1.10.188.83", port: 31940}, {ip: "1.10.188.85", port: 35121}, {ip: "1.10.188.88", port: 47760}, {ip: "1.10.188.94", port: 41229}, {ip: "1.10.188.95", port: 30593}, {ip: "1.10.188.98", port: 52842}, {ip: "1.10.188.99", port: 35852}, {ip: "1.10.189.100", port: 30090}, {ip: "1.10.189.12", port: 54425}, {ip: "1.10.189.121", port: 38822}, {ip: "1.10.189.126", port: 45526}, {ip: "1.10.189.31", port: 61828}, {ip: "1.10.189.45", port: 33696}, {ip: "1.10.189.53", port: 43968}, {ip: "1.10.189.57", port: 46116}, {ip: "1.10.189.58", port: 48564}, {ip: "1.10.189.62", port: 31452}, {ip: "1.10.189.65", port: 41966}, {ip: "1.10.189.97", port: 50644}, {ip: "1.179.143.53", port: 44452}, {ip: "1.179.147.5", port: 37296}, {ip: "1.179.148.9", port: 44155}, {ip: "1.179.151.145", port: 36654}, {ip: "1.179.157.237", port: 46178}, {ip: "1.179.158.53", port: 40583}, {ip: "1.179.164.213", port: 8080}, {ip: "1.179.173.5", port: 43102}, {ip: "1.179.180.17", port: 30440}, {ip: "1.179.184.158", port: 34927}, {ip: "1.179.198.37", port: 8080}, {ip: "1.2.169.122", port: 43117}, {ip: "1.2.169.123", port: 58278}, {ip: "1.2.169.4", port: 35900}, {ip: "1.2.169.85", port: 37250}, {ip: "1.20.100.132", port: 55495}, {ip: "1.20.100.177", port: 46834}, {ip: "1.20.100.234", port: 40099}, {ip: "1.20.100.81", port: 49149}, {ip: "1.20.100.91", port: 35544}, {ip: "1.20.100.99", port: 53794}, {ip: "1.20.101.110", port: 61368}, {ip: "1.20.101.221", port: 55707}, {ip: "1.20.101.254", port: 35394}, {ip: "1.20.101.80", port: 36234}, {ip: "1.20.102.129", port: 35049}, {ip: "1.20.102.133", port: 40296}, {ip: "1.20.102.167", port: 49758}, {ip: "1.20.102.191", port: 49775}, {ip: "1.20.102.84", port: 55168}, {ip: "1.20.103.100", port: 30802}, {ip: "1.20.103.13", port: 40544}, {ip: "1.20.103.192", port: 61861}, {ip: "1.20.103.208", port: 47481}, {ip: "1.20.103.241", port: 58029}, {ip: "1.20.103.56", port: 55422}, {ip: "1.20.103.78", port: 56833}, {ip: "1.20.103.8", port: 55485}, {ip: "1.20.96.118", port: 34489}, {ip: "1.20.96.160", port: 46769}, {ip: "1.20.96.198", port: 44308}, {ip: "1.20.96.234", port: 53142}, {ip: "1.20.96.248", port: 57556}, {ip: "1.20.97.104", port: 31305}, {ip: "1.20.97.108", port: 33388}, {ip: "1.20.97.112", port: 30997}, {ip: "1.20.97.114", port: 41661}, {ip: "1.20.97.122", port: 54909}, {ip: "1.20.97.132", port: 54656}, {ip: "1.20.97.148", port: 33460}, {ip: "1.20.97.155", port: 45714}, {ip: "1.20.97.158", port: 41981}, {ip: "1.20.97.159", port: 42515}, {ip: "1.20.97.166", port: 45644}, {ip: "1.20.97.179", port: 52437}, {ip: "1.20.97.181", port: 51427}, {ip: "1.20.97.186", port: 30643}, {ip: "1.20.97.189", port: 55170}, {ip: "1.20.97.190", port: 40531}, {ip: "1.20.97.191", port: 57834}, {ip: "1.20.97.203", port: 54579}, {ip: "1.20.97.204", port: 38689}, {ip: "1.20.97.212", port: 48674}, {ip: "1.20.97.213", port: 51794}, {ip: "1.20.97.216", port: 36743}, {ip: "1.20.97.222", port: 42603}, {ip: "1.20.97.225", port: 32301}, {ip: "1.20.97.227", port: 42934}, {ip: "1.20.97.23", port: 44290}, {ip: "1.20.97.238", port: 53599}, {ip: "1.20.97.24", port: 52877}, {ip: "1.20.97.4", port: 41795}, {ip: "1.20.97.46", port: 46206}, {ip: "1.20.97.47", port: 57039}, {ip: "1.20.97.54", port: 60122}, {ip: "1.20.97.68", port: 38481}, {ip: "1.20.97.93", port: 41217}, {ip: "1.20.98.15", port: 50116}, {ip: "1.20.98.150", port: 40891}, {ip: "1.20.98.18", port: 47201}, {ip: "1.20.98.211", port: 51330}, {ip: "1.20.98.22", port: 41807}, {ip: "1.20.98.40", port: 49487}, {ip: "1.20.98.57", port: 50882}, {ip: "1.20.98.60", port: 58159}, {ip: "1.20.98.66", port: 47505}, {ip: "1.20.98.78", port: 35136}, {ip: "1.20.98.83", port: 30466}, {ip: "1.20.99.10", port: 45820}, {ip: "1.20.99.125", port: 42027}, {ip: "1.20.99.143", port: 42677}, {ip: "1.20.99.176", port: 47317}, {ip: "1.20.99.178", port: 43863}, {ip: "1.20.99.185", port: 57666}, {ip: "1.20.99.23", port: 56816}, {ip: "1.20.99.32", port: 39968}, {ip: "1.20.99.42", port: 34311}, {ip: "1.20.99.44", port: 53531}, {ip: "1.20.99.47", port: 33129}, {ip: "1.20.99.57", port: 50442}, {ip: "1.20.99.63", port: 32123}, {ip: "1.20.99.83", port: 52447}, {ip: "1.20.99.85", port: 55815}, {ip: "1.20.99.89", port: 61902}, {ip: "101.108.92.20", port: 8080}, {ip: "101.109.143.71", port: 36127}, {ip: "101.109.242.3", port: 8080}, {ip: "101.109.83.204", port: 38641}, {ip: "101.109.83.221", port: 30558}, {ip: "101.51.106.58", port: 50507}, {ip: "101.51.138.13", port: 8080}, {ip: "101.51.138.13", port: 80}, {ip: "101.51.141.101", port: 31327}, {ip: "101.51.141.102", port: 41823}, {ip: "101.51.141.106", port: 50867}, {ip: "101.51.141.110", port: 42860}, {ip: "101.51.141.115", port: 61906}, {ip: "101.51.141.46", port: 42104}, {ip: "101.51.141.49", port: 47121}, {ip: "101.51.141.60", port: 60417}, {ip: "101.51.141.64", port: 51488}, {ip: "103.246.17.237", port: 3128}, {ip: "103.253.75.31", port: 44121}, {ip: "106.0.224.154", port: 80}, {ip: "110.164.58.103", port: 44093}, {ip: "110.164.73.131", port: 8080}, {ip: "110.164.87.80", port: 35844}, {ip: "110.168.191.26", port: 35502}, {ip: "110.169.50.215", port: 44898}, {ip: "110.77.134.106", port: 8080}, {ip: "110.77.201.55", port: 8080}, {ip: "110.77.246.60", port: 8080}, {ip: "110.78.145.84", port: 8080}, {ip: "110.78.149.43", port: 8080}, {ip: "113.53.29.92", port: 47297}, {ip: "113.53.60.11", port: 8080}, {ip: "113.53.60.11", port: 80}, {ip: "113.53.82.92", port: 49643}, {ip: "113.53.83.139", port: 51563}, {ip: "113.53.83.155", port: 42493}, {ip: "113.53.83.157", port: 47392}, {ip: "113.53.83.184", port: 55295}, {ip: "113.53.83.192", port: 32780}, {ip: "113.53.83.195", port: 35686}, {ip: "113.53.83.210", port: 33215}, {ip: "113.53.83.252", port: 42151}, {ip: "113.53.91.12", port: 53281}, {ip: "113.53.91.17", port: 45148}, {ip: "113.53.91.214", port: 8080}, {ip: "114.109.22.32", port: 41018}, {ip: "115.87.27.0", port: 53276}, {ip: "118.172.181.147", port: 60363}, {ip: "118.172.181.181", port: 48015}, {ip: "118.172.211.11", port: 39212}, {ip: "118.172.211.155", port: 43259}, {ip: "118.172.211.166", port: 35811}, {ip: "118.172.211.167", port: 44550}, {ip: "118.172.211.168", port: 56606}, {ip: "118.172.211.169", port: 49437}, {ip: "118.172.211.17", port: 39122}, {ip: "118.172.211.171", port: 42590}, {ip: "118.172.211.175", port: 56096}, {ip: "118.172.211.183", port: 51615}, {ip: "118.172.211.195", port: 34289}, {ip: "118.172.211.22", port: 57166}, {ip: "118.172.211.26", port: 60327}, {ip: "118.172.211.3", port: 58535}, {ip: "118.172.211.37", port: 32553}, {ip: "118.172.211.39", port: 49186}, {ip: "118.172.211.4", port: 40384}, {ip: "118.172.211.40", port: 30430}, {ip: "118.172.43.60", port: 8080}, {ip: "118.172.51.206", port: 32425}, {ip: "118.172.51.67", port: 42912}, {ip: "118.173.232.120", port: 60396}, {ip: "118.173.232.169", port: 35880}, {ip: "118.173.232.184", port: 42704}, {ip: "118.173.232.32", port: 36104}, {ip: "118.173.232.47", port: 34341}, {ip: "118.173.232.68", port: 58118}, {ip: "118.173.232.78", port: 52456}, {ip: "118.173.232.99", port: 47186}, {ip: "118.173.233.134", port: 53722}, {ip: "118.173.233.149", port: 48606}, {ip: "118.173.233.150", port: 47625}, {ip: "118.173.233.151", port: 58480}, {ip: "118.173.233.152", port: 61838}, {ip: "118.173.233.158", port: 30673}, {ip: "118.173.233.243", port: 44125}, {ip: "118.173.233.38", port: 54995}, {ip: "118.173.233.80", port: 57573}, {ip: "118.174.196.174", port: 23500}, {ip: "118.174.196.203", port: 23500}, {ip: "118.174.196.39", port: 31879}, {ip: "118.174.196.6", port: 35361}, {ip: "118.174.220.104", port: 47074}, {ip: "118.174.220.107", port: 41222}, {ip: "118.174.220.109", port: 52336}, {ip: "118.174.220.110", port: 39025}, {ip: "118.174.220.115", port: 41011}, {ip: "118.174.220.116", port: 53678}, {ip: "118.174.220.118", port: 59556}, {ip: "118.174.220.120", port: 39858}, {ip: "118.174.220.130", port: 45781}, {ip: "118.174.220.131", port: 45232}, {ip: "118.174.220.136", port: 55041}, {ip: "118.174.220.14", port: 42280}, {ip: "118.174.220.142", port: 31779}, {ip: "118.174.220.157", port: 50400}, {ip: "118.174.220.163", port: 31561}, {ip: "118.174.220.164", port: 40850}, {ip: "118.174.220.168", port: 47455}, {ip: "118.174.220.176", port: 40840}, {ip: "118.174.220.191", port: 52068}, {ip: "118.174.220.193", port: 37326}, {ip: "118.174.220.199", port: 35468}, {ip: "118.174.220.216", port: 43089}, {ip: "118.174.220.218", port: 48094}, {ip: "118.174.220.224", port: 59789}, {ip: "118.174.220.231", port: 40924}, {ip: "118.174.220.238", port: 46326}, {ip: "118.174.220.248", port: 60571}, {ip: "118.174.220.27", port: 33091}, {ip: "118.174.220.42", port: 57384}, {ip: "118.174.220.45", port: 43635}, {ip: "118.174.220.58", port: 60894}, {ip: "118.174.220.60", port: 51403}, {ip: "118.174.220.68", port: 60989}, {ip: "118.174.220.84", port: 61598}, {ip: "118.174.234.100", port: 38767}, {ip: "118.174.234.11", port: 58208}, {ip: "118.174.234.13", port: 53084}, {ip: "118.174.234.131", port: 56467}, {ip: "118.174.234.135", port: 51769}, {ip: "118.174.234.136", port: 58259}, {ip: "118.174.234.138", port: 42986}, {ip: "118.174.234.141", port: 42201}, {ip: "118.174.234.143", port: 30778}, {ip: "118.174.234.144", port: 41172}, {ip: "118.174.234.160", port: 47541}, {ip: "118.174.234.162", port: 39381}, {ip: "118.174.234.164", port: 56285}, {ip: "118.174.234.18", port: 43199}, {ip: "118.174.234.195", port: 55111}, {ip: "118.174.234.198", port: 51675}, {ip: "118.174.234.20", port: 42908}, {ip: "118.174.234.21", port: 46681}, {ip: "118.174.234.26", port: 41926}, {ip: "118.174.234.28", port: 46285}, {ip: "118.174.234.29", port: 50819}, {ip: "118.174.234.30", port: 48485}, {ip: "118.174.234.32", port: 57403}, {ip: "118.174.234.36", port: 33364}, {ip: "118.174.234.41", port: 58469}, {ip: "118.174.234.46", port: 33229}, {ip: "118.174.234.49", port: 48923}, {ip: "118.174.234.55", port: 32783}, {ip: "118.174.234.57", port: 30580}, {ip: "118.174.234.58", port: 44731}, {ip: "118.174.234.59", port: 59149}, {ip: "118.174.234.68", port: 42626}, {ip: "118.174.234.80", port: 40442}, {ip: "118.174.234.83", port: 38006}, {ip: "118.174.255.7", port: 56958}, {ip: "118.174.255.8", port: 49733}, {ip: "118.174.255.86", port: 55275}, {ip: "118.174.255.89", port: 60776}, {ip: "118.174.64.72", port: 57791}, {ip: "118.174.65.140", port: 57602}, {ip: "118.175.186.114", port: 45493}, {ip: "118.175.207.104", port: 38959}, {ip: "118.175.207.129", port: 46292}, {ip: "118.175.207.205", port: 32288}, {ip: "118.175.207.213", port: 59240}, {ip: "118.175.207.216", port: 32035}, {ip: "118.175.207.218", port: 44032}, {ip: "118.175.244.111", port: 8080}, {ip: "118.175.244.28", port: 8080}, {ip: "118.175.93.103", port: 36802}, {ip: "118.175.93.105", port: 60102}, {ip: "118.175.93.107", port: 34063}, {ip: "118.175.93.112", port: 54499}, {ip: "118.175.93.131", port: 37851}, {ip: "118.175.93.132", port: 37988}, {ip: "118.175.93.137", port: 53807}, {ip: "118.175.93.144", port: 59045}, {ip: "118.175.93.148", port: 49286}, {ip: "118.175.93.158", port: 57875}, {ip: "118.175.93.16", port: 33028}, {ip: "118.175.93.174", port: 32107}, {ip: "118.175.93.179", port: 52940}, {ip: "118.175.93.182", port: 53884}, {ip: "118.175.93.187", port: 57983}, {ip: "118.175.93.189", port: 32888}, {ip: "118.175.93.207", port: 50738}, {ip: "118.175.93.24", port: 34350}, {ip: "118.175.93.28", port: 39073}, {ip: "118.175.93.33", port: 47746}, {ip: "118.175.93.38", port: 46691}, {ip: "118.175.93.40", port: 44531}, {ip: "118.175.93.44", port: 45510}, {ip: "118.175.93.49", port: 31712}, {ip: "118.175.93.68", port: 42192}, {ip: "118.175.93.69", port: 52465}, {ip: "118.175.93.7", port: 50577}, {ip: "118.175.93.70", port: 36034}, {ip: "118.175.93.71", port: 44644}, {ip: "118.175.93.73", port: 33782}, {ip: "118.175.93.74", port: 47389}, {ip: "118.175.93.76", port: 46708}, {ip: "118.175.93.79", port: 31900}, {ip: "118.175.93.83", port: 37077}, {ip: "118.175.93.84", port: 45090}, {ip: "118.175.93.86", port: 61465}, {ip: "118.175.93.9", port: 43856}, {ip: "118.175.93.90", port: 30720}, {ip: "118.175.93.91", port: 52509}, {ip: "118.175.93.92", port: 41539}, {ip: "118.175.93.96", port: 51018}, {ip: "118.175.93.98", port: 49750}, {ip: "118.175.93.99", port: 55629}, {ip: "119.46.146.58", port: 8080}, {ip: "119.46.146.58", port: 80}, {ip: "122.154.38.53", port: 8080}, {ip: "122.154.59.6", port: 8080}, {ip: "122.154.72.102", port: 8080}, {ip: "122.155.222.98", port: 3128}, {ip: "124.121.22.121", port: 61699}, {ip: "124.122.8.148", port: 8080}, {ip: "125.24.156.16", port: 44321}, {ip: "125.24.156.233", port: 37387}, {ip: "125.24.156.252", port: 48383}, {ip: "125.25.165.105", port: 33850}, {ip: "125.25.165.109", port: 30484}, {ip: "125.25.165.111", port: 40808}, {ip: "125.25.165.127", port: 33746}, {ip: "125.25.165.21", port: 51288}, {ip: "125.25.165.30", port: 58281}, {ip: "125.25.165.42", port: 47221}, {ip: "125.25.165.47", port: 36114}, {ip: "125.25.201.14", port: 30100}, {ip: "125.25.202.43", port: 3128}, {ip: "125.25.80.31", port: 61845}, {ip: "125.25.80.34", port: 35919}, {ip: "125.25.80.39", port: 32242}, {ip: "125.25.80.44", port: 38211}, {ip: "125.25.80.45", port: 38783}, {ip: "125.25.80.52", port: 53967}, {ip: "125.25.80.54", port: 44346}, {ip: "125.25.80.57", port: 37600}, {ip: "125.25.80.58", port: 61206}, {ip: "125.25.80.64", port: 51868}, {ip: "125.25.80.76", port: 58894}, {ip: "125.25.80.77", port: 41128}, {ip: "125.26.108.12", port: 52088}, {ip: "125.26.108.192", port: 43653}, {ip: "125.26.108.70", port: 57728}, {ip: "125.26.7.120", port: 60515}, {ip: "125.26.99.131", port: 59569}, {ip: "125.26.99.132", port: 41183}, {ip: "125.26.99.135", port: 55637}, {ip: "125.26.99.141", port: 38537}, {ip: "125.26.99.148", port: 31818}, {ip: "125.26.99.150", port: 31172}, {ip: "125.26.99.174", port: 36728}, {ip: "125.26.99.182", port: 59002}, {ip: "125.26.99.185", port: 45828}, {ip: "125.26.99.186", port: 53173}, {ip: "125.26.99.194", port: 37531}, {ip: "125.26.99.200", port: 38092}, {ip: "125.26.99.204", port: 54670}, {ip: "125.26.99.207", port: 47214}, {ip: "125.26.99.223", port: 47578}, {ip: "125.26.99.228", port: 51117}, {ip: "125.26.99.240", port: 38059}, {ip: "125.26.99.249", port: 50478}, {ip: "125.26.99.250", port: 34704}, {ip: "125.27.10.195", port: 38153}, {ip: "125.27.10.218", port: 33666}, {ip: "125.27.10.221", port: 40747}, {ip: "125.27.10.227", port: 51945}, {ip: "125.27.10.230", port: 58537}, {ip: "125.27.10.245", port: 44396}, {ip: "125.27.10.247", port: 54739}, {ip: "125.27.251.164", port: 31684}, {ip: "125.27.251.236", port: 58946}, {ip: "125.27.251.58", port: 30978}, {ip: "125.27.251.97", port: 50096}, {ip: "134.196.244.120", port: 46425}, {ip: "134.196.245.109", port: 36421}, {ip: "134.236.244.75", port: 53058}, {ip: "134.236.245.57", port: 61131}, {ip: "134.236.245.63", port: 21908}, {ip: "134.236.245.76", port: 8080}, {ip: "134.236.247.137", port: 8080}, {ip: "134.236.252.126", port: 8080}, {ip: "14.207.112.77", port: 8080}, {ip: "14.207.32.173", port: 8080}, {ip: "14.207.33.146", port: 3128}, {ip: "14.207.37.131", port: 8080}, {ip: "14.207.76.5", port: 8080}, {ip: "159.192.240.79", port: 8080}, {ip: "159.192.98.224", port: 3128}, {ip: "171.100.102.154", port: 30090}, {ip: "171.100.2.154", port: 8080}, {ip: "171.100.57.134", port: 8080}, {ip: "171.100.9.126", port: 49163}, {ip: "171.4.21.81", port: 8080}, {ip: "171.4.88.131", port: 8080}, {ip: "171.97.149.17", port: 8080}, {ip: "171.98.244.135", port: 8080}, {ip: "180.180.156.116", port: 48431}, {ip: "180.180.156.125", port: 54912}, {ip: "180.180.156.33", port: 44404}, {ip: "180.180.156.46", port: 48507}, {ip: "180.180.156.70", port: 33710}, {ip: "180.180.156.87", port: 36628}, {ip: "180.180.216.196", port: 8080}, {ip: "180.180.218.204", port: 51565}, {ip: "180.180.8.34", port: 8080}, {ip: "180.183.101.134", port: 8080}, {ip: "180.183.129.250", port: 8080}, {ip: "180.183.135.186", port: 8080}, {ip: "180.183.17.148", port: 8080}, {ip: "180.183.215.152", port: 8080}, {ip: "180.183.224.243", port: 8080}, {ip: "180.183.8.165", port: 8080}, {ip: "182.52.132.43", port: 30756}, {ip: "182.52.134.118", port: 37636}, {ip: "182.52.134.122", port: 44571}, {ip: "182.52.134.123", port: 36287}, {ip: "182.52.134.59", port: 32279}, {ip: "182.52.134.80", port: 31274}, {ip: "182.52.134.88", port: 53038}, {ip: "182.52.134.94", port: 37618}, {ip: "182.52.238.122", port: 50463}, {ip: "182.52.238.125", port: 58861}, {ip: "182.52.238.52", port: 37919}, {ip: "182.52.31.121", port: 47346}, {ip: "182.52.74.52", port: 44584}, {ip: "182.52.74.53", port: 37738}, {ip: "182.52.74.73", port: 36286}, {ip: "182.52.74.76", port: 34084}, {ip: "182.52.74.77", port: 34825}, {ip: "182.52.74.78", port: 48708}, {ip: "182.52.87.107", port: 48779}, {ip: "182.52.87.142", port: 57184}, {ip: "182.52.87.190", port: 48300}, {ip: "182.52.87.191", port: 49981}, {ip: "182.52.90.118", port: 53050}, {ip: "182.52.90.45", port: 53799}, {ip: "182.52.90.76", port: 38018}, {ip: "182.53.206.138", port: 45794}, {ip: "182.53.206.15", port: 30973}, {ip: "182.53.206.155", port: 34307}, {ip: "182.53.206.163", port: 39426}, {ip: "182.53.206.23", port: 60977}, {ip: "182.53.206.26", port: 57543}, {ip: "182.53.206.43", port: 45330}, {ip: "182.53.206.44", port: 33362}, {ip: "182.53.206.47", port: 54158}, {ip: "182.53.206.49", port: 54228}, {ip: "183.88.192.46", port: 8080}, {ip: "183.88.212.141", port: 8080}, {ip: "183.88.212.184", port: 8080}, {ip: "183.88.213.85", port: 8080}, {ip: "183.88.214.47", port: 8080}, {ip: "183.88.217.214", port: 8080}, {ip: "183.88.221.20", port: 8080}, {ip: "183.88.230.130", port: 8080}, {ip: "183.88.232.204", port: 8080}, {ip: "183.88.237.226", port: 8080}, {ip: "183.88.42.222", port: 8080}, {ip: "183.89.161.197", port: 8080}, {ip: "183.89.184.70", port: 8080}, {ip: "183.89.203.141", port: 8080}, {ip: "183.89.209.33", port: 8080}, {ip: "183.89.213.26", port: 8080}, {ip: "183.89.52.127", port: 8080}, {ip: "183.89.6.166", port: 8080}, {ip: "183.89.72.153", port: 8080}, {ip: "184.82.128.211", port: 8080}, {ip: "202.183.201.13", port: 8081}, {ip: "202.29.20.151", port: 43083}, {ip: "202.29.210.166", port: 41219}, {ip: "202.29.217.218", port: 8080}, {ip: "202.29.237.250", port: 80}, {ip: "202.29.243.98", port: 59534}, {ip: "203.113.119.226", port: 49360}, {ip: "203.150.172.151", port: 8080}, {ip: "203.154.82.29", port: 8080}, {ip: "203.170.129.56", port: 3128}, {ip: "203.170.146.146", port: 8080}, {ip: "203.170.146.146", port: 80}, {ip: "27.131.157.90", port: 8080}, {ip: "27.131.157.94", port: 8080}, {ip: "27.145.100.22", port: 8080}, {ip: "27.145.100.243", port: 8080}, {ip: "43.254.132.86", port: 48833}, {ip: "49.0.118.39", port: 8080}, {ip: "49.231.196.114", port: 53281}, {ip: "58.9.118.95", port: 34528}, {ip: "58.97.116.195", port: 56056}, {ip: "58.97.72.83", port: 8080}, {ip: "61.19.145.66", port: 8080}, {ip: "61.7.138.211", port: 8080}, {ip: "61.91.189.162", port: 8080}, {ip: "61.91.79.40", port: 54394}], - "ES" => [{ip: "109.167.113.9", port: 47803}, {ip: "109.167.49.27", port: 40349}, {ip: "151.237.132.42", port: 33371}, {ip: "176.56.66.84", port: 44669}, {ip: "176.56.71.211", port: 60751}, {ip: "176.56.93.123", port: 61823}, {ip: "185.13.76.214", port: 52488}, {ip: "185.152.12.42", port: 33364}, {ip: "185.154.1.167", port: 55127}, {ip: "185.160.230.35", port: 51653}, {ip: "185.163.165.130", port: 53281}, {ip: "185.163.165.49", port: 59575}, {ip: "185.177.43.254", port: 53281}, {ip: "185.177.74.179", port: 3128}, {ip: "185.177.74.216", port: 8080}, {ip: "185.178.83.111", port: 52663}, {ip: "185.183.17.63", port: 36682}, {ip: "185.190.103.159", port: 34206}, {ip: "185.192.180.156", port: 33499}, {ip: "185.192.183.221", port: 41830}, {ip: "185.196.115.252", port: 36063}, {ip: "185.198.184.14", port: 48122}, {ip: "185.212.126.187", port: 44996}, {ip: "185.213.48.231", port: 58654}, {ip: "185.221.189.95", port: 43653}, {ip: "185.221.190.124", port: 48472}, {ip: "185.225.150.28", port: 46798}, {ip: "185.226.230.54", port: 58593}, {ip: "185.232.133.157", port: 56670}, {ip: "185.26.226.241", port: 36012}, {ip: "185.37.213.76", port: 30695}, {ip: "185.44.27.130", port: 46251}, {ip: "188.165.132.181", port: 3128}, {ip: "194.149.222.107", port: 45930}, {ip: "194.224.156.90", port: 3128}, {ip: "194.224.188.82", port: 3128}, {ip: "194.224.197.171", port: 3128}, {ip: "195.235.202.130", port: 3128}, {ip: "195.235.68.61", port: 3128}, {ip: "195.53.237.122", port: 3128}, {ip: "195.53.49.42", port: 3128}, {ip: "195.53.86.82", port: 3128}, {ip: "195.55.240.168", port: 23500}, {ip: "195.77.80.154", port: 42402}, {ip: "2.139.195.2", port: 35235}, {ip: "212.145.30.226", port: 49524}, {ip: "212.170.217.170", port: 3128}, {ip: "212.170.59.132", port: 3128}, {ip: "212.230.130.221", port: 49698}, {ip: "213.0.109.218", port: 3128}, {ip: "213.162.218.75", port: 55230}, {ip: "213.96.245.47", port: 8080}, {ip: "217.125.71.214", port: 33950}, {ip: "217.126.203.104", port: 40646}, {ip: "5.154.13.11", port: 23500}, {ip: "62.14.178.3", port: 53590}, {ip: "62.14.178.72", port: 53281}, {ip: "62.82.84.17", port: 42312}, {ip: "62.99.67.216", port: 8080}, {ip: "77.225.0.106", port: 51655}, {ip: "77.241.123.200", port: 53281}, {ip: "79.148.233.173", port: 61272}, {ip: "80.25.19.165", port: 3128}, {ip: "80.26.152.146", port: 60133}, {ip: "80.28.148.111", port: 3128}, {ip: "80.28.7.3", port: 50866}, {ip: "80.32.132.176", port: 3128}, {ip: "80.35.23.103", port: 55082}, {ip: "80.35.254.42", port: 53281}, {ip: "81.33.4.214", port: 61711}, {ip: "81.36.102.109", port: 8080}, {ip: "83.175.238.170", port: 53281}, {ip: "83.213.14.157", port: 60577}, {ip: "83.47.251.143", port: 8080}, {ip: "83.56.43.218", port: 58778}, {ip: "83.61.18.250", port: 58651}, {ip: "84.236.185.247", port: 46601}, {ip: "85.217.137.77", port: 3128}, {ip: "87.124.164.34", port: 46678}, {ip: "88.2.42.95", port: 52544}, {ip: "89.140.169.24", port: 37839}, {ip: "90.160.46.120", port: 52980}, {ip: "90.170.205.178", port: 33680}, {ip: "91.126.64.19", port: 8888}, {ip: "91.126.65.166", port: 8080}, {ip: "91.235.51.252", port: 53281}, {ip: "93.156.177.91", port: 53281}, {ip: "95.60.152.139", port: 37995}], - "AE" => [{ip: "178.32.5.90", port: 36159}, {ip: "54.36.39.20", port: 8080}, {ip: "91.121.253.113", port: 3128}, {ip: "94.130.92.40", port: 3128}, {ip: "94.130.92.60", port: 3128}], - "KR" => [{ip: "1.215.70.130", port: 30634}, {ip: "112.175.32.88", port: 8080}, {ip: "112.217.199.122", port: 45660}, {ip: "112.217.219.179", port: 3128}, {ip: "114.141.229.2", port: 58115}, {ip: "121.139.218.165", port: 31409}, {ip: "121.179.209.198", port: 30880}, {ip: "122.49.112.2", port: 38592}, {ip: "221.141.130.183", port: 33741}, {ip: "222.105.7.169", port: 47878}, {ip: "222.121.116.26", port: 33310}, {ip: "27.111.100.164", port: 49598}, {ip: "52.78.62.182", port: 3128}, {ip: "52.79.116.117", port: 3128}, {ip: "52.79.239.229", port: 3128}, {ip: "59.11.209.131", port: 8088}, {ip: "61.42.18.132", port: 53281}], - "IR" => [{ip: "109.95.71.253", port: 32231}, {ip: "178.239.147.131", port: 56133}, {ip: "2.179.67.8", port: 8080}, {ip: "217.219.25.19", port: 8080}, {ip: "46.100.58.6", port: 8080}, {ip: "46.225.234.115", port: 23500}, {ip: "5.160.90.91", port: 3128}, {ip: "91.92.186.23", port: 47950}, {ip: "91.92.208.182", port: 45214}, {ip: "91.98.158.182", port: 3128}, {ip: "92.242.208.166", port: 8080}], - "BR" => [{ip: "128.201.92.105", port: 53281}, {ip: "128.201.92.25", port: 53281}, {ip: "128.201.92.30", port: 53281}, {ip: "128.201.97.155", port: 53281}, {ip: "128.201.97.157", port: 53281}, {ip: "128.201.97.158", port: 53281}, {ip: "131.0.246.157", port: 35252}, {ip: "131.0.62.196", port: 8080}, {ip: "131.0.62.224", port: 8080}, {ip: "131.0.62.81", port: 8080}, {ip: "131.100.135.165", port: 47400}, {ip: "131.108.216.44", port: 45749}, {ip: "131.108.62.6", port: 59980}, {ip: "131.161.13.223", port: 3128}, {ip: "131.161.26.124", port: 8080}, {ip: "131.161.26.90", port: 8080}, {ip: "131.161.48.199", port: 31048}, {ip: "131.161.67.70", port: 55087}, {ip: "131.221.105.18", port: 57903}, {ip: "131.221.48.36", port: 8080}, {ip: "131.221.49.80", port: 41985}, {ip: "131.255.33.25", port: 36922}, {ip: "131.255.83.38", port: 53281}, {ip: "131.72.140.70", port: 3128}, {ip: "131.72.143.100", port: 41396}, {ip: "131.72.143.105", port: 41396}, {ip: "131.72.172.29", port: 8080}, {ip: "131.72.68.210", port: 40635}, {ip: "132.255.148.98", port: 38858}, {ip: "132.255.170.41", port: 57243}, {ip: "132.255.92.51", port: 31879}, {ip: "138.0.173.186", port: 49491}, {ip: "138.0.204.54", port: 92}, {ip: "138.0.208.26", port: 34172}, {ip: "138.0.24.66", port: 53281}, {ip: "138.0.53.98", port: 38365}, {ip: "138.117.176.10", port: 46355}, {ip: "138.118.224.49", port: 54626}, {ip: "138.121.130.50", port: 50600}, {ip: "138.121.155.127", port: 61932}, {ip: "138.121.32.133", port: 23492}, {ip: "138.121.32.26", port: 23500}, {ip: "138.121.32.44", port: 12955}, {ip: "138.122.171.190", port: 53281}, {ip: "138.122.51.68", port: 49659}, {ip: "138.185.176.63", port: 53281}, {ip: "138.185.60.239", port: 33388}, {ip: "138.185.9.37", port: 44717}, {ip: "138.185.9.40", port: 44717}, {ip: "138.186.222.46", port: 34894}, {ip: "138.204.179.50", port: 35410}, {ip: "138.204.186.33", port: 47639}, {ip: "138.204.233.190", port: 53281}, {ip: "138.204.233.198", port: 59813}, {ip: "138.204.233.242", port: 53281}, {ip: "138.219.139.69", port: 43908}, {ip: "138.219.32.100", port: 3128}, {ip: "138.219.71.74", port: 52688}, {ip: "138.255.1.22", port: 23500}, {ip: "138.255.15.155", port: 40018}, {ip: "138.36.1.67", port: 50847}, {ip: "138.36.106.24", port: 60812}, {ip: "138.36.107.24", port: 41184}, {ip: "138.36.200.28", port: 40072}, {ip: "138.59.33.43", port: 51706}, {ip: "138.94.115.166", port: 8080}, {ip: "138.94.71.202", port: 8080}, {ip: "138.94.73.14", port: 54829}, {ip: "138.97.12.137", port: 52067}, {ip: "138.97.12.150", port: 49838}, {ip: "138.97.145.112", port: 46484}, {ip: "138.97.146.101", port: 54551}, {ip: "138.97.146.208", port: 47686}, {ip: "138.97.146.218", port: 49684}, {ip: "138.97.146.235", port: 52366}, {ip: "138.97.146.63", port: 55576}, {ip: "138.97.147.168", port: 46665}, {ip: "138.97.147.201", port: 51903}, {ip: "138.97.235.236", port: 38517}, {ip: "143.0.140.62", port: 3128}, {ip: "143.0.176.108", port: 60521}, {ip: "143.0.188.161", port: 53281}, {ip: "143.0.189.89", port: 53281}, {ip: "143.202.0.192", port: 52537}, {ip: "143.202.218.135", port: 8080}, {ip: "143.208.144.117", port: 36977}, {ip: "143.208.2.42", port: 53281}, {ip: "143.208.29.6", port: 8080}, {ip: "143.208.79.223", port: 8080}, {ip: "143.255.109.82", port: 57902}, {ip: "143.255.52.102", port: 40687}, {ip: "143.255.52.116", port: 57856}, {ip: "143.255.52.117", port: 37279}, {ip: "144.217.22.128", port: 8080}, {ip: "152.237.216.240", port: 8080}, {ip: "164.163.250.22", port: 56301}, {ip: "167.249.150.248", port: 23500}, {ip: "167.250.19.12", port: 53281}, {ip: "168.0.155.133", port: 48280}, {ip: "168.0.8.225", port: 8080}, {ip: "168.0.8.55", port: 8080}, {ip: "168.121.107.46", port: 32990}, {ip: "168.121.139.54", port: 40056}, {ip: "168.121.43.214", port: 3128}, {ip: "168.121.6.11", port: 51883}, {ip: "168.181.110.74", port: 57621}, {ip: "168.181.143.131", port: 38972}, {ip: "168.181.168.23", port: 53281}, {ip: "168.181.170.198", port: 31935}, {ip: "168.181.61.154", port: 45528}, {ip: "168.194.14.16", port: 23500}, {ip: "168.194.14.54", port: 23500}, {ip: "168.195.196.138", port: 37328}, {ip: "168.196.100.5", port: 51700}, {ip: "168.197.113.30", port: 59052}, {ip: "168.197.114.42", port: 37145}, {ip: "168.197.114.68", port: 32641}, {ip: "168.197.14.218", port: 60576}, {ip: "168.197.14.225", port: 60576}, {ip: "168.197.155.91", port: 23500}, {ip: "168.205.24.3", port: 53281}, {ip: "168.227.54.10", port: 8080}, {ip: "168.228.20.129", port: 38675}, {ip: "168.228.20.14", port: 38675}, {ip: "168.228.220.236", port: 47955}, {ip: "168.232.151.180", port: 8080}, {ip: "168.232.196.18", port: 42547}, {ip: "168.232.198.25", port: 32009}, {ip: "168.232.198.35", port: 42267}, {ip: "168.232.198.36", port: 59158}, {ip: "168.232.198.66", port: 32429}, {ip: "168.232.198.67", port: 58497}, {ip: "168.232.198.70", port: 32673}, {ip: "168.232.198.78", port: 37664}, {ip: "168.232.204.11", port: 32286}, {ip: "168.232.207.145", port: 46342}, {ip: "168.90.144.114", port: 8080}, {ip: "168.90.144.121", port: 8080}, {ip: "168.90.50.118", port: 51002}, {ip: "168.90.88.35", port: 59591}, {ip: "170.0.104.107", port: 60337}, {ip: "170.0.112.2", port: 50359}, {ip: "170.0.112.224", port: 50359}, {ip: "170.0.112.229", port: 50359}, {ip: "170.233.43.97", port: 43973}, {ip: "170.233.48.10", port: 53281}, {ip: "170.238.118.107", port: 34314}, {ip: "170.238.120.130", port: 8080}, {ip: "170.238.120.131", port: 8080}, {ip: "170.238.120.132", port: 8080}, {ip: "170.238.120.133", port: 8080}, {ip: "170.239.144.9", port: 3128}, {ip: "170.239.158.97", port: 36027}, {ip: "170.239.224.207", port: 20183}, {ip: "170.239.46.145", port: 41823}, {ip: "170.244.105.129", port: 53281}, {ip: "170.244.164.147", port: 60182}, {ip: "170.244.172.145", port: 8080}, {ip: "170.244.172.147", port: 8080}, {ip: "170.244.172.18", port: 58671}, {ip: "170.247.200.155", port: 58654}, {ip: "170.247.29.138", port: 8080}, {ip: "170.247.31.159", port: 55694}, {ip: "170.78.199.10", port: 3128}, {ip: "170.78.7.162", port: 8080}, {ip: "170.79.176.91", port: 50839}, {ip: "170.79.177.14", port: 49368}, {ip: "170.79.177.58", port: 43257}, {ip: "170.80.146.2", port: 53281}, {ip: "170.80.184.110", port: 40891}, {ip: "170.80.184.93", port: 50838}, {ip: "170.80.36.17", port: 50952}, {ip: "170.81.237.32", port: 49723}, {ip: "170.81.237.36", port: 37124}, {ip: "170.81.247.4", port: 3128}, {ip: "170.82.126.197", port: 31641}, {ip: "170.82.180.134", port: 41775}, {ip: "170.82.182.58", port: 35688}, {ip: "170.82.22.168", port: 53281}, {ip: "170.82.22.41", port: 53281}, {ip: "170.82.231.26", port: 50501}, {ip: "170.82.4.217", port: 47920}, {ip: "170.84.104.20", port: 23500}, {ip: "170.84.158.24", port: 55987}, {ip: "170.84.51.74", port: 53281}, {ip: "170.84.60.222", port: 42981}, {ip: "170.84.93.114", port: 42533}, {ip: "177.1.25.242", port: 8080}, {ip: "177.1.74.195", port: 47324}, {ip: "177.10.142.10", port: 44779}, {ip: "177.10.197.133", port: 37380}, {ip: "177.10.202.67", port: 8080}, {ip: "177.10.21.154", port: 8080}, {ip: "177.101.139.208", port: 8080}, {ip: "177.101.60.86", port: 80}, {ip: "177.103.231.211", port: 55091}, {ip: "177.103.231.85", port: 36997}, {ip: "177.105.236.45", port: 30005}, {ip: "177.107.169.110", port: 3128}, {ip: "177.11.139.180", port: 49933}, {ip: "177.11.139.74", port: 48385}, {ip: "177.11.140.1", port: 44827}, {ip: "177.11.140.147", port: 56034}, {ip: "177.11.140.181", port: 39726}, {ip: "177.11.140.99", port: 39615}, {ip: "177.12.2.208", port: 3128}, {ip: "177.12.80.50", port: 50556}, {ip: "177.124.72.155", port: 54666}, {ip: "177.124.74.170", port: 23500}, {ip: "177.125.25.62", port: 34951}, {ip: "177.125.43.18", port: 8080}, {ip: "177.126.104.50", port: 20183}, {ip: "177.126.119.90", port: 37005}, {ip: "177.126.81.63", port: 20183}, {ip: "177.126.89.230", port: 20183}, {ip: "177.129.11.35", port: 8080}, {ip: "177.129.17.171", port: 41378}, {ip: "177.129.17.50", port: 8080}, {ip: "177.129.228.160", port: 30257}, {ip: "177.129.248.131", port: 49253}, {ip: "177.130.243.147", port: 40931}, {ip: "177.130.57.222", port: 52958}, {ip: "177.130.59.121", port: 36354}, {ip: "177.130.59.42", port: 36354}, {ip: "177.131.12.251", port: 60829}, {ip: "177.131.121.109", port: 32048}, {ip: "177.131.13.9", port: 20183}, {ip: "177.135.178.115", port: 42510}, {ip: "177.135.248.75", port: 20183}, {ip: "177.136.172.246", port: 8080}, {ip: "177.136.252.7", port: 3128}, {ip: "177.137.192.226", port: 50384}, {ip: "177.137.228.126", port: 52552}, {ip: "177.139.202.179", port: 23500}, {ip: "177.139.212.80", port: 61378}, {ip: "177.139.219.160", port: 53281}, {ip: "177.152.159.139", port: 53281}, {ip: "177.152.187.218", port: 34641}, {ip: "177.155.84.158", port: 38102}, {ip: "177.158.248.172", port: 8080}, {ip: "177.184.128.3", port: 8080}, {ip: "177.184.136.121", port: 8080}, {ip: "177.184.206.238", port: 39508}, {ip: "177.185.114.89", port: 53281}, {ip: "177.185.148.46", port: 58623}, {ip: "177.185.160.22", port: 42122}, {ip: "177.185.169.15", port: 39011}, {ip: "177.185.20.1", port: 35173}, {ip: "177.185.20.9", port: 52197}, {ip: "177.185.220.9", port: 21776}, {ip: "177.19.208.165", port: 53281}, {ip: "177.190.147.241", port: 41545}, {ip: "177.190.218.30", port: 46483}, {ip: "177.200.2.35", port: 47846}, {ip: "177.200.72.214", port: 20183}, {ip: "177.200.83.218", port: 53910}, {ip: "177.200.83.238", port: 8080}, {ip: "177.202.63.2", port: 20183}, {ip: "177.204.18.83", port: 8080}, {ip: "177.204.85.203", port: 80}, {ip: "177.21.103.86", port: 20183}, {ip: "177.21.13.206", port: 58627}, {ip: "177.21.24.146", port: 666}, {ip: "177.220.151.102", port: 44455}, {ip: "177.220.188.120", port: 47556}, {ip: "177.220.188.213", port: 8080}, {ip: "177.220.243.114", port: 20183}, {ip: "177.220.243.116", port: 20183}, {ip: "177.221.16.29", port: 3128}, {ip: "177.221.176.73", port: 43523}, {ip: "177.221.176.76", port: 59142}, {ip: "177.222.229.243", port: 23500}, {ip: "177.223.51.130", port: 23500}, {ip: "177.223.58.246", port: 23500}, {ip: "177.23.104.38", port: 36197}, {ip: "177.23.138.118", port: 8080}, {ip: "177.234.161.42", port: 8080}, {ip: "177.234.178.103", port: 51609}, {ip: "177.36.11.241", port: 3128}, {ip: "177.36.12.193", port: 23500}, {ip: "177.36.201.69", port: 60570}, {ip: "177.37.199.175", port: 49608}, {ip: "177.37.65.204", port: 3128}, {ip: "177.38.160.58", port: 46296}, {ip: "177.38.195.69", port: 8080}, {ip: "177.38.20.152", port: 8080}, {ip: "177.38.232.40", port: 55789}, {ip: "177.38.66.255", port: 44963}, {ip: "177.39.102.138", port: 46381}, {ip: "177.39.187.70", port: 37315}, {ip: "177.44.134.246", port: 32783}, {ip: "177.44.135.166", port: 20183}, {ip: "177.44.175.199", port: 8080}, {ip: "177.44.183.169", port: 32581}, {ip: "177.46.148.126", port: 3128}, {ip: "177.46.148.142", port: 3128}, {ip: "177.47.194.98", port: 21231}, {ip: "177.47.225.251", port: 39150}, {ip: "177.5.98.58", port: 20183}, {ip: "177.52.44.253", port: 34943}, {ip: "177.52.44.9", port: 34943}, {ip: "177.52.55.19", port: 60901}, {ip: "177.53.134.85", port: 32184}, {ip: "177.53.15.163", port: 49848}, {ip: "177.53.218.235", port: 8080}, {ip: "177.53.56.127", port: 49284}, {ip: "177.53.57.154", port: 49186}, {ip: "177.53.7.12", port: 56305}, {ip: "177.53.7.42", port: 50691}, {ip: "177.53.7.53", port: 33347}, {ip: "177.54.142.70", port: 29815}, {ip: "177.54.200.66", port: 57526}, {ip: "177.55.237.28", port: 8080}, {ip: "177.55.255.74", port: 37147}, {ip: "177.55.62.36", port: 8080}, {ip: "177.66.118.50", port: 8080}, {ip: "177.66.255.140", port: 37746}, {ip: "177.66.52.103", port: 57053}, {ip: "177.66.52.106", port: 39275}, {ip: "177.66.52.108", port: 57615}, {ip: "177.66.52.195", port: 40179}, {ip: "177.66.52.213", port: 50389}, {ip: "177.66.52.99", port: 38126}, {ip: "177.66.53.111", port: 35414}, {ip: "177.66.53.115", port: 38571}, {ip: "177.66.53.116", port: 48059}, {ip: "177.66.53.154", port: 42762}, {ip: "177.66.53.207", port: 48147}, {ip: "177.66.53.227", port: 36003}, {ip: "177.66.53.238", port: 48587}, {ip: "177.66.53.244", port: 35599}, {ip: "177.66.53.245", port: 30647}, {ip: "177.66.54.122", port: 50815}, {ip: "177.67.143.177", port: 57155}, {ip: "177.67.143.183", port: 49322}, {ip: "177.67.143.207", port: 36288}, {ip: "177.67.217.94", port: 53281}, {ip: "177.67.80.154", port: 3128}, {ip: "177.69.23.14", port: 36262}, {ip: "177.70.153.177", port: 20183}, {ip: "177.71.77.202", port: 20183}, {ip: "177.72.164.163", port: 23500}, {ip: "177.72.164.165", port: 23500}, {ip: "177.72.92.24", port: 23500}, {ip: "177.73.160.18", port: 35024}, {ip: "177.73.248.6", port: 54381}, {ip: "177.73.4.234", port: 23500}, {ip: "177.74.146.192", port: 57249}, {ip: "177.75.143.211", port: 35955}, {ip: "177.75.161.191", port: 33279}, {ip: "177.75.161.206", port: 3128}, {ip: "177.75.30.154", port: 20183}, {ip: "177.75.86.49", port: 20183}, {ip: "177.8.163.190", port: 32675}, {ip: "177.8.216.106", port: 8080}, {ip: "177.8.216.114", port: 8080}, {ip: "177.8.37.247", port: 56052}, {ip: "177.84.114.21", port: 53281}, {ip: "177.84.120.147", port: 53281}, {ip: "177.84.120.202", port: 57814}, {ip: "177.84.140.141", port: 43711}, {ip: "177.84.147.118", port: 51311}, {ip: "177.84.216.17", port: 50569}, {ip: "177.84.63.150", port: 38718}, {ip: "177.84.63.161", port: 44608}, {ip: "177.84.63.50", port: 61604}, {ip: "177.84.63.60", port: 60014}, {ip: "177.85.113.45", port: 36173}, {ip: "177.85.200.254", port: 53095}, {ip: "177.85.74.243", port: 58493}, {ip: "177.85.90.124", port: 49027}, {ip: "177.85.90.95", port: 23500}, {ip: "177.86.0.156", port: 8080}, {ip: "177.86.126.194", port: 44776}, {ip: "177.86.158.168", port: 8080}, {ip: "177.86.166.23", port: 8080}, {ip: "177.86.233.41", port: 54502}, {ip: "177.86.39.62", port: 50630}, {ip: "177.87.10.166", port: 8081}, {ip: "177.87.158.180", port: 45456}, {ip: "177.87.168.102", port: 46580}, {ip: "177.87.169.1", port: 53281}, {ip: "177.87.217.145", port: 32006}, {ip: "177.87.40.156", port: 39470}, {ip: "177.87.41.176", port: 47401}, {ip: "177.91.127.32", port: 53755}, {ip: "177.91.127.63", port: 61684}, {ip: "177.91.127.67", port: 42850}, {ip: "177.92.143.146", port: 58545}, {ip: "177.92.143.218", port: 32094}, {ip: "177.92.17.186", port: 23500}, {ip: "177.92.19.38", port: 3128}, {ip: "177.92.24.118", port: 20183}, {ip: "177.92.249.112", port: 47920}, {ip: "177.92.5.182", port: 8080}, {ip: "177.94.212.215", port: 32231}, {ip: "177.94.240.197", port: 32809}, {ip: "177.99.207.243", port: 60875}, {ip: "179.106.150.31", port: 57952}, {ip: "179.106.168.37", port: 43345}, {ip: "179.107.97.178", port: 3128}, {ip: "179.108.249.226", port: 54460}, {ip: "179.109.144.16", port: 60254}, {ip: "179.109.144.25", port: 8080}, {ip: "179.109.193.137", port: 53281}, {ip: "179.109.193.155", port: 53281}, {ip: "179.111.242.56", port: 3128}, {ip: "179.124.11.128", port: 58092}, {ip: "179.124.240.199", port: 45868}, {ip: "179.124.240.210", port: 56869}, {ip: "179.124.242.34", port: 41886}, {ip: "179.125.168.50", port: 30139}, {ip: "179.127.140.188", port: 20183}, {ip: "179.127.242.42", port: 54235}, {ip: "179.127.242.44", port: 41300}, {ip: "179.127.242.95", port: 50621}, {ip: "179.127.243.3", port: 33759}, {ip: "179.184.219.227", port: 45832}, {ip: "179.185.22.211", port: 31274}, {ip: "179.185.35.183", port: 57332}, {ip: "179.185.4.1", port: 39430}, {ip: "179.189.125.206", port: 8080}, {ip: "179.189.248.182", port: 3128}, {ip: "179.189.31.9", port: 56740}, {ip: "179.191.245.156", port: 3128}, {ip: "179.218.45.201", port: 3128}, {ip: "179.222.227.150", port: 50768}, {ip: "179.223.235.246", port: 3128}, {ip: "179.228.102.228", port: 61798}, {ip: "179.228.165.76", port: 46118}, {ip: "179.228.189.67", port: 45145}, {ip: "179.252.22.210", port: 8080}, {ip: "179.83.128.48", port: 60172}, {ip: "179.96.18.170", port: 44950}, {ip: "179.97.30.46", port: 53100}, {ip: "179.97.40.26", port: 31937}, {ip: "179.97.95.14", port: 23500}, {ip: "181.191.216.1", port: 53281}, {ip: "181.191.216.13", port: 53281}, {ip: "181.213.38.165", port: 58227}, {ip: "181.222.88.166", port: 30324}, {ip: "181.223.169.126", port: 53281}, {ip: "181.223.188.142", port: 32428}, {ip: "186.192.195.220", port: 38983}, {ip: "186.193.11.226", port: 48999}, {ip: "186.193.136.100", port: 8080}, {ip: "186.193.23.17", port: 3128}, {ip: "186.193.26.106", port: 3128}, {ip: "186.195.225.221", port: 50203}, {ip: "186.195.82.41", port: 80}, {ip: "186.201.15.133", port: 38616}, {ip: "186.208.220.248", port: 3128}, {ip: "186.208.231.28", port: 34944}, {ip: "186.208.98.101", port: 43396}, {ip: "186.209.243.142", port: 3128}, {ip: "186.209.243.233", port: 3128}, {ip: "186.211.100.138", port: 8080}, {ip: "186.211.106.227", port: 34334}, {ip: "186.211.110.157", port: 54934}, {ip: "186.211.160.178", port: 36756}, {ip: "186.215.133.170", port: 20183}, {ip: "186.215.199.245", port: 20183}, {ip: "186.216.81.21", port: 31773}, {ip: "186.219.106.4", port: 8080}, {ip: "186.219.214.10", port: 32708}, {ip: "186.219.214.13", port: 32708}, {ip: "186.220.18.154", port: 45857}, {ip: "186.224.238.109", port: 20183}, {ip: "186.224.94.6", port: 48957}, {ip: "186.225.182.51", port: 53281}, {ip: "186.225.84.229", port: 53281}, {ip: "186.225.97.246", port: 43082}, {ip: "186.226.169.101", port: 23500}, {ip: "186.226.171.163", port: 48698}, {ip: "186.226.172.12", port: 23500}, {ip: "186.226.179.2", port: 56089}, {ip: "186.226.234.67", port: 33834}, {ip: "186.227.65.2", port: 42301}, {ip: "186.228.147.58", port: 20183}, {ip: "186.232.44.50", port: 53281}, {ip: "186.232.65.24", port: 31179}, {ip: "186.233.177.150", port: 8080}, {ip: "186.233.199.154", port: 53179}, {ip: "186.233.220.150", port: 3128}, {ip: "186.233.97.163", port: 44199}, {ip: "186.233.97.163", port: 8888}, {ip: "186.233.98.198", port: 53281}, {ip: "186.235.64.136", port: 60626}, {ip: "186.236.237.243", port: 33284}, {ip: "186.236.237.49", port: 33046}, {ip: "186.237.161.250", port: 42140}, {ip: "186.237.219.94", port: 36147}, {ip: "186.248.146.51", port: 3128}, {ip: "186.248.151.10", port: 36526}, {ip: "186.248.166.41", port: 45751}, {ip: "186.248.170.82", port: 53281}, {ip: "186.249.20.105", port: 44057}, {ip: "186.249.213.101", port: 53482}, {ip: "186.249.213.106", port: 49359}, {ip: "186.249.213.65", port: 52018}, {ip: "186.249.213.95", port: 40324}, {ip: "186.249.215.108", port: 8888}, {ip: "186.249.215.241", port: 54594}, {ip: "186.250.118.17", port: 59428}, {ip: "186.250.176.129", port: 60057}, {ip: "186.250.176.149", port: 56206}, {ip: "186.250.213.225", port: 60774}, {ip: "186.250.49.82", port: 43027}, {ip: "186.250.96.70", port: 8080}, {ip: "186.250.96.77", port: 8080}, {ip: "187.0.171.206", port: 46297}, {ip: "187.0.174.237", port: 46297}, {ip: "187.1.43.246", port: 53396}, {ip: "187.1.57.206", port: 20183}, {ip: "187.1.57.54", port: 3128}, {ip: "187.103.67.161", port: 8080}, {ip: "187.107.199.86", port: 60346}, {ip: "187.108.18.244", port: 20183}, {ip: "187.108.34.58", port: 20183}, {ip: "187.108.36.250", port: 20183}, {ip: "187.108.38.10", port: 20183}, {ip: "187.109.117.51", port: 49547}, {ip: "187.109.119.116", port: 60188}, {ip: "187.109.121.38", port: 51180}, {ip: "187.109.122.178", port: 31249}, {ip: "187.109.122.58", port: 34756}, {ip: "187.109.208.82", port: 20183}, {ip: "187.109.231.19", port: 44913}, {ip: "187.109.234.18", port: 54885}, {ip: "187.109.36.251", port: 20183}, {ip: "187.109.40.193", port: 20183}, {ip: "187.109.40.21", port: 20183}, {ip: "187.109.40.9", port: 20183}, {ip: "187.109.56.101", port: 20183}, {ip: "187.109.63.146", port: 20183}, {ip: "187.11.238.230", port: 47003}, {ip: "187.110.134.1", port: 20183}, {ip: "187.110.134.160", port: 20183}, {ip: "187.110.93.120", port: 20183}, {ip: "187.111.160.8", port: 30906}, {ip: "187.111.192.54", port: 39034}, {ip: "187.111.90.89", port: 53281}, {ip: "187.115.10.50", port: 20183}, {ip: "187.115.153.197", port: 53281}, {ip: "187.120.137.34", port: 61708}, {ip: "187.120.243.27", port: 59754}, {ip: "187.121.184.222", port: 20183}, {ip: "187.122.189.108", port: 8080}, {ip: "187.122.224.69", port: 46770}, {ip: "187.125.23.26", port: 8080}, {ip: "187.18.113.159", port: 20183}, {ip: "187.18.125.34", port: 3128}, {ip: "187.18.204.176", port: 3128}, {ip: "187.181.220.153", port: 8080}, {ip: "187.181.9.224", port: 35853}, {ip: "187.19.150.34", port: 33245}, {ip: "187.19.199.10", port: 36178}, {ip: "187.19.62.7", port: 59010}, {ip: "187.21.242.156", port: 8080}, {ip: "187.23.65.128", port: 8080}, {ip: "187.28.39.147", port: 8080}, {ip: "187.28.39.158", port: 8080}, {ip: "187.32.111.85", port: 20183}, {ip: "187.32.111.87", port: 20183}, {ip: "187.32.241.205", port: 59048}, {ip: "187.32.88.190", port: 30314}, {ip: "187.32.88.30", port: 20183}, {ip: "187.33.245.5", port: 56856}, {ip: "187.33.79.61", port: 33469}, {ip: "187.35.158.150", port: 38872}, {ip: "187.4.74.50", port: 50772}, {ip: "187.44.1.167", port: 8080}, {ip: "187.44.145.162", port: 47686}, {ip: "187.44.146.114", port: 33120}, {ip: "187.44.5.3", port: 41689}, {ip: "187.45.100.138", port: 30645}, {ip: "187.45.123.167", port: 3128}, {ip: "187.45.127.87", port: 20183}, {ip: "187.45.156.108", port: 8080}, {ip: "187.45.156.109", port: 8080}, {ip: "187.5.218.215", port: 20183}, {ip: "187.58.65.225", port: 3128}, {ip: "187.59.7.30", port: 47532}, {ip: "187.60.254.18", port: 36127}, {ip: "187.60.43.186", port: 8080}, {ip: "187.62.205.152", port: 58975}, {ip: "187.62.205.224", port: 39297}, {ip: "187.62.216.197", port: 8080}, {ip: "187.63.111.37", port: 3128}, {ip: "187.64.111.129", port: 37748}, {ip: "187.64.45.49", port: 8080}, {ip: "187.65.63.126", port: 57824}, {ip: "187.66.38.214", port: 61356}, {ip: "187.72.166.10", port: 8080}, {ip: "187.73.205.165", port: 3128}, {ip: "187.73.68.14", port: 53281}, {ip: "187.84.177.6", port: 45903}, {ip: "187.84.191.170", port: 43936}, {ip: "187.85.133.9", port: 54959}, {ip: "187.85.15.37", port: 54890}, {ip: "187.86.153.254", port: 54387}, {ip: "187.87.173.33", port: 53281}, {ip: "187.87.180.132", port: 20183}, {ip: "187.87.204.210", port: 45597}, {ip: "187.87.206.10", port: 8080}, {ip: "187.87.39.247", port: 31793}, {ip: "187.87.39.38", port: 52597}, {ip: "187.9.41.119", port: 50689}, {ip: "187.94.217.69", port: 3128}, {ip: "187.95.124.179", port: 23500}, {ip: "187.95.125.66", port: 53281}, {ip: "187.95.20.15", port: 8080}, {ip: "187.95.236.240", port: 20183}, {ip: "187.95.248.41", port: 8080}, {ip: "187.95.3.108", port: 23500}, {ip: "187.95.34.10", port: 8080}, {ip: "189.1.16.162", port: 23500}, {ip: "189.108.140.70", port: 8080}, {ip: "189.109.140.243", port: 34227}, {ip: "189.112.212.6", port: 32875}, {ip: "189.112.250.196", port: 38453}, {ip: "189.112.49.69", port: 3128}, {ip: "189.113.124.162", port: 8080}, {ip: "189.124.195.185", port: 37318}, {ip: "189.124.201.112", port: 8080}, {ip: "189.124.29.157", port: 20183}, {ip: "189.124.85.182", port: 8080}, {ip: "189.126.65.57", port: 8080}, {ip: "189.126.67.206", port: 8080}, {ip: "189.126.71.49", port: 8080}, {ip: "189.126.77.198", port: 36885}, {ip: "189.126.77.2", port: 52760}, {ip: "189.126.79.198", port: 48615}, {ip: "189.17.21.98", port: 53710}, {ip: "189.2.64.226", port: 43027}, {ip: "189.3.196.18", port: 61595}, {ip: "189.3.224.195", port: 8888}, {ip: "189.34.62.220", port: 60235}, {ip: "189.36.201.182", port: 57102}, {ip: "189.37.33.59", port: 35532}, {ip: "189.38.46.25", port: 49129}, {ip: "189.39.31.162", port: 53281}, {ip: "189.4.65.147", port: 8080}, {ip: "189.41.240.180", port: 33488}, {ip: "189.42.110.111", port: 49785}, {ip: "189.44.108.98", port: 52477}, {ip: "189.45.199.37", port: 20183}, {ip: "189.5.194.15", port: 8080}, {ip: "189.5.207.181", port: 55748}, {ip: "189.5.233.5", port: 8080}, {ip: "189.50.149.236", port: 53281}, {ip: "189.51.96.114", port: 59575}, {ip: "189.51.98.182", port: 49142}, {ip: "189.51.98.214", port: 20183}, {ip: "189.51.98.69", port: 34627}, {ip: "189.57.183.250", port: 50598}, {ip: "189.7.17.100", port: 8080}, {ip: "189.7.49.66", port: 42700}, {ip: "189.7.89.244", port: 8080}, {ip: "189.7.97.54", port: 8080}, {ip: "189.80.135.130", port: 8080}, {ip: "189.84.158.133", port: 53281}, {ip: "189.89.247.178", port: 53281}, {ip: "189.89.248.186", port: 20183}, {ip: "189.89.73.29", port: 45334}, {ip: "189.90.194.35", port: 30843}, {ip: "189.90.241.198", port: 3128}, {ip: "189.90.248.75", port: 8080}, {ip: "189.90.255.231", port: 8080}, {ip: "189.91.231.43", port: 3128}, {ip: "190.180.160.127", port: 3128}, {ip: "190.7.182.52", port: 20183}, {ip: "190.7.182.57", port: 20183}, {ip: "191.17.255.164", port: 8080}, {ip: "191.187.33.49", port: 8080}, {ip: "191.205.241.158", port: 8080}, {ip: "191.239.243.156", port: 3128}, {ip: "191.239.243.199", port: 3128}, {ip: "191.240.154.246", port: 23500}, {ip: "191.240.156.154", port: 36127}, {ip: "191.240.99.142", port: 9090}, {ip: "191.241.226.230", port: 53281}, {ip: "191.241.228.118", port: 20183}, {ip: "191.241.228.74", port: 20183}, {ip: "191.241.228.78", port: 20183}, {ip: "191.241.33.238", port: 39188}, {ip: "191.241.36.170", port: 8080}, {ip: "191.241.36.218", port: 3128}, {ip: "191.242.182.132", port: 8081}, {ip: "191.242.188.60", port: 46437}, {ip: "191.242.240.172", port: 21231}, {ip: "191.243.221.130", port: 3128}, {ip: "191.248.226.218", port: 30695}, {ip: "191.252.193.115", port: 80}, {ip: "191.252.194.143", port: 8080}, {ip: "191.253.108.132", port: 53281}, {ip: "191.253.71.234", port: 8080}, {ip: "191.255.207.231", port: 20183}, {ip: "191.32.54.50", port: 3128}, {ip: "191.33.179.242", port: 8080}, {ip: "191.33.179.243", port: 8080}, {ip: "191.36.151.93", port: 59824}, {ip: "191.36.192.196", port: 3128}, {ip: "191.36.240.200", port: 48339}, {ip: "191.36.244.230", port: 51377}, {ip: "191.37.157.14", port: 46298}, {ip: "191.37.231.202", port: 35725}, {ip: "191.37.3.149", port: 57713}, {ip: "191.37.62.26", port: 47467}, {ip: "191.5.0.79", port: 53281}, {ip: "191.5.114.138", port: 3128}, {ip: "191.5.177.133", port: 39526}, {ip: "191.5.177.146", port: 42837}, {ip: "191.5.177.55", port: 52792}, {ip: "191.55.97.254", port: 60170}, {ip: "191.6.132.77", port: 59844}, {ip: "191.6.228.6", port: 53281}, {ip: "191.7.193.18", port: 38133}, {ip: "191.7.20.134", port: 3128}, {ip: "191.7.207.117", port: 23500}, {ip: "191.7.209.138", port: 20183}, {ip: "191.7.209.141", port: 20183}, {ip: "191.7.211.74", port: 53281}, {ip: "191.7.47.249", port: 54381}, {ip: "192.140.30.253", port: 34237}, {ip: "192.140.42.28", port: 47730}, {ip: "192.140.42.81", port: 33209}, {ip: "192.140.91.133", port: 50581}, {ip: "192.140.91.173", port: 20183}, {ip: "192.141.137.165", port: 8080}, {ip: "192.141.236.2", port: 52781}, {ip: "200.140.132.18", port: 8080}, {ip: "200.141.203.90", port: 8080}, {ip: "200.149.19.170", port: 8080}, {ip: "200.150.120.82", port: 38588}, {ip: "200.150.67.251", port: 8080}, {ip: "200.150.86.138", port: 44677}, {ip: "200.155.36.185", port: 3128}, {ip: "200.155.36.188", port: 3128}, {ip: "200.155.39.41", port: 3128}, {ip: "200.155.57.145", port: 80}, {ip: "200.160.107.199", port: 8080}, {ip: "200.163.125.234", port: 56030}, {ip: "200.165.64.90", port: 8080}, {ip: "200.165.64.90", port: 80}, {ip: "200.165.72.98", port: 30633}, {ip: "200.167.185.137", port: 20183}, {ip: "200.172.103.227", port: 20183}, {ip: "200.174.158.26", port: 34112}, {ip: "200.178.16.139", port: 20183}, {ip: "200.178.251.146", port: 8080}, {ip: "200.187.177.105", port: 20183}, {ip: "200.187.87.138", port: 20183}, {ip: "200.192.252.201", port: 8080}, {ip: "200.192.255.102", port: 8080}, {ip: "200.193.220.17", port: 58355}, {ip: "200.194.249.2", port: 38010}, {ip: "200.195.162.170", port: 8888}, {ip: "200.195.186.203", port: 30698}, {ip: "200.195.188.2", port: 60443}, {ip: "200.201.29.2", port: 3128}, {ip: "200.203.144.2", port: 50262}, {ip: "200.204.166.94", port: 60073}, {ip: "200.206.70.162", port: 20183}, {ip: "200.215.36.180", port: 20183}, {ip: "200.222.46.130", port: 8080}, {ip: "200.229.227.93", port: 8080}, {ip: "200.229.230.237", port: 3128}, {ip: "200.229.230.57", port: 8080}, {ip: "200.229.233.209", port: 8080}, {ip: "200.229.238.42", port: 20183}, {ip: "200.233.134.85", port: 43172}, {ip: "200.233.136.177", port: 20183}, {ip: "200.233.204.233", port: 23500}, {ip: "200.233.220.167", port: 40421}, {ip: "200.236.216.205", port: 34064}, {ip: "200.236.216.242", port: 34064}, {ip: "200.241.44.3", port: 20183}, {ip: "200.241.65.126", port: 33835}, {ip: "200.255.122.170", port: 8080}, {ip: "200.255.122.174", port: 8080}, {ip: "200.49.54.99", port: 51014}, {ip: "200.6.139.173", port: 45902}, {ip: "200.71.123.197", port: 42998}, {ip: "200.9.18.22", port: 8080}, {ip: "200.94.255.198", port: 41823}, {ip: "200.98.166.135", port: 3128}, {ip: "200.98.166.135", port: 80}, {ip: "201.12.21.57", port: 8080}, {ip: "201.131.224.21", port: 56200}, {ip: "201.140.240.9", port: 56902}, {ip: "201.148.238.248", port: 30339}, {ip: "201.150.148.170", port: 8080}, {ip: "201.158.60.26", port: 30219}, {ip: "201.17.147.203", port: 3128}, {ip: "201.17.147.203", port: 3130}, {ip: "201.17.27.229", port: 8888}, {ip: "201.18.98.18", port: 8080}, {ip: "201.182.223.16", port: 37492}, {ip: "201.20.120.14", port: 8080}, {ip: "201.20.89.126", port: 8080}, {ip: "201.20.99.219", port: 8080}, {ip: "201.22.95.10", port: 8080}, {ip: "201.23.192.173", port: 53281}, {ip: "201.30.158.210", port: 36327}, {ip: "201.33.248.59", port: 31952}, {ip: "201.48.118.41", port: 3128}, {ip: "201.48.149.197", port: 42301}, {ip: "201.49.90.38", port: 42045}, {ip: "201.53.201.2", port: 55003}, {ip: "201.54.31.1", port: 55282}, {ip: "201.55.116.242", port: 3128}, {ip: "201.57.167.34", port: 8080}, {ip: "201.57.97.114", port: 3128}, {ip: "201.59.200.246", port: 80}, {ip: "201.6.167.178", port: 3128}, {ip: "201.62.125.229", port: 8080}, {ip: "201.62.125.30", port: 8080}, {ip: "201.62.56.49", port: 40882}, {ip: "201.76.120.78", port: 20183}, {ip: "201.76.70.134", port: 42967}, {ip: "201.82.6.49", port: 8080}, {ip: "201.90.36.194", port: 3128}, {ip: "45.160.228.34", port: 58486}, {ip: "45.160.238.253", port: 8080}, {ip: "45.160.238.253", port: 80}, {ip: "45.225.15.18", port: 53281}, {ip: "45.225.236.223", port: 8080}, {ip: "45.225.6.62", port: 53281}, {ip: "45.225.65.158", port: 38184}, {ip: "45.226.20.6", port: 8080}, {ip: "45.228.48.4", port: 53281}, {ip: "45.229.104.194", port: 80}, {ip: "45.229.158.250", port: 32745}, {ip: "45.229.2.42", port: 53281}, {ip: "45.232.249.143", port: 8181}, {ip: "45.232.249.144", port: 8181}, {ip: "45.232.77.13", port: 46940}, {ip: "45.234.139.129", port: 20183}, {ip: "45.234.16.162", port: 49836}, {ip: "45.234.200.18", port: 53281}, {ip: "45.235.11.5", port: 39916}, {ip: "45.235.116.30", port: 60135}, {ip: "45.235.155.25", port: 31312}, {ip: "45.235.87.11", port: 45965}, {ip: "45.235.87.4", port: 51996}, {ip: "45.239.137.216", port: 52361}, {ip: "45.4.158.220", port: 49961}, {ip: "45.4.187.10", port: 47471}, {ip: "45.4.237.72", port: 34705}, {ip: "45.6.100.70", port: 3128}, {ip: "45.6.120.123", port: 40625}, {ip: "45.6.136.38", port: 53281}, {ip: "45.6.80.131", port: 52080}, {ip: "45.6.93.10", port: 8080}, {ip: "45.70.36.68", port: 53281}, {ip: "45.70.60.18", port: 37750}, {ip: "45.70.85.22", port: 38984}, {ip: "45.71.108.162", port: 53281}, {ip: "45.71.150.103", port: 46866}, {ip: "45.71.150.139", port: 42547}, {ip: "45.71.150.84", port: 38816}, {ip: "45.71.151.72", port: 37778}, {ip: "45.71.80.34", port: 30740}], - "PK" => [{ip: "103.18.243.154", port: 8080}, {ip: "103.4.94.178", port: 57003}, {ip: "103.55.69.14", port: 56066}, {ip: "110.36.181.37", port: 8080}, {ip: "110.36.181.37", port: 80}, {ip: "110.36.218.126", port: 36651}, {ip: "110.36.234.210", port: 8080}, {ip: "110.37.217.252", port: 8080}, {ip: "110.39.162.74", port: 53281}, {ip: "110.39.174.58", port: 8080}, {ip: "110.39.60.2", port: 36293}, {ip: "110.39.64.218", port: 47165}, {ip: "110.93.214.36", port: 31993}, {ip: "110.93.230.218", port: 43054}, {ip: "111.68.108.34", port: 8080}, {ip: "113.203.238.11", port: 8080}, {ip: "115.186.177.243", port: 8080}, {ip: "116.0.54.30", port: 8080}, {ip: "116.58.94.162", port: 8888}, {ip: "121.52.157.23", port: 8080}, {ip: "125.209.115.186", port: 8080}, {ip: "125.209.116.182", port: 31653}, {ip: "125.209.116.94", port: 60364}, {ip: "125.209.78.21", port: 8080}, {ip: "125.209.78.80", port: 32431}, {ip: "125.209.82.78", port: 35087}, {ip: "14.192.128.66", port: 8080}, {ip: "175.107.248.50", port: 57067}, {ip: "175.110.107.69", port: 30058}, {ip: "180.92.156.150", port: 8080}, {ip: "182.176.148.202", port: 42488}, {ip: "182.176.176.150", port: 44187}, {ip: "202.142.158.114", port: 8080}, {ip: "202.142.172.131", port: 8080}, {ip: "202.142.185.166", port: 8080}, {ip: "202.147.173.10", port: 8080}, {ip: "202.147.173.10", port: 80}, {ip: "202.154.247.75", port: 53281}, {ip: "202.166.169.18", port: 8080}, {ip: "202.61.49.52", port: 45119}, {ip: "202.69.38.82", port: 8080}, {ip: "202.70.146.187", port: 8080}, {ip: "203.124.53.2", port: 39573}, {ip: "203.124.53.25", port: 39573}, {ip: "203.128.16.126", port: 59538}, {ip: "203.128.16.154", port: 33002}, {ip: "203.170.67.101", port: 21776}, {ip: "203.170.69.162", port: 60185}, {ip: "203.170.76.6", port: 58576}, {ip: "210.2.153.149", port: 8080}, {ip: "27.255.4.170", port: 8080}, {ip: "42.201.248.154", port: 8080}, {ip: "58.27.212.82", port: 53281}, {ip: "58.65.128.202", port: 49079}, {ip: "58.65.128.234", port: 42807}, {ip: "58.65.175.102", port: 80}], - "ID" => [{ip: "101.128.68.113", port: 8080}, {ip: "101.128.68.123", port: 8080}, {ip: "101.255.103.99", port: 53067}, {ip: "101.255.116.113", port: 53281}, {ip: "101.255.120.170", port: 6969}, {ip: "101.255.121.74", port: 8080}, {ip: "101.255.124.2", port: 53281}, {ip: "101.255.124.242", port: 8080}, {ip: "101.255.124.242", port: 80}, {ip: "101.255.44.156", port: 80}, {ip: "101.255.44.201", port: 55399}, {ip: "101.255.44.203", port: 55399}, {ip: "101.255.52.162", port: 31941}, {ip: "101.255.56.138", port: 53560}, {ip: "101.255.63.10", port: 36818}, {ip: "101.255.64.142", port: 56093}, {ip: "101.255.64.58", port: 55301}, {ip: "101.255.85.42", port: 80}, {ip: "101.255.97.74", port: 53281}, {ip: "103.10.120.205", port: 8080}, {ip: "103.10.171.132", port: 41043}, {ip: "103.10.81.172", port: 80}, {ip: "103.100.96.174", port: 53281}, {ip: "103.104.57.34", port: 42793}, {ip: "103.105.64.162", port: 23500}, {ip: "103.105.68.158", port: 50280}, {ip: "103.105.70.13", port: 39588}, {ip: "103.105.77.27", port: 8080}, {ip: "103.108.158.3", port: 48196}, {ip: "103.110.88.16", port: 39210}, {ip: "103.111.219.159", port: 53281}, {ip: "103.111.219.169", port: 53281}, {ip: "103.111.219.170", port: 53281}, {ip: "103.111.30.102", port: 53281}, {ip: "103.111.31.154", port: 60226}, {ip: "103.111.31.230", port: 8080}, {ip: "103.111.54.26", port: 49781}, {ip: "103.111.54.74", port: 8080}, {ip: "103.111.59.18", port: 41112}, {ip: "103.112.162.34", port: 8080}, {ip: "103.15.241.225", port: 53281}, {ip: "103.17.244.82", port: 46168}, {ip: "103.18.32.242", port: 47985}, {ip: "103.19.110.177", port: 8080}, {ip: "103.19.37.24", port: 53281}, {ip: "103.19.37.3", port: 53281}, {ip: "103.197.92.204", port: 55925}, {ip: "103.2.146.66", port: 49089}, {ip: "103.206.168.177", port: 53281}, {ip: "103.206.253.58", port: 49573}, {ip: "103.206.254.170", port: 65103}, {ip: "103.207.97.181", port: 8080}, {ip: "103.21.92.254", port: 33929}, {ip: "103.210.120.42", port: 44700}, {ip: "103.210.121.10", port: 8080}, {ip: "103.211.232.12", port: 53281}, {ip: "103.211.233.212", port: 44560}, {ip: "103.214.185.1", port: 3128}, {ip: "103.217.172.62", port: 41977}, {ip: "103.217.173.182", port: 58815}, {ip: "103.217.173.194", port: 80}, {ip: "103.217.173.238", port: 58815}, {ip: "103.217.216.2", port: 53281}, {ip: "103.224.101.132", port: 55872}, {ip: "103.224.101.155", port: 46288}, {ip: "103.224.103.10", port: 8080}, {ip: "103.224.64.204", port: 52405}, {ip: "103.226.49.83", port: 23500}, {ip: "103.227.147.100", port: 8080}, {ip: "103.227.147.142", port: 37581}, {ip: "103.228.117.244", port: 8080}, {ip: "103.228.118.134", port: 41950}, {ip: "103.228.119.26", port: 41784}, {ip: "103.228.119.50", port: 8080}, {ip: "103.23.101.58", port: 8080}, {ip: "103.232.242.238", port: 46678}, {ip: "103.232.242.46", port: 54731}, {ip: "103.232.243.34", port: 42085}, {ip: "103.232.33.46", port: 8080}, {ip: "103.24.107.2", port: 8181}, {ip: "103.244.205.114", port: 32018}, {ip: "103.244.205.142", port: 60716}, {ip: "103.244.205.225", port: 55867}, {ip: "103.244.37.34", port: 55374}, {ip: "103.245.19.222", port: 53281}, {ip: "103.247.122.38", port: 8080}, {ip: "103.247.15.146", port: 48039}, {ip: "103.247.216.209", port: 8080}, {ip: "103.247.217.117", port: 30989}, {ip: "103.247.218.166", port: 3128}, {ip: "103.247.226.114", port: 61870}, {ip: "103.248.219.26", port: 53634}, {ip: "103.248.25.99", port: 53281}, {ip: "103.253.1.158", port: 43674}, {ip: "103.253.107.231", port: 30352}, {ip: "103.253.113.23", port: 46641}, {ip: "103.253.2.165", port: 33543}, {ip: "103.253.2.168", port: 51229}, {ip: "103.253.2.174", port: 30827}, {ip: "103.254.104.154", port: 53281}, {ip: "103.254.126.182", port: 47699}, {ip: "103.255.240.66", port: 46324}, {ip: "103.255.242.22", port: 46562}, {ip: "103.255.242.47", port: 54514}, {ip: "103.26.130.156", port: 53281}, {ip: "103.28.114.133", port: 8080}, {ip: "103.28.114.134", port: 8080}, {ip: "103.28.114.61", port: 50675}, {ip: "103.28.114.62", port: 50675}, {ip: "103.28.114.63", port: 50675}, {ip: "103.28.220.73", port: 53281}, {ip: "103.28.226.125", port: 32862}, {ip: "103.28.226.83", port: 39753}, {ip: "103.28.227.69", port: 3128}, {ip: "103.29.184.106", port: 47338}, {ip: "103.29.185.35", port: 53281}, {ip: "103.3.76.90", port: 39850}, {ip: "103.3.77.94", port: 37239}, {ip: "103.30.181.90", port: 53281}, {ip: "103.30.246.47", port: 3128}, {ip: "103.30.92.91", port: 35683}, {ip: "103.31.225.162", port: 32110}, {ip: "103.31.45.118", port: 8080}, {ip: "103.31.45.169", port: 57655}, {ip: "103.31.45.172", port: 37660}, {ip: "103.31.45.214", port: 32296}, {ip: "103.4.164.206", port: 8080}, {ip: "103.41.122.14", port: 53281}, {ip: "103.42.255.70", port: 8080}, {ip: "103.43.130.33", port: 56687}, {ip: "103.54.94.204", port: 54960}, {ip: "103.57.194.253", port: 53281}, {ip: "103.66.198.118", port: 80}, {ip: "103.68.0.115", port: 47390}, {ip: "103.68.0.66", port: 54766}, {ip: "103.75.101.97", port: 8080}, {ip: "103.75.150.130", port: 8080}, {ip: "103.75.27.94", port: 80}, {ip: "103.76.15.238", port: 37835}, {ip: "103.76.151.154", port: 39806}, {ip: "103.76.17.151", port: 23500}, {ip: "103.76.170.50", port: 53375}, {ip: "103.76.50.181", port: 8080}, {ip: "103.76.50.181", port: 80}, {ip: "103.76.50.182", port: 8080}, {ip: "103.78.211.234", port: 8080}, {ip: "103.78.213.226", port: 33818}, {ip: "103.78.74.170", port: 3128}, {ip: "103.78.75.27", port: 8080}, {ip: "103.78.80.194", port: 33442}, {ip: "103.8.122.5", port: 53297}, {ip: "103.80.236.107", port: 53281}, {ip: "103.80.238.203", port: 53281}, {ip: "103.80.80.202", port: 8080}, {ip: "103.83.95.122", port: 50049}, {ip: "103.84.143.245", port: 8080}, {ip: "103.84.208.22", port: 33606}, {ip: "103.85.150.146", port: 23500}, {ip: "103.85.150.90", port: 23500}, {ip: "103.85.220.138", port: 60173}, {ip: "103.85.220.234", port: 38046}, {ip: "103.86.140.74", port: 59538}, {ip: "103.86.147.2", port: 8088}, {ip: "103.94.122.254", port: 8080}, {ip: "103.94.125.244", port: 41508}, {ip: "103.94.169.19", port: 8080}, {ip: "103.94.171.134", port: 46845}, {ip: "103.94.3.10", port: 3128}, {ip: "103.94.4.99", port: 8080}, {ip: "103.94.7.254", port: 53281}, {ip: "106.0.51.50", port: 17385}, {ip: "110.136.236.197", port: 3128}, {ip: "110.232.64.164", port: 42008}, {ip: "110.232.67.50", port: 23500}, {ip: "110.232.72.22", port: 8080}, {ip: "110.232.74.51", port: 8080}, {ip: "110.232.76.164", port: 80}, {ip: "110.232.76.212", port: 8888}, {ip: "110.232.76.247", port: 8080}, {ip: "110.232.80.247", port: 14996}, {ip: "110.232.80.91", port: 8080}, {ip: "110.232.83.134", port: 30096}, {ip: "110.232.83.184", port: 8080}, {ip: "110.232.83.190", port: 30619}, {ip: "110.232.83.55", port: 30528}, {ip: "110.232.85.168", port: 50056}, {ip: "110.232.86.204", port: 61465}, {ip: "110.232.86.69", port: 23500}, {ip: "110.5.100.130", port: 33622}, {ip: "110.50.85.174", port: 8080}, {ip: "110.76.148.25", port: 9191}, {ip: "110.93.13.202", port: 34881}, {ip: "111.223.252.43", port: 8080}, {ip: "111.67.77.210", port: 53281}, {ip: "111.68.124.154", port: 53281}, {ip: "111.68.31.50", port: 39551}, {ip: "112.215.116.178", port: 58192}, {ip: "112.78.178.2", port: 36530}, {ip: "112.78.188.194", port: 8080}, {ip: "112.78.37.6", port: 54791}, {ip: "112.78.38.21", port: 33427}, {ip: "112.78.39.59", port: 32410}, {ip: "112.78.44.217", port: 59551}, {ip: "113.11.156.42", port: 31476}, {ip: "114.110.22.90", port: 43221}, {ip: "114.141.51.122", port: 53281}, {ip: "114.199.110.58", port: 55898}, {ip: "114.199.112.170", port: 23500}, {ip: "114.199.123.194", port: 8080}, {ip: "114.4.116.174", port: 44986}, {ip: "114.4.121.54", port: 48304}, {ip: "114.5.128.18", port: 36588}, {ip: "114.5.22.54", port: 61315}, {ip: "114.57.189.2", port: 42304}, {ip: "114.57.33.162", port: 46935}, {ip: "114.57.33.214", port: 8080}, {ip: "114.6.192.186", port: 44080}, {ip: "114.6.197.254", port: 8080}, {ip: "114.6.61.122", port: 54097}, {ip: "114.7.15.146", port: 8080}, {ip: "114.7.162.254", port: 53281}, {ip: "114.7.165.186", port: 8080}, {ip: "114.7.170.130", port: 53281}, {ip: "114.8.147.102", port: 40109}, {ip: "115.124.75.226", port: 53990}, {ip: "115.124.75.228", port: 3128}, {ip: "115.166.100.5", port: 57068}, {ip: "115.85.65.146", port: 58343}, {ip: "115.85.71.18", port: 41746}, {ip: "115.85.77.7", port: 33886}, {ip: "116.0.2.94", port: 35441}, {ip: "116.0.3.124", port: 60918}, {ip: "116.197.131.210", port: 8080}, {ip: "116.254.100.203", port: 3128}, {ip: "116.254.100.97", port: 46179}, {ip: "116.50.25.154", port: 37806}, {ip: "116.90.183.20", port: 46871}, {ip: "117.102.112.115", port: 32231}, {ip: "117.102.227.190", port: 44931}, {ip: "117.102.227.26", port: 53527}, {ip: "117.102.65.20", port: 36048}, {ip: "117.102.78.42", port: 8080}, {ip: "117.102.93.251", port: 8080}, {ip: "117.102.94.186", port: 8080}, {ip: "117.102.94.186", port: 80}, {ip: "117.102.97.186", port: 61979}, {ip: "117.103.2.249", port: 58276}, {ip: "117.121.200.174", port: 53433}, {ip: "117.121.207.149", port: 36983}, {ip: "117.54.13.174", port: 34190}, {ip: "117.54.138.34", port: 8080}, {ip: "117.54.138.36", port: 8080}, {ip: "117.54.239.82", port: 60843}, {ip: "117.54.4.229", port: 53281}, {ip: "117.74.124.129", port: 8088}, {ip: "118.96.239.139", port: 8080}, {ip: "118.97.100.83", port: 35220}, {ip: "118.97.169.170", port: 3128}, {ip: "118.97.175.114", port: 8080}, {ip: "118.97.175.122", port: 8080}, {ip: "118.97.180.142", port: 30793}, {ip: "118.97.187.42", port: 8080}, {ip: "118.97.191.162", port: 8080}, {ip: "118.97.191.162", port: 80}, {ip: "118.97.191.203", port: 8080}, {ip: "118.97.235.234", port: 53281}, {ip: "118.97.255.202", port: 34205}, {ip: "118.97.36.18", port: 8080}, {ip: "118.97.47.248", port: 53281}, {ip: "118.97.47.249", port: 53281}, {ip: "118.97.47.250", port: 53281}, {ip: "118.97.73.85", port: 53281}, {ip: "118.97.83.42", port: 8080}, {ip: "118.99.105.226", port: 8080}, {ip: "119.10.176.226", port: 8080}, {ip: "119.11.240.131", port: 34405}, {ip: "119.11.253.2", port: 50059}, {ip: "119.18.157.218", port: 8080}, {ip: "119.18.158.218", port: 8000}, {ip: "119.2.40.238", port: 35808}, {ip: "119.2.41.98", port: 36953}, {ip: "119.2.48.129", port: 49660}, {ip: "119.2.49.154", port: 23500}, {ip: "119.2.50.234", port: 43164}, {ip: "119.2.52.45", port: 44643}, {ip: "119.2.54.98", port: 8080}, {ip: "119.252.168.50", port: 53281}, {ip: "119.252.168.51", port: 53281}, {ip: "119.252.168.53", port: 53281}, {ip: "119.82.244.86", port: 37119}, {ip: "119.82.245.250", port: 55113}, {ip: "120.29.153.97", port: 8080}, {ip: "121.101.133.71", port: 8080}, {ip: "121.101.135.98", port: 8080}, {ip: "122.102.41.82", port: 46799}, {ip: "122.102.43.82", port: 48267}, {ip: "122.129.108.107", port: 51774}, {ip: "122.129.199.250", port: 37366}, {ip: "122.248.45.35", port: 53281}, {ip: "122.50.5.190", port: 8080}, {ip: "122.50.5.190", port: 80}, {ip: "122.50.6.186", port: 8080}, {ip: "122.50.6.186", port: 80}, {ip: "123.108.99.9", port: 8080}, {ip: "123.231.203.254", port: 8080}, {ip: "123.231.226.114", port: 47562}, {ip: "123.231.237.131", port: 35806}, {ip: "123.231.246.189", port: 37652}, {ip: "123.231.251.194", port: 3128}, {ip: "123.255.202.83", port: 32523}, {ip: "124.158.161.146", port: 3128}, {ip: "124.158.164.195", port: 8080}, {ip: "124.81.123.10", port: 8080}, {ip: "124.81.123.3", port: 8080}, {ip: "124.81.228.34", port: 48549}, {ip: "124.81.245.148", port: 8080}, {ip: "124.81.99.30", port: 3128}, {ip: "125.162.20.249", port: 8080}, {ip: "125.162.89.106", port: 8080}, {ip: "125.162.89.136", port: 8080}, {ip: "125.208.136.42", port: 38627}, {ip: "137.59.162.10", port: 3128}, {ip: "137.59.162.110", port: 8080}, {ip: "139.0.29.18", port: 59532}, {ip: "139.0.29.20", port: 59532}, {ip: "139.0.5.203", port: 3128}, {ip: "139.255.100.34", port: 8080}, {ip: "139.255.120.4", port: 53281}, {ip: "139.255.123.194", port: 4550}, {ip: "139.255.129.252", port: 8080}, {ip: "139.255.16.171", port: 31773}, {ip: "139.255.17.2", port: 47421}, {ip: "139.255.19.162", port: 42371}, {ip: "139.255.19.26", port: 8080}, {ip: "139.255.19.74", port: 32677}, {ip: "139.255.40.138", port: 43228}, {ip: "139.255.7.81", port: 53281}, {ip: "139.255.87.101", port: 30287}, {ip: "139.255.91.115", port: 8080}, {ip: "139.255.92.156", port: 8080}, {ip: "139.255.92.26", port: 53281}, {ip: "139.5.153.86", port: 53281}, {ip: "14.102.152.157", port: 8080}, {ip: "149.129.217.212", port: 8080}, {ip: "150.107.136.105", port: 23500}, {ip: "150.107.249.6", port: 8080}, {ip: "150.129.57.147", port: 42526}, {ip: "158.140.181.140", port: 54041}, {ip: "158.140.191.191", port: 8080}, {ip: "160.202.40.20", port: 55655}, {ip: "163.53.185.22", port: 8080}, {ip: "175.103.42.147", port: 8080}, {ip: "175.106.14.138", port: 8181}, {ip: "175.106.18.190", port: 41232}, {ip: "175.184.224.102", port: 49689}, {ip: "175.184.248.83", port: 8080}, {ip: "175.184.248.83", port: 80}, {ip: "180.178.98.166", port: 44194}, {ip: "180.178.98.198", port: 8080}, {ip: "180.214.247.195", port: 61506}, {ip: "180.214.247.196", port: 35128}, {ip: "180.241.157.148", port: 8080}, {ip: "180.241.78.217", port: 8080}, {ip: "180.244.92.5", port: 8080}, {ip: "180.246.205.26", port: 8080}, {ip: "180.250.101.146", port: 8080}, {ip: "180.250.113.52", port: 8080}, {ip: "180.250.141.225", port: 8080}, {ip: "180.250.150.73", port: 8080}, {ip: "180.250.158.52", port: 51621}, {ip: "180.250.16.34", port: 8080}, {ip: "180.250.16.66", port: 53281}, {ip: "180.250.161.154", port: 59120}, {ip: "180.250.182.59", port: 8080}, {ip: "180.250.19.92", port: 3128}, {ip: "180.250.220.162", port: 8080}, {ip: "180.250.5.37", port: 80}, {ip: "180.250.54.27", port: 53281}, {ip: "180.250.7.27", port: 8080}, {ip: "180.250.70.12", port: 51540}, {ip: "180.253.237.201", port: 8080}, {ip: "180.253.252.18", port: 80}, {ip: "180.253.90.32", port: 3128}, {ip: "180.254.249.102", port: 8080}, {ip: "182.16.163.233", port: 53301}, {ip: "182.16.171.26", port: 53281}, {ip: "182.16.178.211", port: 8080}, {ip: "182.16.181.90", port: 61620}, {ip: "182.16.184.138", port: 23500}, {ip: "182.16.184.146", port: 23500}, {ip: "182.16.184.162", port: 23500}, {ip: "182.16.185.210", port: 53281}, {ip: "182.23.102.10", port: 53399}, {ip: "182.23.103.180", port: 8080}, {ip: "182.23.103.180", port: 80}, {ip: "182.23.107.212", port: 3128}, {ip: "182.23.2.101", port: 49833}, {ip: "182.23.2.105", port: 49833}, {ip: "182.23.2.98", port: 49833}, {ip: "182.23.28.187", port: 3128}, {ip: "182.23.28.188", port: 3128}, {ip: "182.23.5.10", port: 53334}, {ip: "182.23.5.46", port: 32716}, {ip: "182.23.7.226", port: 8080}, {ip: "182.23.98.214", port: 8080}, {ip: "182.253.100.136", port: 3129}, {ip: "182.253.113.42", port: 53281}, {ip: "182.253.117.162", port: 8080}, {ip: "182.253.122.151", port: 53281}, {ip: "182.253.122.40", port: 8080}, {ip: "182.253.123.10", port: 3128}, {ip: "182.253.141.116", port: 8080}, {ip: "182.253.141.25", port: 8080}, {ip: "182.253.143.11", port: 8080}, {ip: "182.253.176.33", port: 8080}, {ip: "182.253.177.186", port: 8080}, {ip: "182.253.177.65", port: 43858}, {ip: "182.253.180.203", port: 8080}, {ip: "182.253.195.174", port: 36964}, {ip: "182.253.201.10", port: 30393}, {ip: "182.253.209.18", port: 8080}, {ip: "182.253.209.203", port: 3128}, {ip: "182.253.209.205", port: 3128}, {ip: "182.253.21.26", port: 36926}, {ip: "182.253.215.210", port: 3128}, {ip: "182.253.238.154", port: 30353}, {ip: "182.253.25.235", port: 8080}, {ip: "182.253.26.196", port: 8080}, {ip: "182.253.33.147", port: 8080}, {ip: "182.253.39.137", port: 8080}, {ip: "182.253.39.179", port: 8080}, {ip: "182.253.43.246", port: 8080}, {ip: "182.253.82.106", port: 58046}, {ip: "183.81.152.193", port: 8080}, {ip: "183.91.66.210", port: 80}, {ip: "202.137.10.179", port: 57338}, {ip: "202.137.25.53", port: 3128}, {ip: "202.137.25.8", port: 8080}, {ip: "202.138.230.121", port: 53281}, {ip: "202.138.242.69", port: 38189}, {ip: "202.138.242.76", port: 4550}, {ip: "202.138.242.88", port: 8080}, {ip: "202.138.244.32", port: 8080}, {ip: "202.138.248.171", port: 4550}, {ip: "202.138.249.195", port: 8000}, {ip: "202.138.249.202", port: 43108}, {ip: "202.138.249.223", port: 56546}, {ip: "202.138.254.113", port: 8080}, {ip: "202.138.254.40", port: 8080}, {ip: "202.146.0.219", port: 47217}, {ip: "202.146.144.134", port: 37233}, {ip: "202.147.195.158", port: 8080}, {ip: "202.148.13.62", port: 53281}, {ip: "202.148.2.254", port: 8000}, {ip: "202.150.151.83", port: 3128}, {ip: "202.150.151.83", port: 80}, {ip: "202.150.152.24", port: 46776}, {ip: "202.152.55.66", port: 8080}, {ip: "202.152.55.66", port: 80}, {ip: "202.152.59.245", port: 8080}, {ip: "202.152.59.245", port: 80}, {ip: "202.153.226.98", port: 8080}, {ip: "202.154.181.42", port: 23500}, {ip: "202.154.41.28", port: 37638}, {ip: "202.158.6.115", port: 8888}, {ip: "202.158.89.4", port: 58405}, {ip: "202.162.195.77", port: 8080}, {ip: "202.162.196.177", port: 80}, {ip: "202.162.197.110", port: 8080}, {ip: "202.162.200.67", port: 41448}, {ip: "202.162.201.94", port: 53281}, {ip: "202.162.212.2", port: 52434}, {ip: "202.162.221.250", port: 48199}, {ip: "202.162.222.42", port: 8080}, {ip: "202.162.34.115", port: 53281}, {ip: "202.165.47.26", port: 8080}, {ip: "202.169.235.17", port: 59852}, {ip: "202.169.244.190", port: 23500}, {ip: "202.169.246.35", port: 41424}, {ip: "202.182.55.18", port: 53281}, {ip: "202.43.167.130", port: 8080}, {ip: "202.51.115.130", port: 53281}, {ip: "202.51.123.250", port: 53281}, {ip: "202.51.126.10", port: 53281}, {ip: "202.56.167.233", port: 35596}, {ip: "202.57.10.154", port: 808}, {ip: "202.57.8.144", port: 61220}, {ip: "202.58.199.150", port: 58839}, {ip: "202.58.205.179", port: 80}, {ip: "202.59.171.164", port: 58567}, {ip: "202.6.237.170", port: 8080}, {ip: "202.6.238.198", port: 59889}, {ip: "202.72.209.83", port: 53281}, {ip: "202.72.219.42", port: 61300}, {ip: "202.74.239.21", port: 37639}, {ip: "202.75.110.114", port: 56060}, {ip: "202.77.107.243", port: 61917}, {ip: "202.77.112.34", port: 38978}, {ip: "202.91.8.228", port: 53281}, {ip: "202.93.128.98", port: 3128}, {ip: "202.93.227.14", port: 53281}, {ip: "202.93.228.34", port: 53281}, {ip: "202.93.229.2", port: 8080}, {ip: "203.128.68.242", port: 53281}, {ip: "203.128.70.206", port: 80}, {ip: "203.130.208.165", port: 8081}, {ip: "203.130.231.178", port: 8080}, {ip: "203.130.231.178", port: 80}, {ip: "203.130.243.81", port: 53281}, {ip: "203.142.69.242", port: 37139}, {ip: "203.142.72.114", port: 808}, {ip: "203.153.109.150", port: 47967}, {ip: "203.153.117.65", port: 54144}, {ip: "203.160.56.89", port: 8080}, {ip: "203.173.92.254", port: 44376}, {ip: "203.173.94.101", port: 35786}, {ip: "203.173.94.65", port: 37083}, {ip: "203.174.12.86", port: 30789}, {ip: "203.189.89.1", port: 53281}, {ip: "203.201.174.82", port: 23500}, {ip: "203.210.84.181", port: 38313}, {ip: "203.215.48.158", port: 45523}, {ip: "203.215.48.86", port: 41665}, {ip: "203.30.236.39", port: 36533}, {ip: "203.77.215.250", port: 61474}, {ip: "203.77.239.18", port: 37002}, {ip: "203.77.239.2", port: 80}, {ip: "203.77.239.22", port: 37002}, {ip: "203.77.249.114", port: 36550}, {ip: "203.77.250.195", port: 8080}, {ip: "203.89.29.174", port: 34218}, {ip: "203.89.29.198", port: 50079}, {ip: "203.99.110.214", port: 56706}, {ip: "203.99.116.162", port: 43403}, {ip: "203.99.117.162", port: 8888}, {ip: "203.99.117.234", port: 47689}, {ip: "203.99.123.25", port: 61502}, {ip: "203.99.131.218", port: 51618}, {ip: "210.210.129.250", port: 48404}, {ip: "210.211.16.146", port: 51539}, {ip: "210.211.17.98", port: 31632}, {ip: "210.211.18.166", port: 31096}, {ip: "210.211.18.182", port: 48309}, {ip: "220.247.168.163", port: 53281}, {ip: "220.247.170.82", port: 3128}, {ip: "220.247.171.138", port: 8080}, {ip: "220.247.171.139", port: 8080}, {ip: "220.247.171.19", port: 8080}, {ip: "220.247.173.154", port: 53281}, {ip: "220.247.174.206", port: 53445}, {ip: "222.124.131.211", port: 47343}, {ip: "222.124.173.146", port: 53281}, {ip: "222.124.2.131", port: 8080}, {ip: "222.124.2.186", port: 8080}, {ip: "222.124.215.187", port: 38913}, {ip: "222.124.219.202", port: 8080}, {ip: "222.124.221.179", port: 53281}, {ip: "222.124.26.37", port: 32802}, {ip: "223.25.101.242", port: 59504}, {ip: "223.25.97.62", port: 8080}, {ip: "223.25.99.38", port: 80}, {ip: "27.111.38.188", port: 56525}, {ip: "27.111.44.202", port: 80}, {ip: "27.111.47.112", port: 40662}, {ip: "27.111.47.225", port: 13968}, {ip: "27.111.47.3", port: 51144}, {ip: "27.112.66.18", port: 33992}, {ip: "27.112.69.114", port: 48938}, {ip: "27.112.69.67", port: 8080}, {ip: "27.121.85.106", port: 8080}, {ip: "27.123.7.110", port: 8080}, {ip: "27.131.7.162", port: 53281}, {ip: "27.50.18.42", port: 23500}, {ip: "27.50.31.46", port: 8080}, {ip: "36.37.103.10", port: 53281}, {ip: "36.37.110.136", port: 34304}, {ip: "36.37.112.210", port: 42883}, {ip: "36.37.124.226", port: 36179}, {ip: "36.37.124.234", port: 36179}, {ip: "36.37.124.235", port: 36179}, {ip: "36.37.70.70", port: 47781}, {ip: "36.37.75.82", port: 8080}, {ip: "36.37.81.135", port: 8080}, {ip: "36.37.89.98", port: 32323}, {ip: "36.65.204.226", port: 8080}, {ip: "36.65.8.152", port: 8080}, {ip: "36.66.124.227", port: 46661}, {ip: "36.66.126.77", port: 45726}, {ip: "36.66.138.25", port: 40496}, {ip: "36.66.140.207", port: 59310}, {ip: "36.66.16.25", port: 53281}, {ip: "36.66.163.98", port: 8080}, {ip: "36.66.171.3", port: 39105}, {ip: "36.66.175.111", port: 51498}, {ip: "36.66.201.130", port: 51788}, {ip: "36.66.203.245", port: 51988}, {ip: "36.66.207.124", port: 47430}, {ip: "36.66.210.211", port: 33188}, {ip: "36.66.213.69", port: 55279}, {ip: "36.66.215.179", port: 46361}, {ip: "36.66.217.179", port: 8080}, {ip: "36.66.220.185", port: 61949}, {ip: "36.66.235.147", port: 43220}, {ip: "36.66.252.50", port: 38385}, {ip: "36.66.254.115", port: 41955}, {ip: "36.66.40.11", port: 47356}, {ip: "36.66.43.133", port: 61303}, {ip: "36.66.43.27", port: 8080}, {ip: "36.66.43.39", port: 40206}, {ip: "36.66.56.58", port: 53281}, {ip: "36.66.56.66", port: 8080}, {ip: "36.66.61.157", port: 33752}, {ip: "36.66.71.17", port: 8080}, {ip: "36.66.76.177", port: 3128}, {ip: "36.66.83.97", port: 58542}, {ip: "36.66.83.99", port: 40209}, {ip: "36.66.93.226", port: 8080}, {ip: "36.66.95.187", port: 55179}, {ip: "36.66.97.51", port: 8080}, {ip: "36.66.98.6", port: 53281}, {ip: "36.67.10.77", port: 8080}, {ip: "36.67.10.77", port: 80}, {ip: "36.67.134.165", port: 50706}, {ip: "36.67.142.59", port: 50173}, {ip: "36.67.143.183", port: 48746}, {ip: "36.67.146.19", port: 53281}, {ip: "36.67.15.129", port: 30543}, {ip: "36.67.158.49", port: 65301}, {ip: "36.67.166.221", port: 57942}, {ip: "36.67.184.179", port: 30480}, {ip: "36.67.199.221", port: 42969}, {ip: "36.67.199.89", port: 32420}, {ip: "36.67.20.71", port: 8080}, {ip: "36.67.203.74", port: 37232}, {ip: "36.67.204.74", port: 32809}, {ip: "36.67.206.187", port: 8080}, {ip: "36.67.206.29", port: 3128}, {ip: "36.67.215.249", port: 8080}, {ip: "36.67.217.243", port: 40605}, {ip: "36.67.223.67", port: 31233}, {ip: "36.67.32.237", port: 60770}, {ip: "36.67.32.87", port: 8080}, {ip: "36.67.37.53", port: 49708}, {ip: "36.67.42.39", port: 46808}, {ip: "36.67.52.99", port: 53281}, {ip: "36.67.57.165", port: 48969}, {ip: "36.67.57.165", port: 8888}, {ip: "36.67.57.45", port: 53367}, {ip: "36.67.66.202", port: 49851}, {ip: "36.67.7.98", port: 44590}, {ip: "36.67.79.28", port: 53281}, {ip: "36.67.8.37", port: 34142}, {ip: "36.67.8.81", port: 37579}, {ip: "36.67.80.19", port: 8080}, {ip: "36.67.85.3", port: 8080}, {ip: "36.67.93.220", port: 3128}, {ip: "36.67.93.220", port: 80}, {ip: "36.67.96.7", port: 37554}, {ip: "36.72.122.17", port: 53281}, {ip: "36.72.230.234", port: 80}, {ip: "36.73.138.100", port: 8080}, {ip: "36.73.216.76", port: 8080}, {ip: "36.74.72.76", port: 41437}, {ip: "36.78.223.250", port: 8080}, {ip: "36.78.223.250", port: 80}, {ip: "36.79.6.130", port: 8080}, {ip: "36.80.165.181", port: 53281}, {ip: "36.81.0.187", port: 8080}, {ip: "36.81.1.38", port: 8080}, {ip: "36.81.203.228", port: 8080}, {ip: "36.81.255.73", port: 8080}, {ip: "36.81.3.95", port: 55242}, {ip: "36.82.18.94", port: 8080}, {ip: "36.83.73.209", port: 8080}, {ip: "36.89.10.51", port: 34115}, {ip: "36.89.116.61", port: 3128}, {ip: "36.89.119.149", port: 8080}, {ip: "36.89.127.91", port: 8080}, {ip: "36.89.127.91", port: 80}, {ip: "36.89.129.183", port: 38992}, {ip: "36.89.129.241", port: 8080}, {ip: "36.89.145.162", port: 80}, {ip: "36.89.148.47", port: 54788}, {ip: "36.89.157.23", port: 37728}, {ip: "36.89.165.51", port: 53437}, {ip: "36.89.165.55", port: 8080}, {ip: "36.89.165.89", port: 49696}, {ip: "36.89.17.27", port: 3128}, {ip: "36.89.171.243", port: 46344}, {ip: "36.89.180.129", port: 42321}, {ip: "36.89.181.155", port: 60165}, {ip: "36.89.181.161", port: 50204}, {ip: "36.89.188.11", port: 39507}, {ip: "36.89.189.239", port: 53281}, {ip: "36.89.193.207", port: 53281}, {ip: "36.89.193.79", port: 53236}, {ip: "36.89.194.107", port: 54532}, {ip: "36.89.194.113", port: 37811}, {ip: "36.89.194.141", port: 60493}, {ip: "36.89.20.154", port: 8080}, {ip: "36.89.205.10", port: 53281}, {ip: "36.89.209.42", port: 42852}, {ip: "36.89.211.146", port: 40438}, {ip: "36.89.212.10", port: 8080}, {ip: "36.89.226.254", port: 8081}, {ip: "36.89.227.34", port: 39339}, {ip: "36.89.229.127", port: 36155}, {ip: "36.89.229.97", port: 36528}, {ip: "36.89.232.138", port: 23500}, {ip: "36.89.235.35", port: 51455}, {ip: "36.89.238.19", port: 52334}, {ip: "36.89.239.133", port: 41152}, {ip: "36.89.242.130", port: 42256}, {ip: "36.89.244.151", port: 60590}, {ip: "36.89.247.59", port: 8080}, {ip: "36.89.247.60", port: 8080}, {ip: "36.89.28.250", port: 3128}, {ip: "36.89.28.250", port: 80}, {ip: "36.89.29.101", port: 57372}, {ip: "36.89.39.10", port: 3128}, {ip: "36.89.46.202", port: 80}, {ip: "36.89.51.43", port: 41599}, {ip: "36.89.53.175", port: 47048}, {ip: "36.89.65.253", port: 60997}, {ip: "36.89.66.204", port: 8080}, {ip: "36.89.78.43", port: 8080}, {ip: "36.89.81.129", port: 53732}, {ip: "36.89.81.147", port: 52022}, {ip: "36.89.81.161", port: 34182}, {ip: "36.89.85.181", port: 3128}, {ip: "36.89.89.7", port: 8080}, {ip: "36.89.89.7", port: 80}, {ip: "36.90.130.113", port: 8080}, {ip: "36.91.44.189", port: 50726}, {ip: "36.91.44.243", port: 41907}, {ip: "36.91.45.10", port: 33481}, {ip: "36.91.48.82", port: 8080}, {ip: "36.91.54.145", port: 51730}, {ip: "36.91.54.205", port: 38707}, {ip: "36.91.75.125", port: 8080}, {ip: "42.62.176.226", port: 12}, {ip: "42.62.177.30", port: 30953}, {ip: "43.229.252.45", port: 53281}, {ip: "43.243.141.114", port: 8080}, {ip: "43.245.184.202", port: 41102}, {ip: "43.245.184.238", port: 8080}, {ip: "43.245.184.238", port: 80}, {ip: "43.248.24.157", port: 51166}, {ip: "43.252.10.244", port: 8181}, {ip: "43.252.11.123", port: 8080}, {ip: "43.252.156.236", port: 8080}, {ip: "43.252.156.239", port: 8080}, {ip: "43.252.158.21", port: 56595}, {ip: "43.252.159.211", port: 41358}, {ip: "45.112.125.43", port: 8080}, {ip: "45.251.72.162", port: 8080}, {ip: "60.253.115.10", port: 48514}, {ip: "66.96.232.250", port: 8181}, {ip: "66.96.233.225", port: 35053}, {ip: "66.96.237.253", port: 8080}], - "BD" => [{ip: "103.102.138.180", port: 32529}, {ip: "103.103.88.91", port: 8080}, {ip: "103.106.119.154", port: 8080}, {ip: "103.106.119.170", port: 32814}, {ip: "103.106.236.1", port: 8080}, {ip: "103.106.236.41", port: 8080}, {ip: "103.106.236.50", port: 8080}, {ip: "103.106.236.65", port: 8080}, {ip: "103.106.237.103", port: 45300}, {ip: "103.106.237.6", port: 8080}, {ip: "103.106.238.241", port: 8080}, {ip: "103.106.239.253", port: 8080}, {ip: "103.106.32.230", port: 46319}, {ip: "103.106.33.254", port: 33843}, {ip: "103.106.34.10", port: 61784}, {ip: "103.106.34.65", port: 60490}, {ip: "103.107.77.5", port: 53281}, {ip: "103.108.144.139", port: 53281}, {ip: "103.108.88.118", port: 8080}, {ip: "103.108.88.158", port: 36552}, {ip: "103.109.57.218", port: 8080}, {ip: "103.109.57.65", port: 53281}, {ip: "103.109.58.242", port: 8080}, {ip: "103.111.13.10", port: 30501}, {ip: "103.112.129.106", port: 31094}, {ip: "103.112.129.82", port: 53281}, {ip: "103.112.170.68", port: 8080}, {ip: "103.112.204.10", port: 8080}, {ip: "103.112.204.14", port: 8080}, {ip: "103.112.60.38", port: 8080}, {ip: "103.112.63.225", port: 53281}, {ip: "103.114.10.177", port: 8080}, {ip: "103.114.10.250", port: 8080}, {ip: "103.115.100.118", port: 40714}, {ip: "103.116.116.178", port: 53281}, {ip: "103.116.164.41", port: 36965}, {ip: "103.116.164.45", port: 43127}, {ip: "103.116.164.50", port: 41397}, {ip: "103.118.76.129", port: 3128}, {ip: "103.118.76.54", port: 42999}, {ip: "103.122.253.188", port: 8080}, {ip: "103.14.27.166", port: 8080}, {ip: "103.15.245.26", port: 8080}, {ip: "103.16.73.170", port: 32802}, {ip: "103.19.130.34", port: 8080}, {ip: "103.192.158.251", port: 38204}, {ip: "103.195.204.73", port: 21776}, {ip: "103.197.48.90", port: 23500}, {ip: "103.197.49.106", port: 49688}, {ip: "103.198.168.29", port: 21776}, {ip: "103.200.38.110", port: 53281}, {ip: "103.213.237.46", port: 82}, {ip: "103.213.237.46", port: 83}, {ip: "103.214.200.6", port: 59008}, {ip: "103.216.57.105", port: 23500}, {ip: "103.216.59.81", port: 23500}, {ip: "103.218.24.113", port: 8080}, {ip: "103.218.24.161", port: 8080}, {ip: "103.218.24.97", port: 8080}, {ip: "103.218.25.1", port: 8080}, {ip: "103.218.25.161", port: 8080}, {ip: "103.218.25.217", port: 8080}, {ip: "103.218.25.41", port: 8080}, {ip: "103.218.26.110", port: 8080}, {ip: "103.218.26.201", port: 8080}, {ip: "103.218.26.204", port: 8080}, {ip: "103.218.27.201", port: 8080}, {ip: "103.218.27.221", port: 8080}, {ip: "103.218.27.25", port: 8080}, {ip: "103.218.27.254", port: 8080}, {ip: "103.218.27.49", port: 8080}, {ip: "103.220.204.101", port: 45199}, {ip: "103.225.94.46", port: 53240}, {ip: "103.228.0.238", port: 45328}, {ip: "103.228.2.162", port: 53281}, {ip: "103.229.47.28", port: 52454}, {ip: "103.229.87.12", port: 23500}, {ip: "103.229.87.226", port: 23500}, {ip: "103.230.60.150", port: 57774}, {ip: "103.230.62.194", port: 59738}, {ip: "103.231.229.90", port: 53281}, {ip: "103.234.25.162", port: 43423}, {ip: "103.234.26.179", port: 42377}, {ip: "103.234.27.106", port: 8080}, {ip: "103.239.252.233", port: 8080}, {ip: "103.239.252.50", port: 8080}, {ip: "103.239.253.193", port: 8080}, {ip: "103.239.254.252", port: 8080}, {ip: "103.239.254.70", port: 61967}, {ip: "103.239.255.170", port: 38146}, {ip: "103.239.255.242", port: 8080}, {ip: "103.240.248.98", port: 8080}, {ip: "103.243.82.234", port: 59215}, {ip: "103.248.236.8", port: 35110}, {ip: "103.25.120.134", port: 8080}, {ip: "103.250.68.193", port: 51370}, {ip: "103.254.167.122", port: 52145}, {ip: "103.254.167.209", port: 60401}, {ip: "103.254.167.250", port: 56858}, {ip: "103.254.94.116", port: 53877}, {ip: "103.254.94.125", port: 8080}, {ip: "103.254.94.158", port: 54281}, {ip: "103.255.30.34", port: 3128}, {ip: "103.255.30.34", port: 8080}, {ip: "103.26.247.102", port: 52656}, {ip: "103.26.247.106", port: 51652}, {ip: "103.36.100.234", port: 8080}, {ip: "103.36.100.234", port: 80}, {ip: "103.36.101.6", port: 23500}, {ip: "103.49.168.18", port: 38367}, {ip: "103.5.232.146", port: 8080}, {ip: "103.60.173.2", port: 8080}, {ip: "103.66.179.10", port: 34526}, {ip: "103.67.196.42", port: 8080}, {ip: "103.73.224.169", port: 23500}, {ip: "103.73.224.53", port: 23500}, {ip: "103.73.225.214", port: 23500}, {ip: "103.75.239.241", port: 50495}, {ip: "103.76.196.41", port: 8080}, {ip: "103.79.182.18", port: 48946}, {ip: "103.79.183.138", port: 58015}, {ip: "103.80.226.65", port: 53281}, {ip: "103.85.112.51", port: 53281}, {ip: "103.87.236.46", port: 41183}, {ip: "103.9.134.73", port: 65301}, {ip: "103.92.152.246", port: 47924}, {ip: "103.92.153.66", port: 50153}, {ip: "103.92.154.98", port: 44863}, {ip: "103.92.155.170", port: 53281}, {ip: "103.92.212.1", port: 52130}, {ip: "103.99.181.2", port: 8080}, {ip: "113.11.47.242", port: 40071}, {ip: "113.11.5.67", port: 40071}, {ip: "114.31.5.34", port: 52606}, {ip: "115.127.114.76", port: 32736}, {ip: "115.127.51.226", port: 42764}, {ip: "115.127.64.62", port: 39611}, {ip: "115.127.79.37", port: 50071}, {ip: "115.127.84.34", port: 35792}, {ip: "115.127.91.106", port: 8080}, {ip: "115.127.92.234", port: 31496}, {ip: "116.193.220.189", port: 48142}, {ip: "116.193.221.86", port: 50259}, {ip: "116.212.109.42", port: 31082}, {ip: "118.179.178.12", port: 33919}, {ip: "118.179.206.50", port: 8080}, {ip: "118.179.59.72", port: 8080}, {ip: "118.67.222.154", port: 30488}, {ip: "119.148.31.162", port: 34400}, {ip: "119.15.155.94", port: 8080}, {ip: "119.18.149.24", port: 42832}, {ip: "119.40.83.162", port: 8080}, {ip: "119.40.83.242", port: 8080}, {ip: "119.40.83.250", port: 8080}, {ip: "119.40.85.198", port: 36899}, {ip: "119.40.87.94", port: 31000}, {ip: "119.40.95.122", port: 8888}, {ip: "120.50.25.114", port: 58124}, {ip: "120.50.6.170", port: 33232}, {ip: "122.144.12.24", port: 45898}, {ip: "122.152.55.49", port: 52427}, {ip: "123.200.23.46", port: 56737}, {ip: "123.200.24.19", port: 53281}, {ip: "123.200.29.110", port: 23500}, {ip: "123.200.31.226", port: 53281}, {ip: "123.49.2.110", port: 58551}, {ip: "123.49.49.78", port: 41061}, {ip: "123.49.51.42", port: 55124}, {ip: "123.49.53.250", port: 32069}, {ip: "14.1.102.218", port: 8080}, {ip: "150.242.106.122", port: 34106}, {ip: "150.242.106.126", port: 34106}, {ip: "157.119.49.70", port: 53281}, {ip: "163.47.35.150", port: 49890}, {ip: "163.47.36.90", port: 3128}, {ip: "163.53.149.206", port: 21231}, {ip: "163.53.182.148", port: 60637}, {ip: "175.29.184.189", port: 42575}, {ip: "175.29.184.19", port: 35796}, {ip: "175.29.188.10", port: 55126}, {ip: "175.41.45.182", port: 39803}, {ip: "175.41.45.190", port: 39803}, {ip: "180.211.134.158", port: 23500}, {ip: "180.211.172.151", port: 42766}, {ip: "180.211.185.228", port: 8080}, {ip: "180.211.193.74", port: 40536}, {ip: "180.211.243.142", port: 53281}, {ip: "180.234.219.164", port: 50617}, {ip: "180.92.229.94", port: 32605}, {ip: "180.92.231.78", port: 37140}, {ip: "180.92.233.162", port: 54042}, {ip: "180.92.238.109", port: 23500}, {ip: "180.92.238.22", port: 8080}, {ip: "180.92.238.226", port: 53451}, {ip: "180.92.239.218", port: 41421}, {ip: "182.160.104.213", port: 8080}, {ip: "182.160.113.98", port: 55920}, {ip: "182.48.94.134", port: 39849}, {ip: "202.125.75.154", port: 45919}, {ip: "202.191.121.171", port: 53281}, {ip: "202.191.126.58", port: 23500}, {ip: "202.4.126.170", port: 8080}, {ip: "202.40.179.34", port: 47544}, {ip: "202.40.187.218", port: 39774}, {ip: "202.40.188.94", port: 32287}, {ip: "202.5.37.241", port: 33623}, {ip: "202.5.46.37", port: 8888}, {ip: "202.5.49.73", port: 23500}, {ip: "202.5.57.5", port: 61729}, {ip: "202.51.188.76", port: 8080}, {ip: "202.51.188.77", port: 8080}, {ip: "202.58.109.47", port: 43992}, {ip: "202.59.138.138", port: 8080}, {ip: "202.74.241.236", port: 8080}, {ip: "202.74.243.214", port: 61750}, {ip: "202.79.16.129", port: 60122}, {ip: "202.79.17.129", port: 60122}, {ip: "202.79.17.65", port: 60122}, {ip: "202.86.221.142", port: 40298}, {ip: "203.188.248.52", port: 23500}, {ip: "203.202.243.210", port: 8888}, {ip: "203.202.248.35", port: 80}, {ip: "203.202.253.186", port: 45448}, {ip: "203.76.220.226", port: 43329}, {ip: "203.83.170.66", port: 37682}, {ip: "203.83.174.210", port: 37623}, {ip: "203.83.178.178", port: 59429}, {ip: "203.83.182.86", port: 8080}, {ip: "203.83.189.157", port: 36882}, {ip: "203.95.220.178", port: 59667}, {ip: "203.95.221.222", port: 59838}, {ip: "203.95.222.206", port: 31323}, {ip: "203.95.222.210", port: 6969}, {ip: "223.25.252.22", port: 53281}, {ip: "223.27.113.155", port: 3128}, {ip: "223.27.113.241", port: 57181}, {ip: "223.29.212.101", port: 31200}, {ip: "27.123.254.182", port: 42413}, {ip: "27.123.255.82", port: 43129}, {ip: "27.147.134.194", port: 53776}, {ip: "27.147.136.178", port: 47678}, {ip: "27.147.137.210", port: 51386}, {ip: "27.147.142.78", port: 53281}, {ip: "27.147.146.78", port: 52220}, {ip: "27.147.149.146", port: 8080}, {ip: "27.147.151.50", port: 37954}, {ip: "27.147.155.189", port: 41813}, {ip: "27.147.164.10", port: 52344}, {ip: "27.147.183.238", port: 61501}, {ip: "27.147.212.38", port: 53281}, {ip: "27.147.217.154", port: 43252}, {ip: "27.147.219.102", port: 49464}, {ip: "43.229.209.102", port: 53281}, {ip: "43.229.209.14", port: 53281}, {ip: "43.239.73.30", port: 8080}, {ip: "43.239.74.137", port: 8080}, {ip: "43.239.75.137", port: 53886}, {ip: "43.239.75.189", port: 8080}, {ip: "43.240.103.113", port: 3128}, {ip: "43.240.103.252", port: 8080}, {ip: "43.245.194.178", port: 53036}, {ip: "43.245.194.182", port: 53036}, {ip: "43.246.202.33", port: 8080}, {ip: "43.246.202.37", port: 8080}, {ip: "45.113.133.6", port: 50611}, {ip: "45.120.115.110", port: 36079}, {ip: "45.123.42.121", port: 37309}, {ip: "45.125.220.137", port: 8080}, {ip: "45.125.221.239", port: 8080}, {ip: "45.125.222.12", port: 57980}, {ip: "45.125.223.10", port: 8080}, {ip: "45.125.223.57", port: 8080}, {ip: "45.125.223.81", port: 8080}, {ip: "45.125.223.97", port: 8080}, {ip: "45.248.147.177", port: 35654}, {ip: "45.248.147.230", port: 35654}, {ip: "45.249.102.21", port: 8080}, {ip: "45.249.102.29", port: 8080}, {ip: "45.249.103.209", port: 8080}, {ip: "45.249.103.247", port: 8080}, {ip: "45.251.228.122", port: 41418}, {ip: "45.251.56.74", port: 45801}, {ip: "45.251.57.115", port: 8080}, {ip: "45.251.59.2", port: 8080}, {ip: "45.64.132.137", port: 8080}, {ip: "45.64.132.137", port: 80}, {ip: "49.0.38.238", port: 53281}, {ip: "49.0.39.153", port: 53281}, {ip: "58.84.33.177", port: 60411}, {ip: "59.152.13.98", port: 8080}, {ip: "59.152.6.44", port: 8080}, {ip: "59.152.90.42", port: 8080}, {ip: "59.152.90.83", port: 8080}, {ip: "59.152.98.130", port: 8080}, {ip: "61.247.186.137", port: 8080}], - "MX" => [{ip: "131.72.230.151", port: 39954}, {ip: "148.217.94.54", port: 3128}, {ip: "148.243.240.155", port: 59093}, {ip: "148.243.247.51", port: 48283}, {ip: "148.243.37.101", port: 53281}, {ip: "168.121.240.13", port: 31756}, {ip: "177.233.7.75", port: 41294}, {ip: "177.234.0.218", port: 31584}, {ip: "177.234.2.58", port: 59293}, {ip: "177.242.104.102", port: 37040}, {ip: "177.244.28.170", port: 55578}, {ip: "177.244.28.77", port: 53281}, {ip: "177.244.41.154", port: 999}, {ip: "187.141.164.242", port: 31120}, {ip: "187.141.73.147", port: 53281}, {ip: "187.160.245.156", port: 3128}, {ip: "187.176.123.155", port: 43366}, {ip: "187.185.15.35", port: 53281}, {ip: "187.188.15.252", port: 999}, {ip: "187.188.15.253", port: 999}, {ip: "187.188.163.19", port: 999}, {ip: "187.188.163.26", port: 999}, {ip: "187.188.168.57", port: 999}, {ip: "187.188.211.82", port: 999}, {ip: "187.188.46.172", port: 53455}, {ip: "187.188.93.170", port: 61178}, {ip: "187.189.16.78", port: 999}, {ip: "187.189.226.220", port: 999}, {ip: "187.189.26.14", port: 59607}, {ip: "187.189.59.181", port: 41461}, {ip: "187.189.75.123", port: 53281}, {ip: "187.189.80.114", port: 3128}, {ip: "187.190.218.136", port: 3128}, {ip: "187.190.221.71", port: 3128}, {ip: "187.190.64.42", port: 47662}, {ip: "187.190.73.164", port: 46294}, {ip: "187.216.83.185", port: 8080}, {ip: "187.216.90.46", port: 53281}, {ip: "187.243.253.182", port: 33796}, {ip: "189.194.93.227", port: 41853}, {ip: "189.195.132.86", port: 43286}, {ip: "189.195.162.222", port: 53281}, {ip: "189.198.239.61", port: 51272}, {ip: "189.199.106.202", port: 8888}, {ip: "189.199.69.122", port: 58630}, {ip: "189.203.179.18", port: 8080}, {ip: "189.203.184.131", port: 30198}, {ip: "189.204.158.149", port: 57231}, {ip: "189.204.158.161", port: 8080}, {ip: "189.206.175.169", port: 44295}, {ip: "189.206.226.82", port: 40936}, {ip: "189.211.185.174", port: 45406}, {ip: "189.240.193.34", port: 51167}, {ip: "190.115.1.181", port: 60846}, {ip: "195.154.41.145", port: 60941}, {ip: "200.57.195.204", port: 30158}, {ip: "200.66.94.148", port: 8080}, {ip: "200.76.97.21", port: 55999}, {ip: "200.79.180.115", port: 8080}, {ip: "201.116.230.229", port: 42282}, {ip: "201.131.195.70", port: 49308}, {ip: "201.132.155.10", port: 8080}, {ip: "201.139.125.90", port: 21213}, {ip: "201.140.113.90", port: 37193}, {ip: "201.140.116.186", port: 8080}, {ip: "201.144.14.229", port: 53281}, {ip: "201.150.1.61", port: 8080}, {ip: "201.150.255.185", port: 3128}, {ip: "201.151.162.193", port: 8081}, {ip: "201.156.160.91", port: 34009}, {ip: "201.156.6.25", port: 40962}, {ip: "201.159.22.164", port: 33866}, {ip: "201.161.223.150", port: 39800}, {ip: "201.163.73.93", port: 53281}, {ip: "45.235.128.6", port: 60949}], - "PH" => [{ip: "103.252.32.174", port: 8080}, {ip: "103.86.187.242", port: 23500}, {ip: "116.50.208.114", port: 8080}, {ip: "122.54.101.69", port: 8080}, {ip: "122.54.105.143", port: 53281}, {ip: "122.54.20.218", port: 8090}, {ip: "122.54.65.150", port: 8080}, {ip: "122.55.250.90", port: 8080}, {ip: "122.55.48.131", port: 8080}, {ip: "125.5.20.134", port: 53281}, {ip: "130.105.131.163", port: 8080}, {ip: "146.88.77.51", port: 8080}, {ip: "180.232.77.107", port: 54002}, {ip: "182.18.200.92", port: 8080}, {ip: "202.57.35.74", port: 51412}, {ip: "202.57.47.122", port: 41890}, {ip: "202.57.54.226", port: 45222}, {ip: "203.160.182.115", port: 40552}, {ip: "203.177.41.30", port: 49887}, {ip: "219.90.87.91", port: 53281}, {ip: "43.255.216.138", port: 54384}, {ip: "45.64.122.210", port: 54892}, {ip: "58.69.12.210", port: 8080}, {ip: "61.9.82.34", port: 33326}], - "EG" => [{ip: "195.246.57.154", port: 8080}, {ip: "41.196.22.230", port: 8080}, {ip: "41.65.0.167", port: 8080}], - "VN" => [{ip: "1.55.240.156", port: 53281}, {ip: "101.99.23.136", port: 3128}, {ip: "103.15.51.160", port: 8080}, {ip: "103.90.227.194", port: 3128}, {ip: "113.160.158.49", port: 8080}, {ip: "113.161.128.169", port: 60427}, {ip: "113.161.149.45", port: 39356}, {ip: "113.161.161.143", port: 57967}, {ip: "113.161.173.10", port: 3128}, {ip: "113.161.35.108", port: 30028}, {ip: "113.164.176.189", port: 41187}, {ip: "113.164.176.19", port: 41187}, {ip: "113.164.79.177", port: 46281}, {ip: "113.190.235.50", port: 34619}, {ip: "115.77.191.180", port: 53281}, {ip: "115.78.160.247", port: 8080}, {ip: "115.78.225.211", port: 8080}, {ip: "116.105.225.104", port: 9090}, {ip: "117.2.155.29", port: 47228}, {ip: "117.2.17.26", port: 53281}, {ip: "117.2.22.41", port: 41973}, {ip: "117.4.145.16", port: 51487}, {ip: "117.4.242.109", port: 3128}, {ip: "118.69.219.185", port: 55184}, {ip: "118.69.61.212", port: 53281}, {ip: "118.70.116.227", port: 61651}, {ip: "118.70.12.171", port: 53281}, {ip: "118.70.219.124", port: 53281}, {ip: "118.70.81.253", port: 8080}, {ip: "123.31.47.8", port: 3128}, {ip: "125.234.113.170", port: 35720}, {ip: "125.234.121.222", port: 53281}, {ip: "14.161.14.64", port: 54752}, {ip: "163.44.206.148", port: 8888}, {ip: "203.205.29.106", port: 47773}, {ip: "203.205.52.51", port: 50015}, {ip: "221.121.12.238", port: 36077}, {ip: "27.2.7.59", port: 52148}, {ip: "27.72.244.198", port: 46506}, {ip: "27.72.56.239", port: 8080}, {ip: "27.72.72.48", port: 47729}, {ip: "27.72.72.5", port: 33975}], - "CD" => [{ip: "169.255.67.130", port: 55852}, {ip: "169.255.67.244", port: 55222}, {ip: "197.231.253.205", port: 8080}, {ip: "197.231.253.87", port: 47110}, {ip: "217.171.85.234", port: 61030}, {ip: "41.60.24.46", port: 8080}, {ip: "41.79.233.108", port: 8080}, {ip: "41.79.233.45", port: 8080}], - "TR" => [{ip: "151.80.65.175", port: 3128}, {ip: "176.235.132.106", port: 47793}, {ip: "176.235.170.182", port: 38098}, {ip: "176.235.171.170", port: 36127}, {ip: "176.235.182.100", port: 8080}, {ip: "176.235.182.95", port: 8080}, {ip: "176.235.186.242", port: 37043}, {ip: "178.250.92.18", port: 8080}, {ip: "178.250.92.190", port: 8080}, {ip: "185.136.205.57", port: 5836}, {ip: "185.136.205.60", port: 5836}, {ip: "185.195.252.254", port: 53127}, {ip: "185.203.170.92", port: 8080}, {ip: "185.203.170.94", port: 8080}, {ip: "185.203.170.95", port: 8080}, {ip: "185.250.241.62", port: 3128}, {ip: "185.250.241.64", port: 3128}, {ip: "185.250.241.68", port: 3128}, {ip: "185.252.40.136", port: 53281}, {ip: "185.51.36.152", port: 41258}, {ip: "185.71.118.109", port: 53143}, {ip: "185.82.222.56", port: 23}, {ip: "195.137.223.50", port: 41336}, {ip: "195.155.98.70", port: 52598}, {ip: "195.175.74.254", port: 8080}, {ip: "195.244.36.205", port: 39491}, {ip: "212.156.146.22", port: 40080}, {ip: "212.175.0.201", port: 49769}, {ip: "212.175.191.218", port: 41616}, {ip: "213.14.31.122", port: 44621}, {ip: "213.14.31.138", port: 40289}, {ip: "213.14.31.140", port: 40289}, {ip: "213.74.123.103", port: 38078}, {ip: "213.74.123.108", port: 33672}, {ip: "213.74.123.83", port: 41496}, {ip: "213.74.252.177", port: 8080}, {ip: "31.145.137.139", port: 31871}, {ip: "31.145.138.129", port: 31871}, {ip: "31.145.138.146", port: 34159}, {ip: "31.145.187.172", port: 30636}, {ip: "31.145.9.146", port: 53247}, {ip: "31.145.96.102", port: 60567}, {ip: "78.186.111.109", port: 8080}, {ip: "78.186.135.235", port: 48083}, {ip: "78.186.140.120", port: 61753}, {ip: "78.186.153.69", port: 55159}, {ip: "78.186.169.88", port: 8080}, {ip: "78.186.237.201", port: 42201}, {ip: "78.186.56.193", port: 57573}, {ip: "78.188.119.210", port: 37321}, {ip: "78.188.131.102", port: 30930}, {ip: "78.188.155.224", port: 38433}, {ip: "78.188.155.99", port: 8080}, {ip: "78.188.4.124", port: 34514}, {ip: "78.189.115.46", port: 45686}, {ip: "78.189.230.165", port: 48950}, {ip: "81.213.77.57", port: 36401}, {ip: "82.222.50.189", port: 9090}, {ip: "82.222.50.195", port: 9090}, {ip: "82.222.50.196", port: 9090}, {ip: "84.51.0.66", port: 8888}, {ip: "84.51.0.70", port: 53281}, {ip: "85.109.124.174", port: 32857}, {ip: "85.109.127.66", port: 61947}, {ip: "85.109.142.189", port: 35062}, {ip: "85.111.9.73", port: 32796}, {ip: "85.97.195.101", port: 59239}, {ip: "88.245.139.216", port: 44888}, {ip: "88.247.10.31", port: 8080}, {ip: "88.247.165.215", port: 51331}, {ip: "88.247.94.128", port: 36653}, {ip: "88.248.23.216", port: 36426}, {ip: "88.249.159.109", port: 34373}, {ip: "88.250.198.74", port: 8080}, {ip: "88.255.101.155", port: 53757}, {ip: "88.255.101.240", port: 8080}, {ip: "88.255.101.241", port: 8080}, {ip: "88.255.101.242", port: 8080}, {ip: "88.255.101.243", port: 8080}, {ip: "88.255.101.244", port: 8080}, {ip: "88.255.101.245", port: 8080}, {ip: "88.255.101.247", port: 8080}, {ip: "88.255.101.248", port: 8080}, {ip: "88.255.101.250", port: 8080}, {ip: "88.255.101.251", port: 8080}, {ip: "88.255.102.60", port: 23500}, {ip: "88.255.213.234", port: 8080}, {ip: "88.255.60.153", port: 31983}, {ip: "91.93.64.244", port: 49905}, {ip: "92.45.120.200", port: 32854}, {ip: "93.182.72.36", port: 8080}, {ip: "95.0.160.104", port: 3128}, {ip: "95.0.176.198", port: 8080}, {ip: "95.0.182.171", port: 55138}, {ip: "95.0.194.241", port: 9090}, {ip: "95.0.194.53", port: 39665}, {ip: "95.0.206.211", port: 23500}, {ip: "95.0.226.109", port: 48366}, {ip: "95.0.226.122", port: 36168}, {ip: "95.0.226.125", port: 35348}, {ip: "95.6.79.2", port: 44438}, {ip: "95.9.113.12", port: 52566}], + "GB" => [{ip: "147.135.206.233", port: 3128}, {ip: "167.114.180.102", port: 8080}, {ip: "176.35.250.108", port: 8080}, {ip: "5.148.128.44", port: 80}, {ip: "62.7.85.234", port: 8080}, {ip: "88.150.135.10", port: 36624}], + "DE" => [{ip: "138.201.223.250", port: 31288}, {ip: "138.68.73.59", port: 32574}, {ip: "159.69.211.173", port: 3128}, {ip: "173.249.43.105", port: 3128}, {ip: "212.202.244.90", port: 8080}, {ip: "5.56.18.35", port: 38827}], + "FR" => [{ip: "137.74.254.242", port: 3128}, {ip: "151.80.143.155", port: 53281}, {ip: "178.33.150.97", port: 3128}, {ip: "37.187.2.31", port: 3128}, {ip: "5.135.164.72", port: 3128}, {ip: "5.39.91.73", port: 3128}, {ip: "51.38.162.2", port: 32231}, {ip: "51.38.217.121", port: 808}, {ip: "51.75.109.81", port: 3128}, {ip: "51.75.109.82", port: 3128}, {ip: "51.75.109.83", port: 3128}, {ip: "51.75.109.84", port: 3128}, {ip: "51.75.109.86", port: 3128}, {ip: "51.75.109.88", port: 3128}, {ip: "51.75.109.90", port: 3128}, {ip: "62.210.167.3", port: 3128}, {ip: "90.63.218.232", port: 8080}, {ip: "91.134.165.198", port: 9999}], + "IN" => [{ip: "1.186.151.206", port: 36253}, {ip: "1.186.63.130", port: 39142}, {ip: "103.105.40.1", port: 16538}, {ip: "103.105.40.153", port: 16538}, {ip: "103.106.148.203", port: 60227}, {ip: "103.106.148.207", port: 51451}, {ip: "103.12.246.12", port: 8080}, {ip: "103.14.235.109", port: 8080}, {ip: "103.14.235.26", port: 8080}, {ip: "103.198.172.4", port: 50820}, {ip: "103.205.112.1", port: 23500}, {ip: "103.209.64.19", port: 6666}, {ip: "103.211.76.5", port: 8080}, {ip: "103.216.82.19", port: 6666}, {ip: "103.216.82.190", port: 6666}, {ip: "103.216.82.209", port: 54806}, {ip: "103.216.82.214", port: 6666}, {ip: "103.216.82.37", port: 6666}, {ip: "103.216.82.44", port: 8080}, {ip: "103.216.82.50", port: 53281}, {ip: "103.22.173.230", port: 8080}, {ip: "103.224.38.2", port: 83}, {ip: "103.226.142.90", port: 41386}, {ip: "103.236.114.38", port: 49638}, {ip: "103.240.161.107", port: 6666}, {ip: "103.240.161.108", port: 6666}, {ip: "103.240.161.109", port: 6666}, {ip: "103.240.161.59", port: 48809}, {ip: "103.245.198.101", port: 8080}, {ip: "103.250.148.82", port: 6666}, {ip: "103.251.58.51", port: 61489}, {ip: "103.253.169.115", port: 32731}, {ip: "103.253.211.182", port: 8080}, {ip: "103.253.211.182", port: 80}, {ip: "103.255.234.169", port: 39847}, {ip: "103.42.161.118", port: 8080}, {ip: "103.42.162.30", port: 8080}, {ip: "103.42.162.50", port: 8080}, {ip: "103.42.162.58", port: 8080}, {ip: "103.46.233.12", port: 83}, {ip: "103.46.233.13", port: 83}, {ip: "103.46.233.16", port: 83}, {ip: "103.46.233.17", port: 83}, {ip: "103.46.233.21", port: 83}, {ip: "103.46.233.23", port: 83}, {ip: "103.46.233.29", port: 81}, {ip: "103.46.233.29", port: 83}, {ip: "103.46.233.50", port: 83}, {ip: "103.47.153.87", port: 8080}, {ip: "103.47.66.2", port: 39804}, {ip: "103.49.53.1", port: 81}, {ip: "103.52.220.1", port: 49068}, {ip: "103.56.228.166", port: 53281}, {ip: "103.56.30.128", port: 8080}, {ip: "103.65.193.17", port: 50862}, {ip: "103.65.195.1", port: 33960}, {ip: "103.69.220.14", port: 3128}, {ip: "103.70.128.84", port: 8080}, {ip: "103.70.128.86", port: 8080}, {ip: "103.70.131.74", port: 8080}, {ip: "103.70.146.250", port: 59563}, {ip: "103.72.216.194", port: 38345}, {ip: "103.75.161.38", port: 21776}, {ip: "103.76.253.155", port: 3128}, {ip: "103.87.104.137", port: 8080}, {ip: "110.235.198.3", port: 57660}, {ip: "114.69.229.161", port: 8080}, {ip: "117.196.231.201", port: 37769}, {ip: "117.211.166.214", port: 3128}, {ip: "117.240.175.51", port: 3128}, {ip: "117.240.210.155", port: 53281}, {ip: "117.240.59.115", port: 36127}, {ip: "117.242.154.73", port: 33889}, {ip: "117.244.15.243", port: 3128}, {ip: "119.235.54.3", port: 8080}, {ip: "120.138.117.102", port: 59308}, {ip: "123.108.200.185", port: 83}, {ip: "123.108.200.217", port: 82}, {ip: "123.176.43.218", port: 40524}, {ip: "125.21.43.82", port: 8080}, {ip: "125.62.192.225", port: 82}, {ip: "125.62.192.33", port: 84}, {ip: "125.62.194.1", port: 83}, {ip: "125.62.213.134", port: 82}, {ip: "125.62.213.18", port: 83}, {ip: "125.62.213.201", port: 84}, {ip: "125.62.213.242", port: 83}, {ip: "125.62.214.185", port: 84}, {ip: "139.5.26.27", port: 53281}, {ip: "14.102.67.101", port: 30337}, {ip: "14.142.122.134", port: 8080}, {ip: "150.129.114.194", port: 6666}, {ip: "150.129.151.62", port: 6666}, {ip: "150.129.171.115", port: 6666}, {ip: "150.129.201.30", port: 6666}, {ip: "157.119.207.38", port: 53281}, {ip: "175.100.185.151", port: 53281}, {ip: "182.18.177.114", port: 56173}, {ip: "182.73.194.170", port: 8080}, {ip: "182.74.85.230", port: 51214}, {ip: "183.82.116.56", port: 8080}, {ip: "183.82.32.56", port: 49551}, {ip: "183.87.14.229", port: 53281}, {ip: "183.87.14.250", port: 44915}, {ip: "202.134.160.168", port: 8080}, {ip: "202.134.166.1", port: 8080}, {ip: "202.134.180.50", port: 8080}, {ip: "202.62.84.210", port: 53281}, {ip: "203.192.193.225", port: 8080}, {ip: "203.192.195.14", port: 31062}, {ip: "203.192.217.11", port: 8080}, {ip: "223.196.83.182", port: 53281}, {ip: "27.116.20.169", port: 36630}, {ip: "27.116.20.209", port: 36630}, {ip: "27.116.51.21", port: 36033}, {ip: "43.224.8.114", port: 50333}, {ip: "43.224.8.116", port: 6666}, {ip: "43.224.8.124", port: 6666}, {ip: "43.224.8.86", port: 6666}, {ip: "43.225.20.73", port: 8080}, {ip: "43.225.23.26", port: 8080}, {ip: "43.230.196.98", port: 36569}, {ip: "43.240.5.225", port: 31777}, {ip: "43.241.28.248", port: 8080}, {ip: "43.242.209.201", port: 8080}, {ip: "43.246.139.82", port: 8080}, {ip: "43.248.73.86", port: 53281}, {ip: "43.251.170.145", port: 54059}, {ip: "45.112.57.230", port: 61222}, {ip: "45.115.171.30", port: 47949}, {ip: "45.121.29.254", port: 54858}, {ip: "45.123.26.146", port: 53281}, {ip: "45.125.61.193", port: 32804}, {ip: "45.125.61.209", port: 32804}, {ip: "45.127.121.194", port: 53281}, {ip: "45.250.226.14", port: 3128}, {ip: "45.250.226.38", port: 8080}, {ip: "45.250.226.47", port: 8080}, {ip: "45.250.226.55", port: 8080}, {ip: "49.249.251.86", port: 53281}], + "CN" => [{ip: "182.61.170.45", port: 3128}], + "RU" => [{ip: "109.106.139.225", port: 45689}, {ip: "109.161.48.228", port: 53281}, {ip: "109.167.224.198", port: 51919}, {ip: "109.172.57.250", port: 23500}, {ip: "109.194.2.126", port: 61822}, {ip: "109.195.150.128", port: 37564}, {ip: "109.201.96.171", port: 31773}, {ip: "109.201.97.204", port: 41258}, {ip: "109.201.97.235", port: 39125}, {ip: "109.206.140.74", port: 45991}, {ip: "109.206.148.31", port: 30797}, {ip: "109.69.75.5", port: 46347}, {ip: "109.71.181.170", port: 53983}, {ip: "109.74.132.190", port: 42663}, {ip: "109.74.143.45", port: 36529}, {ip: "109.75.140.158", port: 59916}, {ip: "109.95.84.114", port: 52125}, {ip: "130.255.12.24", port: 31004}, {ip: "134.19.147.72", port: 44812}, {ip: "134.90.181.7", port: 54353}, {ip: "145.255.6.171", port: 31252}, {ip: "146.120.227.3", port: 8080}, {ip: "149.255.112.194", port: 48968}, {ip: "158.46.127.222", port: 52574}, {ip: "158.46.43.144", port: 39120}, {ip: "158.58.130.185", port: 50016}, {ip: "158.58.132.12", port: 56962}, {ip: "158.58.133.106", port: 41258}, {ip: "158.58.133.13", port: 21213}, {ip: "176.101.0.47", port: 34471}, {ip: "176.101.89.226", port: 33470}, {ip: "176.106.12.65", port: 30120}, {ip: "176.107.80.110", port: 58901}, {ip: "176.110.121.9", port: 46322}, {ip: "176.110.121.90", port: 21776}, {ip: "176.111.97.18", port: 8080}, {ip: "176.112.106.230", port: 33996}, {ip: "176.112.110.40", port: 61142}, {ip: "176.113.116.70", port: 55589}, {ip: "176.113.27.192", port: 47337}, {ip: "176.115.197.118", port: 8080}, {ip: "176.117.255.182", port: 53100}, {ip: "176.120.200.69", port: 44331}, {ip: "176.124.123.93", port: 41258}, {ip: "176.192.124.98", port: 60787}, {ip: "176.192.5.238", port: 61227}, {ip: "176.192.8.206", port: 39422}, {ip: "176.193.15.94", port: 8080}, {ip: "176.196.195.170", port: 48129}, {ip: "176.196.198.154", port: 35252}, {ip: "176.196.238.234", port: 44648}, {ip: "176.196.239.46", port: 35656}, {ip: "176.196.246.6", port: 53281}, {ip: "176.196.84.138", port: 51336}, {ip: "176.197.145.246", port: 32649}, {ip: "176.197.99.142", port: 47278}, {ip: "176.215.1.108", port: 60339}, {ip: "176.215.170.147", port: 35604}, {ip: "176.56.23.14", port: 35340}, {ip: "176.62.185.54", port: 53883}, {ip: "176.74.13.110", port: 8080}, {ip: "178.130.29.226", port: 53295}, {ip: "178.170.254.178", port: 46788}, {ip: "178.213.13.136", port: 53281}, {ip: "178.218.104.8", port: 49707}, {ip: "178.219.183.163", port: 8080}, {ip: "178.237.180.34", port: 57307}, {ip: "178.57.101.212", port: 38020}, {ip: "178.57.101.235", port: 31309}, {ip: "178.64.190.133", port: 46688}, {ip: "178.75.1.111", port: 50411}, {ip: "178.75.27.131", port: 41879}, {ip: "185.13.35.178", port: 40654}, {ip: "185.15.189.67", port: 30215}, {ip: "185.175.119.137", port: 41258}, {ip: "185.18.111.194", port: 41258}, {ip: "185.19.176.237", port: 53281}, {ip: "185.190.40.115", port: 31747}, {ip: "185.216.195.134", port: 61287}, {ip: "185.22.172.94", port: 10010}, {ip: "185.22.172.94", port: 1448}, {ip: "185.22.174.65", port: 10010}, {ip: "185.22.174.65", port: 1448}, {ip: "185.23.64.100", port: 3130}, {ip: "185.23.82.39", port: 59248}, {ip: "185.233.94.105", port: 59288}, {ip: "185.233.94.146", port: 57736}, {ip: "185.3.68.54", port: 53500}, {ip: "185.32.120.177", port: 60724}, {ip: "185.34.20.164", port: 53700}, {ip: "185.34.23.43", port: 63238}, {ip: "185.51.60.141", port: 39935}, {ip: "185.61.92.228", port: 33060}, {ip: "185.61.93.67", port: 49107}, {ip: "185.7.233.66", port: 53504}, {ip: "185.72.225.10", port: 56285}, {ip: "185.75.5.158", port: 60819}, {ip: "185.9.86.186", port: 39345}, {ip: "188.133.136.10", port: 47113}, {ip: "188.168.75.254", port: 56899}, {ip: "188.170.41.6", port: 60332}, {ip: "188.187.189.142", port: 38264}, {ip: "188.234.151.103", port: 8080}, {ip: "188.235.11.88", port: 57143}, {ip: "188.235.137.196", port: 23500}, {ip: "188.244.175.2", port: 8080}, {ip: "188.255.82.136", port: 53281}, {ip: "188.43.4.117", port: 60577}, {ip: "188.68.95.166", port: 41258}, {ip: "188.92.242.180", port: 52048}, {ip: "188.93.242.213", port: 49774}, {ip: "192.162.193.243", port: 36910}, {ip: "192.162.214.11", port: 41258}, {ip: "193.106.170.133", port: 38591}, {ip: "193.232.113.244", port: 40412}, {ip: "193.232.234.130", port: 61932}, {ip: "193.242.177.105", port: 53281}, {ip: "193.242.178.50", port: 52376}, {ip: "193.242.178.90", port: 8080}, {ip: "193.33.101.152", port: 34611}, {ip: "194.114.128.149", port: 61213}, {ip: "194.135.15.146", port: 59328}, {ip: "194.135.216.178", port: 56805}, {ip: "194.135.75.74", port: 41258}, {ip: "194.146.201.67", port: 53281}, {ip: "194.186.18.46", port: 56408}, {ip: "194.186.20.62", port: 21231}, {ip: "194.190.171.214", port: 43960}, {ip: "194.9.27.82", port: 42720}, {ip: "195.133.232.58", port: 41733}, {ip: "195.14.114.116", port: 59530}, {ip: "195.14.114.24", port: 56897}, {ip: "195.158.250.97", port: 41582}, {ip: "195.16.48.142", port: 36083}, {ip: "195.191.183.169", port: 47238}, {ip: "195.206.45.112", port: 53281}, {ip: "195.208.172.70", port: 8080}, {ip: "195.209.141.67", port: 31927}, {ip: "195.209.176.2", port: 8080}, {ip: "195.210.144.166", port: 30088}, {ip: "195.211.160.88", port: 44464}, {ip: "195.218.144.182", port: 31705}, {ip: "195.46.168.147", port: 8080}, {ip: "195.9.188.78", port: 53281}, {ip: "195.9.209.10", port: 35242}, {ip: "195.9.223.246", port: 52098}, {ip: "195.9.237.66", port: 8080}, {ip: "195.9.91.66", port: 33199}, {ip: "195.91.132.20", port: 19600}, {ip: "195.98.183.82", port: 30953}, {ip: "212.104.82.246", port: 36495}, {ip: "212.119.229.18", port: 33852}, {ip: "212.13.97.122", port: 30466}, {ip: "212.19.21.19", port: 53264}, {ip: "212.19.5.157", port: 58442}, {ip: "212.19.8.223", port: 30281}, {ip: "212.19.8.239", port: 55602}, {ip: "212.192.202.207", port: 4550}, {ip: "212.22.80.224", port: 34822}, {ip: "212.26.247.178", port: 38418}, {ip: "212.33.228.161", port: 37971}, {ip: "212.33.243.83", port: 38605}, {ip: "212.34.53.126", port: 44369}, {ip: "212.5.107.81", port: 56481}, {ip: "212.7.230.7", port: 51405}, {ip: "212.77.138.161", port: 41258}, {ip: "213.108.221.201", port: 32800}, {ip: "213.109.7.135", port: 59918}, {ip: "213.128.9.204", port: 35549}, {ip: "213.134.196.12", port: 38723}, {ip: "213.168.37.86", port: 8080}, {ip: "213.187.118.184", port: 53281}, {ip: "213.21.23.98", port: 53281}, {ip: "213.210.67.166", port: 53281}, {ip: "213.234.0.242", port: 56503}, {ip: "213.247.192.131", port: 41258}, {ip: "213.251.226.208", port: 56900}, {ip: "213.33.155.80", port: 44387}, {ip: "213.33.199.194", port: 36411}, {ip: "213.33.224.82", port: 8080}, {ip: "213.59.153.19", port: 53281}, {ip: "217.10.45.103", port: 8080}, {ip: "217.107.197.39", port: 33628}, {ip: "217.116.60.66", port: 21231}, {ip: "217.195.87.58", port: 41258}, {ip: "217.197.239.54", port: 34463}, {ip: "217.74.161.42", port: 34175}, {ip: "217.8.84.76", port: 46378}, {ip: "31.131.67.14", port: 8080}, {ip: "31.132.127.142", port: 35432}, {ip: "31.132.218.252", port: 32423}, {ip: "31.173.17.118", port: 51317}, {ip: "31.193.124.70", port: 53281}, {ip: "31.210.211.147", port: 8080}, {ip: "31.220.183.217", port: 53281}, {ip: "31.29.212.82", port: 35066}, {ip: "31.42.254.24", port: 30912}, {ip: "31.47.189.14", port: 38473}, {ip: "37.113.129.98", port: 41665}, {ip: "37.192.103.164", port: 34835}, {ip: "37.192.194.50", port: 50165}, {ip: "37.192.99.151", port: 51417}, {ip: "37.205.83.91", port: 35888}, {ip: "37.233.85.155", port: 53281}, {ip: "37.235.167.66", port: 53281}, {ip: "37.235.65.2", port: 47816}, {ip: "37.235.67.178", port: 34450}, {ip: "37.9.134.133", port: 41262}, {ip: "46.150.174.90", port: 53281}, {ip: "46.151.156.198", port: 56013}, {ip: "46.16.226.10", port: 8080}, {ip: "46.163.131.55", port: 48306}, {ip: "46.173.191.51", port: 53281}, {ip: "46.174.222.61", port: 34977}, {ip: "46.180.96.79", port: 42319}, {ip: "46.181.151.79", port: 39386}, {ip: "46.21.74.130", port: 8080}, {ip: "46.227.162.98", port: 51558}, {ip: "46.229.187.169", port: 53281}, {ip: "46.229.67.198", port: 47437}, {ip: "46.243.179.221", port: 41598}, {ip: "46.254.217.54", port: 53281}, {ip: "46.32.68.188", port: 39707}, {ip: "46.39.224.112", port: 36765}, {ip: "46.63.162.171", port: 8080}, {ip: "46.73.33.253", port: 8080}, {ip: "5.128.32.12", port: 51959}, {ip: "5.129.155.3", port: 51390}, {ip: "5.129.16.27", port: 48935}, {ip: "5.141.81.65", port: 61853}, {ip: "5.16.15.234", port: 8080}, {ip: "5.167.51.235", port: 8080}, {ip: "5.167.96.238", port: 3128}, {ip: "5.19.165.235", port: 30793}, {ip: "5.35.93.157", port: 31773}, {ip: "5.59.137.90", port: 8888}, {ip: "5.8.207.160", port: 57192}, {ip: "62.122.97.66", port: 59143}, {ip: "62.148.151.253", port: 53570}, {ip: "62.152.85.158", port: 31156}, {ip: "62.165.54.153", port: 55522}, {ip: "62.173.140.14", port: 8080}, {ip: "62.173.155.206", port: 41258}, {ip: "62.182.206.19", port: 37715}, {ip: "62.213.14.166", port: 8080}, {ip: "62.76.123.224", port: 8080}, {ip: "77.221.220.133", port: 44331}, {ip: "77.232.153.248", port: 60950}, {ip: "77.233.10.37", port: 54210}, {ip: "77.244.27.109", port: 47554}, {ip: "77.37.142.203", port: 53281}, {ip: "77.39.29.29", port: 49243}, {ip: "77.75.6.34", port: 8080}, {ip: "77.87.102.7", port: 42601}, {ip: "77.94.121.212", port: 36896}, {ip: "77.94.121.51", port: 45293}, {ip: "78.110.154.177", port: 59888}, {ip: "78.140.201.226", port: 8090}, {ip: "78.153.4.122", port: 9001}, {ip: "78.156.225.170", port: 41258}, {ip: "78.156.243.146", port: 59730}, {ip: "78.29.14.201", port: 39001}, {ip: "78.81.24.112", port: 8080}, {ip: "78.85.36.203", port: 8080}, {ip: "79.104.219.125", port: 3128}, {ip: "79.104.55.134", port: 8080}, {ip: "79.137.181.170", port: 8080}, {ip: "79.173.124.194", port: 47832}, {ip: "79.173.124.207", port: 53281}, {ip: "79.174.186.168", port: 45710}, {ip: "79.175.51.13", port: 54853}, {ip: "79.175.57.77", port: 55477}, {ip: "80.234.107.118", port: 56952}, {ip: "80.237.6.1", port: 34880}, {ip: "80.243.14.182", port: 49320}, {ip: "80.251.48.215", port: 45157}, {ip: "80.254.121.66", port: 41055}, {ip: "80.254.125.236", port: 80}, {ip: "80.72.121.185", port: 52379}, {ip: "80.89.133.210", port: 3128}, {ip: "80.91.17.113", port: 41258}, {ip: "81.162.61.166", port: 40392}, {ip: "81.163.57.121", port: 41258}, {ip: "81.163.57.46", port: 41258}, {ip: "81.163.62.136", port: 41258}, {ip: "81.23.112.98", port: 55269}, {ip: "81.23.118.106", port: 60427}, {ip: "81.23.177.245", port: 8080}, {ip: "81.24.126.166", port: 8080}, {ip: "81.30.216.147", port: 41258}, {ip: "81.95.131.10", port: 44292}, {ip: "82.114.125.22", port: 8080}, {ip: "82.151.208.20", port: 8080}, {ip: "83.221.216.110", port: 47326}, {ip: "83.246.139.24", port: 8080}, {ip: "83.97.108.8", port: 41258}, {ip: "84.22.154.76", port: 8080}, {ip: "84.52.110.36", port: 38674}, {ip: "84.52.74.194", port: 8080}, {ip: "84.52.77.227", port: 41806}, {ip: "84.52.79.166", port: 43548}, {ip: "84.52.84.157", port: 44331}, {ip: "84.52.88.125", port: 32666}, {ip: "85.113.48.148", port: 8080}, {ip: "85.113.49.220", port: 8080}, {ip: "85.12.193.210", port: 58470}, {ip: "85.15.179.5", port: 8080}, {ip: "85.173.244.102", port: 53281}, {ip: "85.174.227.52", port: 59280}, {ip: "85.192.184.133", port: 8080}, {ip: "85.192.184.133", port: 80}, {ip: "85.21.240.193", port: 55820}, {ip: "85.21.63.219", port: 53281}, {ip: "85.235.190.18", port: 42494}, {ip: "85.237.56.193", port: 8080}, {ip: "85.91.119.6", port: 8080}, {ip: "86.102.116.30", port: 8080}, {ip: "86.110.30.146", port: 38109}, {ip: "87.117.3.129", port: 3128}, {ip: "87.225.108.195", port: 8080}, {ip: "87.228.103.111", port: 8080}, {ip: "87.228.103.43", port: 8080}, {ip: "87.229.143.10", port: 48872}, {ip: "87.249.205.103", port: 8080}, {ip: "87.249.21.193", port: 43079}, {ip: "87.255.13.217", port: 8080}, {ip: "88.147.159.167", port: 53281}, {ip: "88.200.225.32", port: 38583}, {ip: "88.204.59.177", port: 32666}, {ip: "88.84.209.69", port: 30819}, {ip: "88.87.72.72", port: 8080}, {ip: "88.87.79.20", port: 8080}, {ip: "88.87.91.163", port: 48513}, {ip: "88.87.93.20", port: 33277}, {ip: "89.109.12.82", port: 47972}, {ip: "89.109.21.43", port: 9090}, {ip: "89.109.239.183", port: 41041}, {ip: "89.109.54.137", port: 36469}, {ip: "89.17.37.218", port: 52957}, {ip: "89.189.130.103", port: 32626}, {ip: "89.189.159.214", port: 42530}, {ip: "89.189.174.121", port: 52636}, {ip: "89.23.18.29", port: 53281}, {ip: "89.249.251.21", port: 3128}, {ip: "89.250.149.114", port: 60981}, {ip: "89.250.17.209", port: 8080}, {ip: "89.250.19.173", port: 8080}, {ip: "90.150.87.172", port: 81}, {ip: "90.154.125.173", port: 33078}, {ip: "90.188.38.81", port: 60585}, {ip: "90.189.151.183", port: 32601}, {ip: "91.103.208.114", port: 57063}, {ip: "91.122.100.222", port: 44331}, {ip: "91.122.207.229", port: 8080}, {ip: "91.144.139.93", port: 3128}, {ip: "91.144.142.19", port: 44617}, {ip: "91.146.16.54", port: 57902}, {ip: "91.190.116.194", port: 38783}, {ip: "91.190.80.100", port: 31659}, {ip: "91.190.85.97", port: 34286}, {ip: "91.203.36.188", port: 8080}, {ip: "91.205.131.102", port: 8080}, {ip: "91.205.146.25", port: 37501}, {ip: "91.210.94.212", port: 52635}, {ip: "91.213.23.110", port: 8080}, {ip: "91.215.22.51", port: 53305}, {ip: "91.217.42.3", port: 8080}, {ip: "91.217.42.4", port: 8080}, {ip: "91.220.135.146", port: 41258}, {ip: "91.222.167.213", port: 38057}, {ip: "91.226.140.71", port: 33199}, {ip: "91.235.7.216", port: 59067}, {ip: "92.124.195.22", port: 3128}, {ip: "92.126.193.180", port: 8080}, {ip: "92.241.110.223", port: 53281}, {ip: "92.252.240.1", port: 53281}, {ip: "92.255.164.187", port: 3128}, {ip: "92.255.195.57", port: 53281}, {ip: "92.255.229.146", port: 55785}, {ip: "92.255.5.2", port: 41012}, {ip: "92.38.32.36", port: 56113}, {ip: "92.39.138.98", port: 31150}, {ip: "92.51.16.155", port: 46202}, {ip: "92.55.59.63", port: 33030}, {ip: "93.170.112.200", port: 47995}, {ip: "93.183.86.185", port: 53281}, {ip: "93.188.45.157", port: 8080}, {ip: "93.81.246.5", port: 53281}, {ip: "93.91.112.247", port: 41258}, {ip: "94.127.217.66", port: 40115}, {ip: "94.154.85.214", port: 8080}, {ip: "94.180.106.94", port: 32767}, {ip: "94.180.249.187", port: 38051}, {ip: "94.230.243.6", port: 8080}, {ip: "94.232.57.231", port: 51064}, {ip: "94.24.244.170", port: 48936}, {ip: "94.242.55.108", port: 10010}, {ip: "94.242.55.108", port: 1448}, {ip: "94.242.57.136", port: 10010}, {ip: "94.242.57.136", port: 1448}, {ip: "94.242.58.108", port: 10010}, {ip: "94.242.58.108", port: 1448}, {ip: "94.242.58.14", port: 10010}, {ip: "94.242.58.14", port: 1448}, {ip: "94.242.58.142", port: 10010}, {ip: "94.242.58.142", port: 1448}, {ip: "94.242.59.245", port: 10010}, {ip: "94.242.59.245", port: 1448}, {ip: "94.247.241.70", port: 53640}, {ip: "94.247.62.165", port: 33176}, {ip: "94.253.13.228", port: 54935}, {ip: "94.253.14.187", port: 55045}, {ip: "94.28.94.154", port: 46966}, {ip: "94.73.217.125", port: 40858}, {ip: "95.140.19.9", port: 8080}, {ip: "95.140.20.94", port: 33994}, {ip: "95.154.137.66", port: 41258}, {ip: "95.154.159.119", port: 44242}, {ip: "95.154.82.254", port: 52484}, {ip: "95.161.157.227", port: 43170}, {ip: "95.161.182.146", port: 33877}, {ip: "95.161.189.26", port: 61522}, {ip: "95.165.163.146", port: 8888}, {ip: "95.165.172.90", port: 60496}, {ip: "95.165.182.18", port: 38950}, {ip: "95.165.203.222", port: 33805}, {ip: "95.165.244.122", port: 58162}, {ip: "95.167.123.54", port: 58664}, {ip: "95.167.241.242", port: 49636}, {ip: "95.171.1.92", port: 35956}, {ip: "95.172.52.230", port: 35989}, {ip: "95.181.35.30", port: 40804}, {ip: "95.181.56.178", port: 39144}, {ip: "95.181.75.228", port: 53281}, {ip: "95.188.74.194", port: 57122}, {ip: "95.189.112.214", port: 35508}, {ip: "95.31.10.247", port: 30711}, {ip: "95.31.197.77", port: 41651}, {ip: "95.31.2.199", port: 33632}, {ip: "95.71.125.50", port: 49882}, {ip: "95.73.62.13", port: 32185}, {ip: "95.79.36.55", port: 44861}, {ip: "95.79.55.196", port: 53281}, {ip: "95.79.99.148", port: 3128}, {ip: "95.80.65.39", port: 43555}, {ip: "95.80.93.44", port: 41258}, {ip: "95.80.98.41", port: 8080}, {ip: "95.83.156.250", port: 58438}, {ip: "95.84.128.25", port: 33765}, {ip: "95.84.154.73", port: 57423}], + "CA" => [{ip: "144.217.161.149", port: 8080}, {ip: "24.37.9.6", port: 54154}, {ip: "54.39.138.144", port: 3128}, {ip: "54.39.138.145", port: 3128}, {ip: "54.39.138.151", port: 3128}, {ip: "54.39.138.152", port: 3128}, {ip: "54.39.138.153", port: 3128}, {ip: "54.39.138.154", port: 3128}, {ip: "54.39.138.155", port: 3128}, {ip: "54.39.138.156", port: 3128}, {ip: "54.39.138.157", port: 3128}, {ip: "54.39.53.104", port: 3128}, {ip: "66.70.167.113", port: 3128}, {ip: "66.70.167.116", port: 3128}, {ip: "66.70.167.117", port: 3128}, {ip: "66.70.167.119", port: 3128}, {ip: "66.70.167.120", port: 3128}, {ip: "66.70.167.125", port: 3128}, {ip: "66.70.188.148", port: 3128}, {ip: "70.35.213.229", port: 36127}, {ip: "70.65.233.174", port: 8080}, {ip: "72.139.24.66", port: 38861}, {ip: "74.15.191.160", port: 41564}], + "JP" => [{ip: "47.91.20.67", port: 8080}, {ip: "61.118.35.94", port: 55725}], + "IT" => [{ip: "109.70.201.97", port: 53517}, {ip: "176.31.82.212", port: 8080}, {ip: "185.132.228.118", port: 55583}, {ip: "185.49.58.88", port: 56006}, {ip: "185.94.89.179", port: 41258}, {ip: "213.203.134.10", port: 41258}, {ip: "217.61.172.12", port: 41369}, {ip: "46.232.143.126", port: 41258}, {ip: "46.232.143.253", port: 41258}, {ip: "93.67.154.125", port: 8080}, {ip: "93.67.154.125", port: 80}, {ip: "95.169.95.242", port: 53803}], + "TH" => [{ip: "1.10.184.166", port: 57330}, {ip: "1.10.186.100", port: 55011}, {ip: "1.10.186.209", port: 32431}, {ip: "1.10.186.245", port: 34360}, {ip: "1.10.186.93", port: 53711}, {ip: "1.10.187.118", port: 62000}, {ip: "1.10.187.34", port: 51635}, {ip: "1.10.187.43", port: 38715}, {ip: "1.10.188.181", port: 51093}, {ip: "1.10.188.83", port: 31940}, {ip: "1.10.188.95", port: 30593}, {ip: "1.10.189.58", port: 48564}, {ip: "1.179.157.237", port: 46178}, {ip: "1.179.164.213", port: 8080}, {ip: "1.179.198.37", port: 8080}, {ip: "1.20.100.99", port: 53794}, {ip: "1.20.101.221", port: 55707}, {ip: "1.20.101.254", port: 35394}, {ip: "1.20.101.80", port: 36234}, {ip: "1.20.102.133", port: 40296}, {ip: "1.20.103.13", port: 40544}, {ip: "1.20.103.56", port: 55422}, {ip: "1.20.96.234", port: 53142}, {ip: "1.20.97.54", port: 60122}, {ip: "1.20.99.63", port: 32123}, {ip: "101.108.92.20", port: 8080}, {ip: "101.109.143.71", port: 36127}, {ip: "101.51.141.110", port: 42860}, {ip: "101.51.141.60", port: 60417}, {ip: "103.246.17.237", port: 3128}, {ip: "110.164.73.131", port: 8080}, {ip: "110.164.87.80", port: 35844}, {ip: "110.77.134.106", port: 8080}, {ip: "113.53.29.92", port: 47297}, {ip: "113.53.83.192", port: 32780}, {ip: "113.53.83.195", port: 35686}, {ip: "113.53.91.214", port: 8080}, {ip: "115.87.27.0", port: 53276}, {ip: "118.172.211.3", port: 58535}, {ip: "118.172.211.40", port: 30430}, {ip: "118.174.196.174", port: 23500}, {ip: "118.174.196.203", port: 23500}, {ip: "118.174.220.107", port: 41222}, {ip: "118.174.220.110", port: 39025}, {ip: "118.174.220.115", port: 41011}, {ip: "118.174.220.118", port: 59556}, {ip: "118.174.220.136", port: 55041}, {ip: "118.174.220.163", port: 31561}, {ip: "118.174.220.168", port: 47455}, {ip: "118.174.220.231", port: 40924}, {ip: "118.174.220.238", port: 46326}, {ip: "118.174.234.13", port: 53084}, {ip: "118.174.234.26", port: 41926}, {ip: "118.174.234.32", port: 57403}, {ip: "118.174.234.59", port: 59149}, {ip: "118.174.234.68", port: 42626}, {ip: "118.174.234.83", port: 38006}, {ip: "118.175.207.104", port: 38959}, {ip: "118.175.244.111", port: 8080}, {ip: "118.175.93.207", port: 50738}, {ip: "122.154.38.53", port: 8080}, {ip: "122.154.59.6", port: 8080}, {ip: "122.154.72.102", port: 8080}, {ip: "122.155.222.98", port: 3128}, {ip: "124.121.22.121", port: 61699}, {ip: "125.24.156.16", port: 44321}, {ip: "125.25.165.105", port: 33850}, {ip: "125.25.165.111", port: 40808}, {ip: "125.25.165.42", port: 47221}, {ip: "125.25.201.14", port: 30100}, {ip: "125.26.99.135", port: 55637}, {ip: "125.26.99.141", port: 38537}, {ip: "125.26.99.148", port: 31818}, {ip: "134.236.247.137", port: 8080}, {ip: "159.192.98.224", port: 3128}, {ip: "171.100.2.154", port: 8080}, {ip: "171.100.9.126", port: 49163}, {ip: "180.180.156.116", port: 48431}, {ip: "180.180.156.46", port: 48507}, {ip: "180.180.156.87", port: 36628}, {ip: "180.180.218.204", port: 51565}, {ip: "180.180.8.34", port: 8080}, {ip: "182.52.238.125", port: 58861}, {ip: "182.52.74.73", port: 36286}, {ip: "182.52.74.76", port: 34084}, {ip: "182.52.74.77", port: 34825}, {ip: "182.52.74.78", port: 48708}, {ip: "182.52.90.45", port: 53799}, {ip: "182.53.206.155", port: 34307}, {ip: "182.53.206.43", port: 45330}, {ip: "182.53.206.49", port: 54228}, {ip: "183.88.212.141", port: 8080}, {ip: "183.88.212.184", port: 8080}, {ip: "183.88.213.85", port: 8080}, {ip: "183.88.214.47", port: 8080}, {ip: "184.82.128.211", port: 8080}, {ip: "202.183.201.13", port: 8081}, {ip: "202.29.20.151", port: 43083}, {ip: "203.150.172.151", port: 8080}, {ip: "27.131.157.94", port: 8080}, {ip: "27.145.100.22", port: 8080}, {ip: "27.145.100.243", port: 8080}, {ip: "49.231.196.114", port: 53281}, {ip: "58.97.72.83", port: 8080}, {ip: "61.19.145.66", port: 8080}], + "ES" => [{ip: "185.198.184.14", port: 48122}, {ip: "185.26.226.241", port: 36012}, {ip: "194.224.188.82", port: 3128}, {ip: "195.235.68.61", port: 3128}, {ip: "195.53.237.122", port: 3128}, {ip: "195.53.86.82", port: 3128}, {ip: "213.96.245.47", port: 8080}, {ip: "217.125.71.214", port: 33950}, {ip: "62.14.178.72", port: 53281}, {ip: "80.35.254.42", port: 53281}, {ip: "81.33.4.214", port: 61711}, {ip: "83.175.238.170", port: 53281}, {ip: "85.217.137.77", port: 3128}, {ip: "90.170.205.178", port: 33680}, {ip: "93.156.177.91", port: 53281}, {ip: "95.60.152.139", port: 37995}], + "AE" => [{ip: "178.32.5.90", port: 36159}], + "KR" => [{ip: "112.217.219.179", port: 3128}, {ip: "114.141.229.2", port: 58115}, {ip: "121.139.218.165", port: 31409}, {ip: "122.49.112.2", port: 38592}, {ip: "61.42.18.132", port: 53281}], + "BR" => [{ip: "128.201.97.157", port: 53281}, {ip: "128.201.97.158", port: 53281}, {ip: "131.0.246.157", port: 35252}, {ip: "131.161.26.90", port: 8080}, {ip: "131.72.143.100", port: 41396}, {ip: "138.0.24.66", port: 53281}, {ip: "138.121.130.50", port: 50600}, {ip: "138.121.155.127", port: 61932}, {ip: "138.121.32.133", port: 23492}, {ip: "138.185.176.63", port: 53281}, {ip: "138.204.233.190", port: 53281}, {ip: "138.204.233.242", port: 53281}, {ip: "138.219.71.74", port: 52688}, {ip: "138.36.107.24", port: 41184}, {ip: "138.94.115.166", port: 8080}, {ip: "143.0.188.161", port: 53281}, {ip: "143.202.218.135", port: 8080}, {ip: "143.208.2.42", port: 53281}, {ip: "143.208.79.223", port: 8080}, {ip: "143.255.52.102", port: 40687}, {ip: "143.255.52.116", port: 57856}, {ip: "143.255.52.117", port: 37279}, {ip: "144.217.22.128", port: 8080}, {ip: "168.0.8.225", port: 8080}, {ip: "168.0.8.55", port: 8080}, {ip: "168.121.139.54", port: 40056}, {ip: "168.181.168.23", port: 53281}, {ip: "168.181.170.198", port: 31935}, {ip: "168.232.198.25", port: 32009}, {ip: "168.232.198.35", port: 42267}, {ip: "168.232.207.145", port: 46342}, {ip: "170.0.104.107", port: 60337}, {ip: "170.0.112.2", port: 50359}, {ip: "170.0.112.229", port: 50359}, {ip: "170.238.118.107", port: 34314}, {ip: "170.239.144.9", port: 3128}, {ip: "170.247.29.138", port: 8080}, {ip: "170.81.237.36", port: 37124}, {ip: "170.84.51.74", port: 53281}, {ip: "170.84.60.222", port: 42981}, {ip: "177.10.202.67", port: 8080}, {ip: "177.101.60.86", port: 80}, {ip: "177.103.231.211", port: 55091}, {ip: "177.12.80.50", port: 50556}, {ip: "177.131.13.9", port: 20183}, {ip: "177.135.178.115", port: 42510}, {ip: "177.135.248.75", port: 20183}, {ip: "177.184.206.238", port: 39508}, {ip: "177.185.148.46", port: 58623}, {ip: "177.200.83.238", port: 8080}, {ip: "177.21.24.146", port: 666}, {ip: "177.220.188.120", port: 47556}, {ip: "177.220.188.213", port: 8080}, {ip: "177.222.229.243", port: 23500}, {ip: "177.234.161.42", port: 8080}, {ip: "177.36.11.241", port: 3128}, {ip: "177.36.12.193", port: 23500}, {ip: "177.37.199.175", port: 49608}, {ip: "177.39.187.70", port: 37315}, {ip: "177.44.175.199", port: 8080}, {ip: "177.46.148.126", port: 3128}, {ip: "177.46.148.142", port: 3128}, {ip: "177.47.194.98", port: 21231}, {ip: "177.5.98.58", port: 20183}, {ip: "177.52.55.19", port: 60901}, {ip: "177.54.200.66", port: 57526}, {ip: "177.55.255.74", port: 37147}, {ip: "177.67.217.94", port: 53281}, {ip: "177.73.248.6", port: 54381}, {ip: "177.73.4.234", port: 23500}, {ip: "177.75.143.211", port: 35955}, {ip: "177.75.161.206", port: 3128}, {ip: "177.75.86.49", port: 20183}, {ip: "177.8.216.106", port: 8080}, {ip: "177.8.216.114", port: 8080}, {ip: "177.8.37.247", port: 56052}, {ip: "177.84.216.17", port: 50569}, {ip: "177.85.200.254", port: 53095}, {ip: "177.87.169.1", port: 53281}, {ip: "179.107.97.178", port: 3128}, {ip: "179.109.144.25", port: 8080}, {ip: "179.109.193.137", port: 53281}, {ip: "179.189.125.206", port: 8080}, {ip: "179.97.30.46", port: 53100}, {ip: "186.192.195.220", port: 38983}, {ip: "186.193.11.226", port: 48999}, {ip: "186.193.26.106", port: 3128}, {ip: "186.208.220.248", port: 3128}, {ip: "186.209.243.142", port: 3128}, {ip: "186.209.243.233", port: 3128}, {ip: "186.211.106.227", port: 34334}, {ip: "186.211.160.178", port: 36756}, {ip: "186.215.133.170", port: 20183}, {ip: "186.216.81.21", port: 31773}, {ip: "186.219.214.13", port: 32708}, {ip: "186.224.94.6", port: 48957}, {ip: "186.225.97.246", port: 43082}, {ip: "186.226.171.163", port: 48698}, {ip: "186.226.179.2", port: 56089}, {ip: "186.226.234.67", port: 33834}, {ip: "186.228.147.58", port: 20183}, {ip: "186.233.97.163", port: 8888}, {ip: "186.248.170.82", port: 53281}, {ip: "186.249.213.101", port: 53482}, {ip: "186.249.213.65", port: 52018}, {ip: "186.250.213.225", port: 60774}, {ip: "186.250.96.70", port: 8080}, {ip: "186.250.96.77", port: 8080}, {ip: "187.1.43.246", port: 53396}, {ip: "187.108.36.250", port: 20183}, {ip: "187.108.38.10", port: 20183}, {ip: "187.109.36.251", port: 20183}, {ip: "187.109.40.9", port: 20183}, {ip: "187.109.56.101", port: 20183}, {ip: "187.111.90.89", port: 53281}, {ip: "187.115.10.50", port: 20183}, {ip: "187.19.62.7", port: 59010}, {ip: "187.33.79.61", port: 33469}, {ip: "187.35.158.150", port: 38872}, {ip: "187.44.1.167", port: 8080}, {ip: "187.45.127.87", port: 20183}, {ip: "187.45.156.109", port: 8080}, {ip: "187.5.218.215", port: 20183}, {ip: "187.58.65.225", port: 3128}, {ip: "187.63.111.37", port: 3128}, {ip: "187.72.166.10", port: 8080}, {ip: "187.73.68.14", port: 53281}, {ip: "187.84.177.6", port: 45903}, {ip: "187.84.191.170", port: 43936}, {ip: "187.87.204.210", port: 45597}, {ip: "187.87.39.247", port: 31793}, {ip: "189.1.16.162", port: 23500}, {ip: "189.113.124.162", port: 8080}, {ip: "189.124.195.185", port: 37318}, {ip: "189.3.196.18", port: 61595}, {ip: "189.37.33.59", port: 35532}, {ip: "189.7.49.66", port: 42700}, {ip: "189.90.194.35", port: 30843}, {ip: "189.90.248.75", port: 8080}, {ip: "189.91.231.43", port: 3128}, {ip: "191.239.243.156", port: 3128}, {ip: "191.240.154.246", port: 23500}, {ip: "191.240.156.154", port: 36127}, {ip: "191.240.99.142", port: 9090}, {ip: "191.241.226.230", port: 53281}, {ip: "191.241.228.74", port: 20183}, {ip: "191.241.228.78", port: 20183}, {ip: "191.241.33.238", port: 39188}, {ip: "191.241.36.170", port: 8080}, {ip: "191.241.36.218", port: 3128}, {ip: "191.242.182.132", port: 8081}, {ip: "191.243.221.130", port: 3128}, {ip: "191.255.207.231", port: 20183}, {ip: "191.36.192.196", port: 3128}, {ip: "191.36.244.230", port: 51377}, {ip: "191.5.0.79", port: 53281}, {ip: "191.6.228.6", port: 53281}, {ip: "191.7.193.18", port: 38133}, {ip: "191.7.20.134", port: 3128}, {ip: "192.140.91.173", port: 20183}, {ip: "200.150.86.138", port: 44677}, {ip: "200.155.36.185", port: 3128}, {ip: "200.155.36.188", port: 3128}, {ip: "200.155.39.41", port: 3128}, {ip: "200.174.158.26", port: 34112}, {ip: "200.187.177.105", port: 20183}, {ip: "200.187.87.138", port: 20183}, {ip: "200.192.252.201", port: 8080}, {ip: "200.192.255.102", port: 8080}, {ip: "200.203.144.2", port: 50262}, {ip: "200.229.238.42", port: 20183}, {ip: "200.233.134.85", port: 43172}, {ip: "200.233.136.177", port: 20183}, {ip: "200.241.44.3", port: 20183}, {ip: "200.255.122.170", port: 8080}, {ip: "200.255.122.174", port: 8080}, {ip: "201.12.21.57", port: 8080}, {ip: "201.131.224.21", port: 56200}, {ip: "201.182.223.16", port: 37492}, {ip: "201.20.89.126", port: 8080}, {ip: "201.22.95.10", port: 8080}, {ip: "201.57.167.34", port: 8080}, {ip: "201.59.200.246", port: 80}, {ip: "201.6.167.178", port: 3128}, {ip: "201.90.36.194", port: 3128}, {ip: "45.226.20.6", port: 8080}, {ip: "45.234.139.129", port: 20183}, {ip: "45.234.200.18", port: 53281}, {ip: "45.235.87.4", port: 51996}, {ip: "45.6.136.38", port: 53281}, {ip: "45.6.80.131", port: 52080}, {ip: "45.6.93.10", port: 8080}, {ip: "45.71.108.162", port: 53281}], + "PK" => [{ip: "103.18.243.154", port: 8080}, {ip: "110.36.218.126", port: 36651}, {ip: "110.36.234.210", port: 8080}, {ip: "110.39.162.74", port: 53281}, {ip: "110.39.174.58", port: 8080}, {ip: "111.68.108.34", port: 8080}, {ip: "125.209.116.182", port: 31653}, {ip: "125.209.78.21", port: 8080}, {ip: "125.209.82.78", port: 35087}, {ip: "180.92.156.150", port: 8080}, {ip: "202.142.158.114", port: 8080}, {ip: "202.147.173.10", port: 8080}, {ip: "202.147.173.10", port: 80}, {ip: "202.69.38.82", port: 8080}, {ip: "203.128.16.126", port: 59538}, {ip: "203.128.16.154", port: 33002}, {ip: "27.255.4.170", port: 8080}], + "ID" => [{ip: "101.128.68.113", port: 8080}, {ip: "101.255.116.113", port: 53281}, {ip: "101.255.120.170", port: 6969}, {ip: "101.255.121.74", port: 8080}, {ip: "101.255.124.242", port: 8080}, {ip: "101.255.124.242", port: 80}, {ip: "101.255.56.138", port: 53560}, {ip: "103.10.171.132", port: 41043}, {ip: "103.10.81.172", port: 80}, {ip: "103.108.158.3", port: 48196}, {ip: "103.111.219.159", port: 53281}, {ip: "103.111.54.26", port: 49781}, {ip: "103.111.54.74", port: 8080}, {ip: "103.19.110.177", port: 8080}, {ip: "103.2.146.66", port: 49089}, {ip: "103.206.168.177", port: 53281}, {ip: "103.206.253.58", port: 49573}, {ip: "103.21.92.254", port: 33929}, {ip: "103.226.49.83", port: 23500}, {ip: "103.227.147.142", port: 37581}, {ip: "103.23.101.58", port: 8080}, {ip: "103.24.107.2", port: 8181}, {ip: "103.245.19.222", port: 53281}, {ip: "103.247.122.38", port: 8080}, {ip: "103.247.218.166", port: 3128}, {ip: "103.248.219.26", port: 53634}, {ip: "103.253.2.165", port: 33543}, {ip: "103.253.2.168", port: 51229}, {ip: "103.253.2.174", port: 30827}, {ip: "103.28.114.134", port: 8080}, {ip: "103.28.220.73", port: 53281}, {ip: "103.30.246.47", port: 3128}, {ip: "103.31.45.169", port: 57655}, {ip: "103.41.122.14", port: 53281}, {ip: "103.75.101.97", port: 8080}, {ip: "103.76.17.151", port: 23500}, {ip: "103.76.50.181", port: 8080}, {ip: "103.76.50.181", port: 80}, {ip: "103.76.50.182", port: 8080}, {ip: "103.78.74.170", port: 3128}, {ip: "103.78.80.194", port: 33442}, {ip: "103.8.122.5", port: 53297}, {ip: "103.80.236.107", port: 53281}, {ip: "103.80.238.203", port: 53281}, {ip: "103.86.140.74", port: 59538}, {ip: "103.94.122.254", port: 8080}, {ip: "103.94.125.244", port: 41508}, {ip: "103.94.169.19", port: 8080}, {ip: "103.94.7.254", port: 53281}, {ip: "106.0.51.50", port: 17385}, {ip: "110.93.13.202", port: 34881}, {ip: "112.78.37.6", port: 54791}, {ip: "114.199.110.58", port: 55898}, {ip: "114.199.112.170", port: 23500}, {ip: "114.199.123.194", port: 8080}, {ip: "114.57.33.162", port: 46935}, {ip: "114.57.33.214", port: 8080}, {ip: "114.6.197.254", port: 8080}, {ip: "114.7.15.146", port: 8080}, {ip: "114.7.162.254", port: 53281}, {ip: "115.124.75.226", port: 53990}, {ip: "115.124.75.228", port: 3128}, {ip: "117.102.78.42", port: 8080}, {ip: "117.102.93.251", port: 8080}, {ip: "117.102.94.186", port: 8080}, {ip: "117.102.94.186", port: 80}, {ip: "117.103.2.249", port: 58276}, {ip: "117.54.13.174", port: 34190}, {ip: "117.74.124.129", port: 8088}, {ip: "118.97.100.83", port: 35220}, {ip: "118.97.191.162", port: 80}, {ip: "118.97.191.203", port: 8080}, {ip: "118.97.36.18", port: 8080}, {ip: "118.97.73.85", port: 53281}, {ip: "118.99.105.226", port: 8080}, {ip: "119.252.168.53", port: 53281}, {ip: "122.248.45.35", port: 53281}, {ip: "122.50.6.186", port: 8080}, {ip: "122.50.6.186", port: 80}, {ip: "123.231.226.114", port: 47562}, {ip: "123.255.202.83", port: 32523}, {ip: "124.158.164.195", port: 8080}, {ip: "124.81.99.30", port: 3128}, {ip: "137.59.162.10", port: 3128}, {ip: "139.0.29.20", port: 59532}, {ip: "139.255.123.194", port: 4550}, {ip: "139.255.16.171", port: 31773}, {ip: "139.255.17.2", port: 47421}, {ip: "139.255.19.162", port: 42371}, {ip: "139.255.7.81", port: 53281}, {ip: "139.255.91.115", port: 8080}, {ip: "139.255.92.26", port: 53281}, {ip: "158.140.181.140", port: 54041}, {ip: "160.202.40.20", port: 55655}, {ip: "175.103.42.147", port: 8080}, {ip: "180.178.98.198", port: 8080}, {ip: "180.250.101.146", port: 8080}, {ip: "182.23.107.212", port: 3128}, {ip: "182.23.2.101", port: 49833}, {ip: "182.23.7.226", port: 8080}, {ip: "182.253.209.203", port: 3128}, {ip: "183.91.66.210", port: 80}, {ip: "202.137.10.179", port: 57338}, {ip: "202.137.25.53", port: 3128}, {ip: "202.137.25.8", port: 8080}, {ip: "202.138.242.76", port: 4550}, {ip: "202.138.249.202", port: 43108}, {ip: "202.148.2.254", port: 8000}, {ip: "202.162.201.94", port: 53281}, {ip: "202.165.47.26", port: 8080}, {ip: "202.43.167.130", port: 8080}, {ip: "202.51.126.10", port: 53281}, {ip: "202.59.171.164", port: 58567}, {ip: "202.93.128.98", port: 3128}, {ip: "203.142.72.114", port: 808}, {ip: "203.153.117.65", port: 54144}, {ip: "203.189.89.1", port: 53281}, {ip: "203.77.239.18", port: 37002}, {ip: "203.99.123.25", port: 61502}, {ip: "220.247.168.163", port: 53281}, {ip: "220.247.173.154", port: 53281}, {ip: "220.247.174.206", port: 53445}, {ip: "222.124.131.211", port: 47343}, {ip: "222.124.173.146", port: 53281}, {ip: "222.124.2.131", port: 8080}, {ip: "222.124.2.186", port: 8080}, {ip: "222.124.215.187", port: 38913}, {ip: "222.124.221.179", port: 53281}, {ip: "223.25.101.242", port: 59504}, {ip: "223.25.97.62", port: 8080}, {ip: "223.25.99.38", port: 80}, {ip: "27.111.44.202", port: 80}, {ip: "27.111.47.3", port: 51144}, {ip: "36.37.124.234", port: 36179}, {ip: "36.37.124.235", port: 36179}, {ip: "36.37.81.135", port: 8080}, {ip: "36.37.89.98", port: 32323}, {ip: "36.66.217.179", port: 8080}, {ip: "36.66.98.6", port: 53281}, {ip: "36.67.143.183", port: 48746}, {ip: "36.67.206.187", port: 8080}, {ip: "36.67.32.87", port: 8080}, {ip: "36.67.93.220", port: 3128}, {ip: "36.67.93.220", port: 80}, {ip: "36.89.10.51", port: 34115}, {ip: "36.89.119.149", port: 8080}, {ip: "36.89.157.23", port: 37728}, {ip: "36.89.181.155", port: 60165}, {ip: "36.89.188.11", port: 39507}, {ip: "36.89.194.113", port: 37811}, {ip: "36.89.226.254", port: 8081}, {ip: "36.89.232.138", port: 23500}, {ip: "36.89.39.10", port: 3128}, {ip: "36.89.65.253", port: 60997}, {ip: "43.243.141.114", port: 8080}, {ip: "43.245.184.202", port: 41102}, {ip: "43.245.184.238", port: 80}, {ip: "66.96.233.225", port: 35053}, {ip: "66.96.237.253", port: 8080}], + "BD" => [{ip: "103.103.88.91", port: 8080}, {ip: "103.106.119.154", port: 8080}, {ip: "103.106.236.1", port: 8080}, {ip: "103.106.236.41", port: 8080}, {ip: "103.108.144.139", port: 53281}, {ip: "103.109.57.218", port: 8080}, {ip: "103.109.58.242", port: 8080}, {ip: "103.112.129.106", port: 31094}, {ip: "103.112.129.82", port: 53281}, {ip: "103.114.10.177", port: 8080}, {ip: "103.114.10.250", port: 8080}, {ip: "103.15.245.26", port: 8080}, {ip: "103.195.204.73", port: 21776}, {ip: "103.197.49.106", port: 49688}, {ip: "103.198.168.29", port: 21776}, {ip: "103.214.200.6", port: 59008}, {ip: "103.218.25.161", port: 8080}, {ip: "103.218.25.41", port: 8080}, {ip: "103.218.26.204", port: 8080}, {ip: "103.218.27.221", port: 8080}, {ip: "103.231.229.90", port: 53281}, {ip: "103.239.252.233", port: 8080}, {ip: "103.239.252.50", port: 8080}, {ip: "103.239.253.193", port: 8080}, {ip: "103.250.68.193", port: 51370}, {ip: "103.5.232.146", port: 8080}, {ip: "103.73.224.53", port: 23500}, {ip: "103.9.134.73", port: 65301}, {ip: "113.11.47.242", port: 40071}, {ip: "113.11.5.67", port: 40071}, {ip: "114.31.5.34", port: 52606}, {ip: "115.127.51.226", port: 42764}, {ip: "115.127.64.62", port: 39611}, {ip: "115.127.91.106", port: 8080}, {ip: "119.40.85.198", port: 36899}, {ip: "123.200.29.110", port: 23500}, {ip: "123.49.51.42", port: 55124}, {ip: "163.47.36.90", port: 3128}, {ip: "180.211.134.158", port: 23500}, {ip: "180.211.193.74", port: 40536}, {ip: "180.92.238.226", port: 53451}, {ip: "182.160.104.213", port: 8080}, {ip: "202.191.126.58", port: 23500}, {ip: "202.4.126.170", port: 8080}, {ip: "202.5.37.241", port: 33623}, {ip: "202.5.57.5", port: 61729}, {ip: "202.79.17.65", port: 60122}, {ip: "203.188.248.52", port: 23500}, {ip: "27.147.146.78", port: 52220}, {ip: "27.147.164.10", port: 52344}, {ip: "27.147.212.38", port: 53281}, {ip: "27.147.217.154", port: 43252}, {ip: "27.147.219.102", port: 49464}, {ip: "43.239.74.137", port: 8080}, {ip: "43.240.103.252", port: 8080}, {ip: "45.125.223.57", port: 8080}, {ip: "45.125.223.81", port: 8080}, {ip: "45.251.228.122", port: 41418}, {ip: "45.64.132.137", port: 8080}, {ip: "45.64.132.137", port: 80}, {ip: "61.247.186.137", port: 8080}], + "MX" => [{ip: "148.217.94.54", port: 3128}, {ip: "177.244.28.77", port: 53281}, {ip: "187.141.73.147", port: 53281}, {ip: "187.185.15.35", port: 53281}, {ip: "187.188.46.172", port: 53455}, {ip: "187.216.83.185", port: 8080}, {ip: "187.216.90.46", port: 53281}, {ip: "187.243.253.182", port: 33796}, {ip: "189.195.132.86", port: 43286}, {ip: "189.204.158.161", port: 8080}, {ip: "200.79.180.115", port: 8080}, {ip: "201.140.113.90", port: 37193}, {ip: "201.144.14.229", port: 53281}, {ip: "201.163.73.93", port: 53281}], + "PH" => [{ip: "103.86.187.242", port: 23500}, {ip: "122.54.101.69", port: 8080}, {ip: "122.54.65.150", port: 8080}, {ip: "125.5.20.134", port: 53281}, {ip: "146.88.77.51", port: 8080}, {ip: "182.18.200.92", port: 8080}, {ip: "219.90.87.91", port: 53281}, {ip: "58.69.12.210", port: 8080}], + "EG" => [{ip: "41.65.0.167", port: 8080}], + "VN" => [{ip: "1.55.240.156", port: 53281}, {ip: "101.99.23.136", port: 3128}, {ip: "103.15.51.160", port: 8080}, {ip: "113.161.128.169", port: 60427}, {ip: "113.161.161.143", port: 57967}, {ip: "113.161.173.10", port: 3128}, {ip: "113.161.35.108", port: 30028}, {ip: "113.164.79.177", port: 46281}, {ip: "113.190.235.50", port: 34619}, {ip: "115.78.160.247", port: 8080}, {ip: "117.2.155.29", port: 47228}, {ip: "117.2.17.26", port: 53281}, {ip: "117.2.22.41", port: 41973}, {ip: "117.4.145.16", port: 51487}, {ip: "118.69.219.185", port: 55184}, {ip: "118.69.61.212", port: 53281}, {ip: "118.70.116.227", port: 61651}, {ip: "118.70.219.124", port: 53281}, {ip: "221.121.12.238", port: 36077}, {ip: "27.2.7.59", port: 52148}], + "CD" => [{ip: "41.79.233.45", port: 8080}], + "TR" => [{ip: "151.80.65.175", port: 3128}, {ip: "176.235.186.242", port: 37043}, {ip: "178.250.92.18", port: 8080}, {ip: "185.203.170.92", port: 8080}, {ip: "185.203.170.94", port: 8080}, {ip: "185.203.170.95", port: 8080}, {ip: "185.51.36.152", port: 41258}, {ip: "195.137.223.50", port: 41336}, {ip: "195.155.98.70", port: 52598}, {ip: "212.156.146.22", port: 40080}, {ip: "213.14.31.122", port: 44621}, {ip: "31.145.137.139", port: 31871}, {ip: "31.145.138.129", port: 31871}, {ip: "31.145.138.146", port: 34159}, {ip: "31.145.187.172", port: 30636}, {ip: "78.188.4.124", port: 34514}, {ip: "88.248.23.216", port: 36426}, {ip: "93.182.72.36", port: 8080}, {ip: "95.0.194.241", port: 9090}], } From 9698988be3814e84cb8bfe1bf1d9fda86c7f7de0 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Fri, 8 Feb 2019 09:49:40 -0600 Subject: [PATCH 104/108] Filter video streams to avoid duplicates in DASH player --- src/invidious.cr | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/invidious.cr b/src/invidious.cr index 87305db6..72ac8caf 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -3530,7 +3530,12 @@ get "/api/manifest/dash/id/:id" do |env| begin video = get_video(id, PG_DB, proxies, region: region) rescue ex : VideoRedirect - next env.redirect "/api/manifest/dash/id/#{ex.message}" + url = "/api/manifest/dash/id/#{ex.message}" + if local + url += "?local=true" + end + + next env.redirect url rescue ex halt env, status_code: 403 end @@ -3560,8 +3565,8 @@ get "/api/manifest/dash/id/:id" do |env| end end - video_streams = video.video_streams(adaptive_fmts).select { |stream| stream["type"].starts_with? "video/mp4" } audio_streams = video.audio_streams(adaptive_fmts).select { |stream| stream["type"].starts_with? "audio/mp4" } + video_streams = video.video_streams(adaptive_fmts).select { |stream| stream["type"].starts_with? "video/mp4" }.uniq { |stream| stream["size"] } manifest = XML.build(indent: " ", encoding: "UTF-8") do |xml| xml.element("MPD", "xmlns": "urn:mpeg:dash:schema:mpd:2011", @@ -3570,9 +3575,7 @@ get "/api/manifest/dash/id/:id" do |env| xml.element("Period") do xml.element("AdaptationSet", mimeType: "audio/mp4", startWithSAP: 1, subsegmentAlignment: true) do audio_streams.each do |fmt| - mimetype = fmt["type"].split(";")[0] codecs = fmt["type"].split("codecs=")[1].strip('"') - fmt_type = mimetype.split("/")[0] bandwidth = fmt["bitrate"] itag = fmt["itag"] url = fmt["url"] @@ -3591,7 +3594,6 @@ get "/api/manifest/dash/id/:id" do |env| xml.element("AdaptationSet", mimeType: "video/mp4", startWithSAP: 1, subsegmentAlignment: true, scanType: "progressive") do video_streams.each do |fmt| - mimetype = fmt["type"].split(";") codecs = fmt["type"].split("codecs=")[1].strip('"') bandwidth = fmt["bitrate"] itag = fmt["itag"] From 3cce74d3640d53e4a317981065c8760b38ce33e1 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Fri, 8 Feb 2019 10:34:32 -0600 Subject: [PATCH 105/108] Add feed menu to popular, top, and trending --- src/invidious/views/popular.ecr | 25 +++++++++++++++++++++++++ src/invidious/views/top.ecr | 25 +++++++++++++++++++++++++ src/invidious/views/trending.ecr | 25 +++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/src/invidious/views/popular.ecr b/src/invidious/views/popular.ecr index 8ce1c161..8d67241f 100644 --- a/src/invidious/views/popular.ecr +++ b/src/invidious/views/popular.ecr @@ -1,7 +1,32 @@ <% content_for "header" do %> +"> <%= translate(locale, "Popular") %> - Invidious <% end %> + +
<% popular_videos.each_slice(4) do |slice| %> <% slice.each do |item| %> diff --git a/src/invidious/views/top.ecr b/src/invidious/views/top.ecr index c120e57c..ea5679c4 100644 --- a/src/invidious/views/top.ecr +++ b/src/invidious/views/top.ecr @@ -1,7 +1,32 @@ <% content_for "header" do %> +"> <%= translate(locale, "Top") %> - Invidious <% end %> + +
<% top_videos.each_slice(4) do |slice| %> <% slice.each do |item| %> diff --git a/src/invidious/views/trending.ecr b/src/invidious/views/trending.ecr index 82d03b07..a3db4de3 100644 --- a/src/invidious/views/trending.ecr +++ b/src/invidious/views/trending.ecr @@ -1,7 +1,32 @@ <% content_for "header" do %> +"> <%= translate(locale, "Trending") %> - Invidious <% end %> + +
From 7a9ef0d664c9d8d4eec879fadeb823568877bf28 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 9 Feb 2019 10:15:14 -0600 Subject: [PATCH 106/108] Add produce_channel_playlists_url --- spec/helpers_spec.cr | 4 +- src/invidious/channels.cr | 3 +- src/invidious/helpers/utils.cr | 12 ++-- src/invidious/playlists.cr | 111 +++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 9 deletions(-) diff --git a/spec/helpers_spec.cr b/spec/helpers_spec.cr index fddf55a5..6f33babd 100644 --- a/spec/helpers_spec.cr +++ b/spec/helpers_spec.cr @@ -16,9 +16,9 @@ describe "Helpers" do produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw", page: 20).should eq("/browse_ajax?continuation=4qmFsgJEEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaKEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0l5TUElM0QlM0Q%3D&gl=US&hl=en") - produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", auto_generated: true).should eq("/browse_ajax?continuation=4qmFsgJIEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaLEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQTJlZ294TlRRNU5qQXpOelE1&gl=US&hl=en") + produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", auto_generated: true).should eq("/browse_ajax?continuation=4qmFsgJIEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaLEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQTJlZ294TlRVeU1ESXlPVFE1&gl=US&hl=en") - produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", page: 20, auto_generated: true, sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJOEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaMkVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQTJlZ294TkRrNU5Ea3hOelE1R0FFJTNE&gl=US&hl=en") + produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", page: 20, auto_generated: true, sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJOEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaMkVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQTJlZ294TlRBeU1UY3dNVFE1R0FFJTNE&gl=US&hl=en") end end diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr index 28fbdcd6..956450d5 100644 --- a/src/invidious/channels.cr +++ b/src/invidious/channels.cr @@ -218,7 +218,8 @@ def produce_channel_videos_url(ucid, page = 1, auto_generated = nil, sort_by = " meta.write(Bytes[0x6a, 0x00]) meta.write(Bytes[0xb8, 0x01, 0x00]) - meta.write(Bytes[0x20, switch, 0x7a, page.size]) + meta.write(Bytes[0x20, switch]) + meta.write(Bytes[0x7a, page.size]) meta.print(page) case sort_by diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 282e8ce5..ef2e35dd 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -240,21 +240,21 @@ def get_referer(env, fallback = "/") end def read_var_int(bytes) - numRead = 0 + num_read = 0 result = 0 - read = bytes[numRead] + read = bytes[num_read] if bytes.size == 1 result = bytes[0].to_i32 else while ((read & 0b10000000) != 0) - read = bytes[numRead].to_u64 + read = bytes[num_read].to_u64 value = (read & 0b01111111) - result |= (value << (7 * numRead)) + result |= (value << (7 * num_read)) - numRead += 1 - if numRead > 5 + num_read += 1 + if num_read > 5 raise "VarInt is too big" end end diff --git a/src/invidious/playlists.cr b/src/invidious/playlists.cr index 28f2e4ce..220a0ef7 100644 --- a/src/invidious/playlists.cr +++ b/src/invidious/playlists.cr @@ -161,6 +161,117 @@ def produce_playlist_url(id, index) return url end +def produce_channel_playlists_url(ucid, cursor, sort = "newest") + cursor = Base64.urlsafe_encode(cursor, false) + + meta = IO::Memory.new + meta.write(Bytes[0x12, 0x09]) + meta.print("playlists") + + # TODO: Look at 0x01, 0x00 + case sort + when "oldest", "oldest_created" + meta.write(Bytes[0x18, 0x02]) + when "newest", "newest_created" + meta.write(Bytes[0x18, 0x03]) + when "last", "last_added" + meta.write(Bytes[0x18, 0x04]) + end + + meta.write(Bytes[0x20, 0x01]) + meta.write(Bytes[0x30, 0x02]) + meta.write(Bytes[0x38, 0x01]) + meta.write(Bytes[0x60, 0x01]) + meta.write(Bytes[0x6a, 0x00]) + + meta.write(Bytes[0x7a, cursor.size]) + meta.print(cursor) + + meta.write(Bytes[0xb8, 0x01, 0x00]) + + meta.rewind + meta = Base64.urlsafe_encode(meta.to_slice) + meta = URI.escape(meta) + + continuation = IO::Memory.new + continuation.write(Bytes[0x12, ucid.size]) + continuation.print(ucid) + + continuation.write(Bytes[0x1a]) + continuation.write(write_var_int(meta.size)) + continuation.print(meta) + + continuation.rewind + continuation = continuation.gets_to_end + + wrapper = IO::Memory.new + wrapper.write(Bytes[0xe2, 0xa9, 0x85, 0xb2, 0x02]) + wrapper.write(write_var_int(continuation.size)) + wrapper.print(continuation) + wrapper.rewind + + wrapper = Base64.urlsafe_encode(wrapper.to_slice) + wrapper = URI.escape(wrapper) + + url = "/browse_ajax?continuation=#{wrapper}&gl=US&hl=en" + + return url +end + +def extract_channel_playlists_cursor(url) + wrapper = HTTP::Params.parse(URI.parse(url).query.not_nil!)["continuation"] + + wrapper = URI.unescape(wrapper) + wrapper = Base64.decode(wrapper) + + # 0xe2 0xa9 0x85 0xb2 0x02 + wrapper += 5 + + continuation_size = read_var_int(wrapper[0, 4]) + wrapper += write_var_int(continuation_size).size + continuation = wrapper[0, continuation_size] + + # 0x12 + continuation += 1 + ucid_size = continuation[0] + continuation += 1 + ucid = continuation[0, ucid_size] + continuation += ucid_size + + # 0x1a + continuation += 1 + meta_size = read_var_int(continuation[0, 4]) + continuation += write_var_int(meta_size).size + meta = continuation[0, meta_size] + continuation += meta_size + + meta = String.new(meta) + meta = URI.unescape(meta) + meta = Base64.decode(meta) + + # 0x12 0x09 playlists + meta += 11 + + until meta[0] == 0x7a + tag = read_var_int(meta[0, 4]) + meta += write_var_int(tag).size + value = meta[0] + meta += 1 + end + + # 0x7a + meta += 1 + cursor_size = meta[0] + meta += 1 + cursor = meta[0, cursor_size] + + cursor = String.new(cursor) + cursor = URI.unescape(cursor) + cursor = Base64.decode_string(cursor) + + return cursor +end + def fetch_playlist(plid, locale) client = make_client(YT_URL) From 30e6d291066f489a27b558f536a8ee4f83d79f73 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 9 Feb 2019 10:18:24 -0600 Subject: [PATCH 107/108] Add 'deleted' to channel info --- config/migrate-scripts/migrate-db-e1aa1ce.sh | 4 ++++ config/sql/channels.sql | 1 + src/invidious/channels.cr | 3 ++- src/invidious/jobs.cr | 5 ++++- 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 config/migrate-scripts/migrate-db-e1aa1ce.sh diff --git a/config/migrate-scripts/migrate-db-e1aa1ce.sh b/config/migrate-scripts/migrate-db-e1aa1ce.sh new file mode 100644 index 00000000..259862df --- /dev/null +++ b/config/migrate-scripts/migrate-db-e1aa1ce.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +psql invidious -c "ALTER TABLE channels ADD COLUMN deleted bool;" +psql invidious -c "UPDATE channels SET deleted = false;" diff --git a/config/sql/channels.sql b/config/sql/channels.sql index c4259c12..cecd04ed 100644 --- a/config/sql/channels.sql +++ b/config/sql/channels.sql @@ -7,6 +7,7 @@ CREATE TABLE public.channels id text NOT NULL, author text, updated timestamp with time zone, + deleted boolean, CONSTRAINT channels_id_key UNIQUE (id) ); diff --git a/src/invidious/channels.cr b/src/invidious/channels.cr index 956450d5..ccaf2487 100644 --- a/src/invidious/channels.cr +++ b/src/invidious/channels.cr @@ -3,6 +3,7 @@ class InvidiousChannel id: String, author: String, updated: Time, + deleted: Bool, }) end @@ -187,7 +188,7 @@ def fetch_channel(ucid, client, db, pull_all_videos = true, locale = nil) db.exec("DELETE FROM channel_videos * WHERE NOT id = ANY ('{#{ids.map { |id| %("#{id}") }.join(",")}}') AND ucid = $1", ucid) end - channel = InvidiousChannel.new(ucid, author, Time.now) + channel = InvidiousChannel.new(ucid, author, Time.now, false) return channel end diff --git a/src/invidious/jobs.cr b/src/invidious/jobs.cr index f6e2d8fe..04816efd 100644 --- a/src/invidious/jobs.cr +++ b/src/invidious/jobs.cr @@ -55,7 +55,7 @@ def refresh_channels(db, logger, max_threads = 1, full_refresh = false) active_channel = Channel(Bool).new loop do - db.query("SELECT id FROM channels ORDER BY updated") do |rs| + db.query("SELECT id FROM channels WHERE deleted = false ORDER BY updated") do |rs| rs.each do id = rs.read(String) @@ -73,6 +73,9 @@ def refresh_channels(db, logger, max_threads = 1, full_refresh = false) db.exec("UPDATE channels SET updated = $1, author = $2 WHERE id = $3", Time.now, channel.author, id) rescue ex + if ex.message == "Deleted or invalid channel" + db.exec("UPDATE channels SET deleted = true WHERE id = $1", id) + end logger.write("#{id} : #{ex.message}\n") end From 0d509c82ee2d3bba669d1a6c2625b04358cc9d74 Mon Sep 17 00:00:00 2001 From: Omar Roth Date: Sat, 9 Feb 2019 12:09:15 -0600 Subject: [PATCH 108/108] Rename migrate-db-e1aa1ce.sh to migrate-db-30e6d29.sh --- .../{migrate-db-e1aa1ce.sh => migrate-db-30e6d29.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename config/migrate-scripts/{migrate-db-e1aa1ce.sh => migrate-db-30e6d29.sh} (100%) mode change 100644 => 100755 diff --git a/config/migrate-scripts/migrate-db-e1aa1ce.sh b/config/migrate-scripts/migrate-db-30e6d29.sh old mode 100644 new mode 100755 similarity index 100% rename from config/migrate-scripts/migrate-db-e1aa1ce.sh rename to config/migrate-scripts/migrate-db-30e6d29.sh