|
|
@ -16,6 +16,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
require "crypto/bcrypt/password"
|
|
|
|
require "crypto/bcrypt/password"
|
|
|
|
require "detect_language"
|
|
|
|
require "detect_language"
|
|
|
|
|
|
|
|
require "digest/md5"
|
|
|
|
require "kemal"
|
|
|
|
require "kemal"
|
|
|
|
require "openssl/hmac"
|
|
|
|
require "openssl/hmac"
|
|
|
|
require "option_parser"
|
|
|
|
require "option_parser"
|
|
|
@ -82,10 +83,11 @@ PG_URL = URI.new(
|
|
|
|
path: CONFIG.db[:dbname],
|
|
|
|
path: CONFIG.db[:dbname],
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
PG_DB = DB.open PG_URL
|
|
|
|
PG_DB = DB.open PG_URL
|
|
|
|
YT_URL = URI.parse("https://www.youtube.com")
|
|
|
|
YT_URL = URI.parse("https://www.youtube.com")
|
|
|
|
REDDIT_URL = URI.parse("https://www.reddit.com")
|
|
|
|
REDDIT_URL = URI.parse("https://www.reddit.com")
|
|
|
|
LOGIN_URL = URI.parse("https://accounts.google.com")
|
|
|
|
LOGIN_URL = URI.parse("https://accounts.google.com")
|
|
|
|
|
|
|
|
TEXTCAPTCHA_URL = URI.parse("http://textcaptcha.com/omarroth@hotmail.com.json")
|
|
|
|
|
|
|
|
|
|
|
|
crawl_threads.times do
|
|
|
|
crawl_threads.times do
|
|
|
|
spawn do
|
|
|
|
spawn do
|
|
|
@ -632,8 +634,25 @@ get "/login" do |env|
|
|
|
|
account_type = env.params.query["type"]?
|
|
|
|
account_type = env.params.query["type"]?
|
|
|
|
account_type ||= "invidious"
|
|
|
|
account_type ||= "invidious"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
captcha_type = env.params.query["captcha"]?
|
|
|
|
|
|
|
|
captcha_type ||= "image"
|
|
|
|
|
|
|
|
|
|
|
|
if account_type == "invidious"
|
|
|
|
if account_type == "invidious"
|
|
|
|
captcha = generate_captcha(HMAC_KEY, PG_DB)
|
|
|
|
if captcha_type == "image"
|
|
|
|
|
|
|
|
captcha = generate_captcha(HMAC_KEY, PG_DB)
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
response = HTTP::Client.get(TEXTCAPTCHA_URL).body
|
|
|
|
|
|
|
|
response = JSON.parse(response)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tokens = response["a"].as_a.map do |answer|
|
|
|
|
|
|
|
|
create_response(answer.as_s, "sign_in", HMAC_KEY, PG_DB)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
text_captcha = {
|
|
|
|
|
|
|
|
question: response["q"].as_s,
|
|
|
|
|
|
|
|
tokens: tokens,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
tfa = env.params.query["tfa"]?
|
|
|
|
tfa = env.params.query["tfa"]?
|
|
|
@ -827,27 +846,55 @@ post "/login" do |env|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elsif account_type == "invidious"
|
|
|
|
elsif account_type == "invidious"
|
|
|
|
answer = env.params.body["answer"]?
|
|
|
|
answer = env.params.body["answer"]?
|
|
|
|
|
|
|
|
text_answer = env.params.body["text_answer"]?
|
|
|
|
|
|
|
|
|
|
|
|
if !answer
|
|
|
|
if answer
|
|
|
|
error_message = "CAPTCHA is a required field"
|
|
|
|
answer = answer.lstrip('0')
|
|
|
|
next templated "error"
|
|
|
|
answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
answer = answer.lstrip('0')
|
|
|
|
challenge = env.params.body["challenge"]?
|
|
|
|
answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer)
|
|
|
|
token = env.params.body["token"]?
|
|
|
|
|
|
|
|
|
|
|
|
challenge = env.params.body["challenge"]?
|
|
|
|
begin
|
|
|
|
token = env.params.body["token"]?
|
|
|
|
validate_response(challenge, token, answer, "sign_in", HMAC_KEY, PG_DB)
|
|
|
|
|
|
|
|
rescue ex
|
|
|
|
|
|
|
|
if ex.message == "Invalid user"
|
|
|
|
|
|
|
|
error_message = "Invalid answer"
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
error_message = ex.message
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
next templated "error"
|
|
|
|
validate_response(challenge, token, answer, "sign_in", HMAC_KEY, PG_DB)
|
|
|
|
end
|
|
|
|
rescue ex
|
|
|
|
elsif text_answer
|
|
|
|
if ex.message && ex.message == "Invalid user"
|
|
|
|
text_answer = Digest::MD5.hexdigest(text_answer.downcase.strip)
|
|
|
|
error_message = "Invalid CAPTCHA response"
|
|
|
|
|
|
|
|
else
|
|
|
|
challenges = env.params.body.select { |k, v| k.match(/text_challenge\d+/) }
|
|
|
|
error_message = ex.message
|
|
|
|
tokens = env.params.body.select { |k, v| k.match(/text_token\d+/) }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
found_valid_captcha = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error_message = "Invalid CAPTCHA"
|
|
|
|
|
|
|
|
challenges.each_with_index do |challenge, i|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
|
|
|
challenge = challenge[1]
|
|
|
|
|
|
|
|
token = tokens[i][1]
|
|
|
|
|
|
|
|
validate_response(challenge, token, text_answer, "sign_in", HMAC_KEY, PG_DB)
|
|
|
|
|
|
|
|
found_valid_captcha = true
|
|
|
|
|
|
|
|
rescue ex
|
|
|
|
|
|
|
|
if ex.message == "Invalid user"
|
|
|
|
|
|
|
|
error_message = "Invalid answer"
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
error_message = ex.message
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !found_valid_captcha
|
|
|
|
|
|
|
|
next templated "error"
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
error_message = "CAPTCHA is a required field"
|
|
|
|
next templated "error"
|
|
|
|
next templated "error"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|