diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/invidious.cr | 10 | ||||
| -rw-r--r-- | src/invidious/helpers/jobs.cr | 54 | ||||
| -rw-r--r-- | src/invidious/helpers/utils.cr | 12 |
3 files changed, 68 insertions, 8 deletions
diff --git a/src/invidious.cr b/src/invidious.cr index 147fe935..a4f20bc4 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -87,6 +87,7 @@ LOCALES = { "nb_NO" => load_locale("nb_NO"), "nl" => load_locale("nl"), "pl" => load_locale("pl"), + "ro" => load_locale("ro"), "ru" => load_locale("ru"), "tr" => load_locale("tr"), "uk" => load_locale("uk"), @@ -3852,7 +3853,7 @@ get "/api/v1/captions/:id" do |env| caption = caption[0] end - url = "#{caption.baseUrl}&tlang=#{tlang}" + url = URI.parse("#{caption.baseUrl}&tlang=#{tlang}").full_path # Auto-generated captions often have cues that aren't aligned properly with the video, # as well as some other markup that makes it cumbersome, so we try to fix that here @@ -4523,9 +4524,10 @@ get "/api/v1/search/suggestions" do |env| query ||= "" begin - response = QUIC::Client.get( - "https://suggestqueries.google.com/complete/search?hl=en&gl=#{region}&client=youtube&ds=yt&q=#{URI.encode_www_form(query)}&callback=suggestCallback" - ).body + client = QUIC::Client.new("suggestqueries.google.com") + client.family = CONFIG.force_resolve || Socket::Family::INET + client.family = Socket::Family::INET if client.family == Socket::Family::UNSPEC + response = client.get("/complete/search?hl=en&gl=#{region}&client=youtube&ds=yt&q=#{URI.encode_www_form(query)}&callback=suggestCallback").body body = response[35..-2] body = JSON.parse(body).as_a diff --git a/src/invidious/helpers/jobs.cr b/src/invidious/helpers/jobs.cr index 5838b5b3..f368d6df 100644 --- a/src/invidious/helpers/jobs.cr +++ b/src/invidious/helpers/jobs.cr @@ -290,6 +290,60 @@ def bypass_captcha(captcha_key, logger) response = YT_POOL.client &.post("/das_captcha", headers, form: inputs) yield response.cookies.select { |cookie| cookie.name != "PREF" } + elsif response.headers["Location"]?.try &.includes?("/sorry/index") + location = response.headers["Location"].try { |u| URI.parse(u) } + client = QUIC::Client.new(location.host.not_nil!) + response = client.get(location.full_path) + + html = XML.parse_html(response.body) + form = html.xpath_node(%(//form[@action="index"])).not_nil! + site_key = form.xpath_node(%(.//div[@class="g-recaptcha"])).try &.["data-sitekey"] + + inputs = {} of String => String + form.xpath_nodes(%(.//input[@name])).map do |node| + inputs[node["name"]] = node["value"] + end + + response = JSON.parse(HTTP::Client.post("https://api.anti-captcha.com/createTask", body: { + "clientKey" => CONFIG.captcha_key, + "task" => { + "type" => "NoCaptchaTaskProxyless", + "websiteURL" => location.to_s, + "websiteKey" => site_key, + }, + }.to_json).body) + + if response["error"]? + raise response["error"].as_s + end + + task_id = response["taskId"].as_i + + loop do + sleep 10.seconds + + response = JSON.parse(HTTP::Client.post("https://api.anti-captcha.com/getTaskResult", body: { + "clientKey" => CONFIG.captcha_key, + "taskId" => task_id, + }.to_json).body) + + if response["status"]?.try &.== "ready" + break + elsif response["errorId"]?.try &.as_i != 0 + raise response["errorDescription"].as_s + end + end + + inputs["g-recaptcha-response"] = response["solution"]["gRecaptchaResponse"].as_s + client.close + client = QUIC::Client.new("www.google.com") + response = client.post(location.full_path, form: inputs) + headers = HTTP::Headers{ + "Cookie" => URI.parse(response.headers["location"]).query_params["google_abuse"].split(";")[0], + } + cookies = HTTP::Cookies.from_headers(headers) + + yield cookies end rescue ex logger.puts("Exception: #{ex.message}") diff --git a/src/invidious/helpers/utils.cr b/src/invidious/helpers/utils.cr index 53c18dd5..6fcfa8d2 100644 --- a/src/invidious/helpers/utils.cr +++ b/src/invidious/helpers/utils.cr @@ -31,8 +31,10 @@ struct QUICPool begin response = yield conn rescue ex - conn.destroy_engine + conn.close conn = QUIC::Client.new(url) + conn.family = (url.host == "www.youtube.com") ? CONFIG.force_resolve : Socket::Family::INET + conn.family = Socket::Family::INET if conn.family == Socket::Family::UNSPEC conn.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com" response = yield conn ensure @@ -45,9 +47,11 @@ struct QUICPool private def build_pool ConnectionPool(QUIC::Client).new(capacity: capacity, timeout: timeout) do - client = QUIC::Client.new(url) - client.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com" - client + conn = QUIC::Client.new(url) + conn.family = (url.host == "www.youtube.com") ? CONFIG.force_resolve : Socket::Family::INET + conn.family = Socket::Family::INET if conn.family == Socket::Family::UNSPEC + conn.before_request { |r| add_yt_headers(r) } if url.host == "www.youtube.com" + conn end end end |
