mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-11-04 06:31:57 +00:00 
			
		
		
		
	Add login page
This commit is contained in:
		@@ -405,3 +405,21 @@ def fill_links(html, scheme, host)
 | 
			
		||||
 | 
			
		||||
  html = html.to_xml
 | 
			
		||||
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
 | 
			
		||||
YT_URL     = URI.parse("https://www.youtube.com")
 | 
			
		||||
REDDIT_URL = URI.parse("https://api.reddit.com")
 | 
			
		||||
LOGIN_URL  = URI.parse("https://accounts.google.com")
 | 
			
		||||
 | 
			
		||||
youtube_pool = Deque.new(pool_size) do
 | 
			
		||||
  make_client(YT_URL)
 | 
			
		||||
@@ -330,6 +331,87 @@ get "/search" do |env|
 | 
			
		||||
  templated "search"
 | 
			
		||||
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|
 | 
			
		||||
  if env.params.query["q"]?
 | 
			
		||||
    env.redirect env.params.query["q"]
 | 
			
		||||
 
 | 
			
		||||
@@ -19,11 +19,14 @@
 | 
			
		||||
        <div class="pure-u-1 pure-u-md-1-5">
 | 
			
		||||
          <a href="/" class="pure-menu-heading">Invidious</a>
 | 
			
		||||
        </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">
 | 
			
		||||
            <input type="search" style="width:100%;" name="q" placeholder="search" value="<%= env.params.query["q"]? %>">
 | 
			
		||||
          </form>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="pure-u-1 pure-u-md-1-5">
 | 
			
		||||
          <a href="/login" class="pure-menu-heading">Login</a>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <%= content %>
 | 
			
		||||
      <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>
 | 
			
		||||
		Reference in New Issue
	
	Block a user