Add login page
This commit is contained in:
parent
e8013c6d5c
commit
d8372aa83e
4 changed files with 129 additions and 1 deletions
|
@ -405,3 +405,21 @@ def fill_links(html, scheme, host)
|
||||||
|
|
||||||
html = html.to_xml
|
html = html.to_xml
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def login_req(login_form, f_req)
|
||||||
|
data = {
|
||||||
|
"pstMsg" => "1",
|
||||||
|
"checkConnection" => "youtube",
|
||||||
|
"checkedDomains" => "youtube",
|
||||||
|
"hl" => "en",
|
||||||
|
"deviceinfo" => %q([null,null,null,[],null,"US",null,null,[],"GlifWebSignIn",null,[null,null,[]]]),
|
||||||
|
"f.req" => f_req,
|
||||||
|
"flowName" => "GlifWebSignIn",
|
||||||
|
"flowEntry" => "ServiceLogin",
|
||||||
|
}
|
||||||
|
|
||||||
|
data = data.merge(login_form)
|
||||||
|
# pp data
|
||||||
|
|
||||||
|
return HTTP::Params.encode(data)
|
||||||
|
end
|
||||||
|
|
|
@ -71,6 +71,7 @@ PG_URL = URI.new(
|
||||||
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://api.reddit.com")
|
REDDIT_URL = URI.parse("https://api.reddit.com")
|
||||||
|
LOGIN_URL = URI.parse("https://accounts.google.com")
|
||||||
|
|
||||||
youtube_pool = Deque.new(pool_size) do
|
youtube_pool = Deque.new(pool_size) do
|
||||||
make_client(YT_URL)
|
make_client(YT_URL)
|
||||||
|
@ -330,6 +331,87 @@ get "/search" do |env|
|
||||||
templated "search"
|
templated "search"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get "/login" do |env|
|
||||||
|
templated "login"
|
||||||
|
end
|
||||||
|
|
||||||
|
# See https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/youtube.py#L79
|
||||||
|
post "/login" do |env|
|
||||||
|
email = env.params.body["email"]?
|
||||||
|
password = env.params.body["password"]?
|
||||||
|
remember = env.params.body["remember"]? || "false"
|
||||||
|
|
||||||
|
begin
|
||||||
|
client = make_client(LOGIN_URL)
|
||||||
|
headers = HTTP::Headers.new
|
||||||
|
login_page = client.get("/ServiceLogin")
|
||||||
|
headers = login_page.cookies.add_request_headers(headers)
|
||||||
|
|
||||||
|
login_page = XML.parse_html(login_page.body)
|
||||||
|
|
||||||
|
inputs = {} of String => String
|
||||||
|
login_page.xpath_nodes(%q(//input[@type="submit"])).each do |node|
|
||||||
|
name = node["id"]? || node["name"]?
|
||||||
|
name ||= ""
|
||||||
|
value = node["value"]?
|
||||||
|
value ||= ""
|
||||||
|
|
||||||
|
if name != "" && value != ""
|
||||||
|
inputs[name] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
login_page.xpath_nodes(%q(//input[@type="hidden"])).each do |node|
|
||||||
|
name = node["id"]? || node["name"]?
|
||||||
|
name ||= ""
|
||||||
|
value = node["value"]?
|
||||||
|
value ||= ""
|
||||||
|
|
||||||
|
if name != "" && value != ""
|
||||||
|
inputs[name] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
lookup_req = %(["#{email}","#{inputs["session-state"]}",[],null,"US",null,null,2,false,true,[null,null,[2,1,null,1,"https://accounts.google.com/ServiceLogin?passive=true&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Fnext%3D%252F%26action_handle_signin%3Dtrue%26hl%3Den%26app%3Ddesktop%26feature%3Dsign_in_button&hl=en&service=youtube&uilel=3&requestPath=%2FServiceLogin&Page=PasswordSeparationSignIn",null,[],4,[]],1,[null,null,[]],null,null,null,true],"#{email}"])
|
||||||
|
|
||||||
|
headers["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8"
|
||||||
|
headers["Google-Accounts-XSRF"] = "1"
|
||||||
|
|
||||||
|
lookup_results = client.post("/_/signin/sl/lookup", headers, login_req(inputs, lookup_req))
|
||||||
|
headers = lookup_results.cookies.add_request_headers(headers)
|
||||||
|
|
||||||
|
lookup_results = lookup_results.body
|
||||||
|
lookup_results = lookup_results[5..-1]
|
||||||
|
lookup_results = JSON.parse(lookup_results)
|
||||||
|
|
||||||
|
user_hash = lookup_results[0][2]
|
||||||
|
|
||||||
|
challenge_req = %([#{user_hash},null,1,null,[1,null,null,null,[#{password},null,true]],[null,null,[2,1,null,1,"https://accounts.google.com/ServiceLogin?passive=true&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Fnext%3D%252F%26action_handle_signin%3Dtrue%26hl%3Den%26app%3Ddesktop%26feature%3Dsign_in_button&hl=en&service=youtube&uilel=3&requestPath=%2FServiceLogin&Page=PasswordSeparationSignIn", null,[],4],1,[null,null,[]],null,null,null,true]])
|
||||||
|
|
||||||
|
challenge_results = client.post("/_/signin/sl/challenge", headers, login_req(inputs, challenge_req))
|
||||||
|
headers = challenge_results.cookies.add_request_headers(headers)
|
||||||
|
|
||||||
|
challenge_results = challenge_results.body
|
||||||
|
challenge_results = challenge_results[5..-1]
|
||||||
|
challenge_results = JSON.parse(challenge_results)
|
||||||
|
|
||||||
|
login_res = challenge_results[0][13][2].to_s
|
||||||
|
|
||||||
|
login = client.get(login_res, headers)
|
||||||
|
headers = login.cookies.add_request_headers(headers)
|
||||||
|
|
||||||
|
login = client.get(login.headers["Location"], headers)
|
||||||
|
headers = login.cookies.add_request_headers(headers)
|
||||||
|
|
||||||
|
# We are now logged in
|
||||||
|
|
||||||
|
env.redirect "/"
|
||||||
|
rescue ex
|
||||||
|
error_message = "Login failed"
|
||||||
|
next templated "error"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
get "/redirect" do |env|
|
get "/redirect" do |env|
|
||||||
if env.params.query["q"]?
|
if env.params.query["q"]?
|
||||||
env.redirect env.params.query["q"]
|
env.redirect env.params.query["q"]
|
||||||
|
|
|
@ -19,11 +19,14 @@
|
||||||
<div class="pure-u-1 pure-u-md-1-5">
|
<div class="pure-u-1 pure-u-md-1-5">
|
||||||
<a href="/" class="pure-menu-heading">Invidious</a>
|
<a href="/" class="pure-menu-heading">Invidious</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="pure-u-1 pure-u-md-4-5">
|
<div class="pure-u-1 pure-u-md-3-5">
|
||||||
<form class="pure-form" action="/search" method="get">
|
<form class="pure-form" action="/search" method="get">
|
||||||
<input type="search" style="width:100%;" name="q" placeholder="search" value="<%= env.params.query["q"]? %>">
|
<input type="search" style="width:100%;" name="q" placeholder="search" value="<%= env.params.query["q"]? %>">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pure-u-1 pure-u-md-1-5">
|
||||||
|
<a href="/login" class="pure-menu-heading">Login</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%= content %>
|
<%= content %>
|
||||||
<center class="h-box">
|
<center class="h-box">
|
||||||
|
|
25
src/views/login.ecr
Normal file
25
src/views/login.ecr
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<div class="pure-g">
|
||||||
|
<div class="pure-u-1 pure-u-md-1-5"></div>
|
||||||
|
<div class="pure-u-1 pure-u-md-3-5">
|
||||||
|
<div class="h-box">
|
||||||
|
<form class="pure-form pure-form-stacked" action="/login" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Login for Google</legend>
|
||||||
|
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input class="pure-input-1" name="email" type="email" placeholder="Email">
|
||||||
|
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input class="pure-input-1" name="password" type="password" placeholder="Password">
|
||||||
|
|
||||||
|
<label for="remember" class="pure-checkbox">
|
||||||
|
<input id="remember" name="remember" type="checkbox"> Remember me
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button type="submit" class="pure-button pure-button-primary">Sign in</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pure-u-1 pure-u-md-1-5"></div>
|
||||||
|
</div>
|
Loading…
Reference in a new issue