forked from midou/invidious
Update to Crystal 0.31.0, resolve compiler deprecation warnings, update dependencies (#764)
* shard: update to crystal 0.31.0 Additionally, no longer use the Crystal "markdown" library which has been removed from the Crystal stdlib in version 0.31.0. See https://github.com/crystal-lang/crystal/pull/8115. Also fix some deprecation warnings using the following commands: find . \( -type d -name .git -prune \) -o -type f -exec sed -i 's/URI\.escape/URI\.encode_www_form/g' "{}" \; find . \( -type d -name .git -prune \) -o -type f -exec sed -i 's/URI\.unescape/URI\.decode_www_form/g' "{}" \; sed -i 's/while \%pull\.kind \!\= \:end_object/until \%pull\.kind\.end_object\?/g' src/invidious/helpers/patch_mapping.cr
This commit is contained in:
parent
1085ca4a2d
commit
1aefc5b540
@ -11,14 +11,14 @@ targets:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pg:
|
pg:
|
||||||
github: will/crystal-pg
|
github: will/crystal-pg
|
||||||
version: ~> 0.18.1
|
version: ~> 0.19.0
|
||||||
sqlite3:
|
sqlite3:
|
||||||
github: crystal-lang/crystal-sqlite3
|
github: crystal-lang/crystal-sqlite3
|
||||||
version: ~> 0.13.0
|
version: ~> 0.14.0
|
||||||
kemal:
|
kemal:
|
||||||
github: kemalcr/kemal
|
github: kemalcr/kemal
|
||||||
version: ~> 0.26.0
|
version: ~> 0.26.0
|
||||||
|
|
||||||
crystal: 0.30.1
|
crystal: 0.31.0
|
||||||
|
|
||||||
license: AGPLv3
|
license: AGPLv3
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
require "digest/md5"
|
require "digest/md5"
|
||||||
require "file_utils"
|
require "file_utils"
|
||||||
require "kemal"
|
require "kemal"
|
||||||
require "markdown"
|
|
||||||
require "openssl/hmac"
|
require "openssl/hmac"
|
||||||
require "option_parser"
|
require "option_parser"
|
||||||
require "pg"
|
require "pg"
|
||||||
@ -296,7 +295,7 @@ before_all do |env|
|
|||||||
current_page += "?#{query}"
|
current_page += "?#{query}"
|
||||||
end
|
end
|
||||||
|
|
||||||
env.set "current_page", URI.escape(current_page)
|
env.set "current_page", URI.encode_www_form(current_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/" do |env|
|
get "/" do |env|
|
||||||
@ -841,7 +840,7 @@ get "/results" do |env|
|
|||||||
page ||= 1
|
page ||= 1
|
||||||
|
|
||||||
if query
|
if query
|
||||||
env.redirect "/search?q=#{URI.escape(query)}&page=#{page}"
|
env.redirect "/search?q=#{URI.encode_www_form(query)}&page=#{page}"
|
||||||
else
|
else
|
||||||
env.redirect "/"
|
env.redirect "/"
|
||||||
end
|
end
|
||||||
@ -1050,7 +1049,7 @@ post "/login" do |env|
|
|||||||
|
|
||||||
traceback << "done, returned #{response.status_code}.<br/>"
|
traceback << "done, returned #{response.status_code}.<br/>"
|
||||||
|
|
||||||
headers["Cookie"] = URI.unescape(headers["Cookie"])
|
headers["Cookie"] = URI.decode_www_form(headers["Cookie"])
|
||||||
|
|
||||||
if challenge_results[0][3]?.try &.== 7
|
if challenge_results[0][3]?.try &.== 7
|
||||||
error_message = translate(locale, "Account has temporarily been disabled")
|
error_message = translate(locale, "Account has temporarily been disabled")
|
||||||
@ -2423,7 +2422,7 @@ post "/authorize_token" do |env|
|
|||||||
access_token = generate_token(user.email, scopes, expire, HMAC_KEY, PG_DB)
|
access_token = generate_token(user.email, scopes, expire, HMAC_KEY, PG_DB)
|
||||||
|
|
||||||
if callback_url
|
if callback_url
|
||||||
access_token = URI.escape(access_token)
|
access_token = URI.encode_www_form(access_token)
|
||||||
url = URI.parse(callback_url)
|
url = URI.parse(callback_url)
|
||||||
|
|
||||||
if url.query
|
if url.query
|
||||||
@ -3327,7 +3326,7 @@ get "/api/v1/captions/:id" do |env|
|
|||||||
json.object do
|
json.object do
|
||||||
json.field "label", caption.name.simpleText
|
json.field "label", caption.name.simpleText
|
||||||
json.field "languageCode", caption.languageCode
|
json.field "languageCode", caption.languageCode
|
||||||
json.field "url", "/api/v1/captions/#{id}?label=#{URI.escape(caption.name.simpleText)}"
|
json.field "url", "/api/v1/captions/#{id}?label=#{URI.encode_www_form(caption.name.simpleText)}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3406,7 +3405,7 @@ get "/api/v1/captions/:id" do |env|
|
|||||||
|
|
||||||
if title = env.params.query["title"]?
|
if title = env.params.query["title"]?
|
||||||
# https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
|
# https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
|
||||||
env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
|
env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.encode_www_form(title)}\"; filename*=UTF-8''#{URI.encode_www_form(title)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
webvtt
|
webvtt
|
||||||
@ -3594,7 +3593,7 @@ get "/api/v1/annotations/:id" do |env|
|
|||||||
id = id.sub(/^-/, 'A')
|
id = id.sub(/^-/, 'A')
|
||||||
end
|
end
|
||||||
|
|
||||||
file = URI.escape("#{id[0, 3]}/#{id}.xml")
|
file = URI.encode_www_form("#{id[0, 3]}/#{id}.xml")
|
||||||
|
|
||||||
client = make_client(ARCHIVE_URL)
|
client = make_client(ARCHIVE_URL)
|
||||||
location = client.get("/download/youtubeannotations_#{index}/#{id[0, 2]}.tar/#{file}")
|
location = client.get("/download/youtubeannotations_#{index}/#{id[0, 2]}.tar/#{file}")
|
||||||
@ -4093,7 +4092,7 @@ get "/api/v1/search/suggestions" do |env|
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
client = make_client(URI.parse("https://suggestqueries.google.com"))
|
client = make_client(URI.parse("https://suggestqueries.google.com"))
|
||||||
response = client.get("/complete/search?hl=en&gl=#{region}&client=youtube&ds=yt&q=#{URI.escape(query)}&callback=suggestCallback").body
|
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 = response[35..-2]
|
||||||
body = JSON.parse(body).as_a
|
body = JSON.parse(body).as_a
|
||||||
@ -4477,7 +4476,7 @@ post "/api/v1/auth/tokens/register" do |env|
|
|||||||
access_token = generate_token(user.email, authorized_scopes, expire, HMAC_KEY, PG_DB)
|
access_token = generate_token(user.email, authorized_scopes, expire, HMAC_KEY, PG_DB)
|
||||||
|
|
||||||
if callback_url
|
if callback_url
|
||||||
access_token = URI.escape(access_token)
|
access_token = URI.encode_www_form(access_token)
|
||||||
|
|
||||||
if query = callback_url.query
|
if query = callback_url.query
|
||||||
query = HTTP::Params.parse(query.not_nil!)
|
query = HTTP::Params.parse(query.not_nil!)
|
||||||
@ -4712,7 +4711,7 @@ get "/api/manifest/hls_playlist/*" do |env|
|
|||||||
raw_params = {} of String => Array(String)
|
raw_params = {} of String => Array(String)
|
||||||
path.each_slice(2) do |pair|
|
path.each_slice(2) do |pair|
|
||||||
key, value = pair
|
key, value = pair
|
||||||
value = URI.unescape(value)
|
value = URI.decode_www_form(value)
|
||||||
|
|
||||||
if raw_params[key]?
|
if raw_params[key]?
|
||||||
raw_params[key] << value
|
raw_params[key] << value
|
||||||
@ -4837,7 +4836,7 @@ get "/videoplayback/*" do |env|
|
|||||||
raw_params = {} of String => Array(String)
|
raw_params = {} of String => Array(String)
|
||||||
path.each_slice(2) do |pair|
|
path.each_slice(2) do |pair|
|
||||||
key, value = pair
|
key, value = pair
|
||||||
value = URI.unescape(value)
|
value = URI.decode_www_form(value)
|
||||||
|
|
||||||
if raw_params[key]?
|
if raw_params[key]?
|
||||||
raw_params[key] << value
|
raw_params[key] << value
|
||||||
@ -5011,7 +5010,7 @@ get "/videoplayback" do |env|
|
|||||||
|
|
||||||
if title = query_params["title"]?
|
if title = query_params["title"]?
|
||||||
# https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
|
# https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
|
||||||
env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
|
env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.encode_www_form(title)}\"; filename*=UTF-8''#{URI.encode_www_form(title)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if !response.headers.includes_word?("Transfer-Encoding", "chunked")
|
if !response.headers.includes_word?("Transfer-Encoding", "chunked")
|
||||||
|
@ -476,7 +476,7 @@ def produce_channel_videos_url(ucid, page = 1, auto_generated = nil, sort_by = "
|
|||||||
end
|
end
|
||||||
|
|
||||||
data = Base64.urlsafe_encode(data)
|
data = Base64.urlsafe_encode(data)
|
||||||
cursor = URI.escape(data)
|
cursor = URI.encode_www_form(data)
|
||||||
|
|
||||||
data = IO::Memory.new
|
data = IO::Memory.new
|
||||||
|
|
||||||
@ -497,7 +497,7 @@ def produce_channel_videos_url(ucid, page = 1, auto_generated = nil, sort_by = "
|
|||||||
IO.copy data, buffer
|
IO.copy data, buffer
|
||||||
|
|
||||||
continuation = Base64.urlsafe_encode(buffer)
|
continuation = Base64.urlsafe_encode(buffer)
|
||||||
continuation = URI.escape(continuation)
|
continuation = URI.encode_www_form(continuation)
|
||||||
|
|
||||||
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
||||||
|
|
||||||
@ -547,7 +547,7 @@ def produce_channel_playlists_url(ucid, cursor, sort = "newest", auto_generated
|
|||||||
|
|
||||||
data.rewind
|
data.rewind
|
||||||
data = Base64.urlsafe_encode(data)
|
data = Base64.urlsafe_encode(data)
|
||||||
continuation = URI.escape(data)
|
continuation = URI.encode_www_form(data)
|
||||||
|
|
||||||
data = IO::Memory.new
|
data = IO::Memory.new
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ def produce_channel_playlists_url(ucid, cursor, sort = "newest", auto_generated
|
|||||||
IO.copy data, buffer
|
IO.copy data, buffer
|
||||||
|
|
||||||
continuation = Base64.urlsafe_encode(buffer)
|
continuation = Base64.urlsafe_encode(buffer)
|
||||||
continuation = URI.escape(continuation)
|
continuation = URI.encode_www_form(continuation)
|
||||||
|
|
||||||
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
||||||
|
|
||||||
@ -578,7 +578,7 @@ end
|
|||||||
def extract_channel_playlists_cursor(url, auto_generated)
|
def extract_channel_playlists_cursor(url, auto_generated)
|
||||||
continuation = HTTP::Params.parse(URI.parse(url).query.not_nil!)["continuation"]
|
continuation = HTTP::Params.parse(URI.parse(url).query.not_nil!)["continuation"]
|
||||||
|
|
||||||
continuation = URI.unescape(continuation)
|
continuation = URI.decode_www_form(continuation)
|
||||||
data = IO::Memory.new(Base64.decode(continuation))
|
data = IO::Memory.new(Base64.decode(continuation))
|
||||||
|
|
||||||
# 0xe2 0xa9 0x85 0xb2 0x02
|
# 0xe2 0xa9 0x85 0xb2 0x02
|
||||||
@ -597,7 +597,7 @@ def extract_channel_playlists_cursor(url, auto_generated)
|
|||||||
data.read inner_continuation
|
data.read inner_continuation
|
||||||
|
|
||||||
continuation = String.new(inner_continuation)
|
continuation = String.new(inner_continuation)
|
||||||
continuation = URI.unescape(continuation)
|
continuation = URI.decode_www_form(continuation)
|
||||||
data = IO::Memory.new(Base64.decode(continuation))
|
data = IO::Memory.new(Base64.decode(continuation))
|
||||||
|
|
||||||
# 0x12 0x09 playlists
|
# 0x12 0x09 playlists
|
||||||
@ -614,7 +614,7 @@ def extract_channel_playlists_cursor(url, auto_generated)
|
|||||||
cursor = String.new(cursor)
|
cursor = String.new(cursor)
|
||||||
|
|
||||||
if !auto_generated
|
if !auto_generated
|
||||||
cursor = URI.unescape(cursor)
|
cursor = URI.decode_www_form(cursor)
|
||||||
cursor = Base64.decode_string(cursor)
|
cursor = Base64.decode_string(cursor)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -877,7 +877,7 @@ def fetch_channel_community(ucid, continuation, locale, config, kemal_config, fo
|
|||||||
end
|
end
|
||||||
|
|
||||||
def produce_channel_community_continuation(ucid, cursor)
|
def produce_channel_community_continuation(ucid, cursor)
|
||||||
cursor = URI.escape(cursor)
|
cursor = URI.encode_www_form(cursor)
|
||||||
|
|
||||||
data = IO::Memory.new
|
data = IO::Memory.new
|
||||||
|
|
||||||
@ -898,13 +898,13 @@ def produce_channel_community_continuation(ucid, cursor)
|
|||||||
IO.copy data, buffer
|
IO.copy data, buffer
|
||||||
|
|
||||||
continuation = Base64.urlsafe_encode(buffer)
|
continuation = Base64.urlsafe_encode(buffer)
|
||||||
continuation = URI.escape(continuation)
|
continuation = URI.encode_www_form(continuation)
|
||||||
|
|
||||||
return continuation
|
return continuation
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_channel_community_cursor(continuation)
|
def extract_channel_community_cursor(continuation)
|
||||||
continuation = URI.unescape(continuation)
|
continuation = URI.decode_www_form(continuation)
|
||||||
data = IO::Memory.new(Base64.decode(continuation))
|
data = IO::Memory.new(Base64.decode(continuation))
|
||||||
|
|
||||||
# 0xe2 0xa9 0x85 0xb2 0x02
|
# 0xe2 0xa9 0x85 0xb2 0x02
|
||||||
@ -923,7 +923,7 @@ def extract_channel_community_cursor(continuation)
|
|||||||
data.read_byte
|
data.read_byte
|
||||||
end
|
end
|
||||||
|
|
||||||
return URI.unescape(data.gets_to_end)
|
return URI.decode_www_form(data.gets_to_end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_about_info(ucid, locale)
|
def get_about_info(ucid, locale)
|
||||||
|
@ -573,7 +573,7 @@ def content_to_comment_html(content)
|
|||||||
end
|
end
|
||||||
|
|
||||||
def extract_comment_cursor(continuation)
|
def extract_comment_cursor(continuation)
|
||||||
continuation = URI.unescape(continuation)
|
continuation = URI.decode_www_form(continuation)
|
||||||
data = IO::Memory.new(Base64.decode(continuation))
|
data = IO::Memory.new(Base64.decode(continuation))
|
||||||
|
|
||||||
# 0x12 0x26
|
# 0x12 0x26
|
||||||
@ -653,7 +653,7 @@ def produce_comment_continuation(video_id, cursor = "", sort_by = "top")
|
|||||||
end
|
end
|
||||||
|
|
||||||
continuation = Base64.urlsafe_encode(data)
|
continuation = Base64.urlsafe_encode(data)
|
||||||
continuation = URI.escape(continuation)
|
continuation = URI.encode_www_form(continuation)
|
||||||
|
|
||||||
return continuation
|
return continuation
|
||||||
end
|
end
|
||||||
@ -695,7 +695,7 @@ def produce_comment_reply_continuation(video_id, ucid, comment_id)
|
|||||||
data.write(Bytes[0x48, 0x0a])
|
data.write(Bytes[0x48, 0x0a])
|
||||||
|
|
||||||
continuation = Base64.urlsafe_encode(data.to_slice)
|
continuation = Base64.urlsafe_encode(data.to_slice)
|
||||||
continuation = URI.escape(continuation)
|
continuation = URI.encode_www_form(continuation)
|
||||||
|
|
||||||
return continuation
|
return continuation
|
||||||
end
|
end
|
||||||
|
@ -95,8 +95,8 @@ class AuthHandler < Kemal::Handler
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
if token = env.request.headers["Authorization"]?
|
if token = env.request.headers["Authorization"]?
|
||||||
token = JSON.parse(URI.unescape(token.lchop("Bearer ")))
|
token = JSON.parse(URI.decode_www_form(token.lchop("Bearer ")))
|
||||||
session = URI.unescape(token["session"].as_s)
|
session = URI.decode_www_form(token["session"].as_s)
|
||||||
scopes, expire, signature = validate_request(token, session, env.request, HMAC_KEY, PG_DB, nil)
|
scopes, expire, signature = validate_request(token, session, env.request, HMAC_KEY, PG_DB, nil)
|
||||||
|
|
||||||
if email = PG_DB.query_one?("SELECT email FROM session_ids WHERE id = $1", session, as: String)
|
if email = PG_DB.query_one?("SELECT email FROM session_ids WHERE id = $1", session, as: String)
|
||||||
|
@ -50,7 +50,7 @@ macro patched_json_mapping(_properties_, strict = false)
|
|||||||
rescue exc : ::JSON::ParseException
|
rescue exc : ::JSON::ParseException
|
||||||
raise ::JSON::MappingError.new(exc.message, self.class.to_s, nil, *%location, exc)
|
raise ::JSON::MappingError.new(exc.message, self.class.to_s, nil, *%location, exc)
|
||||||
end
|
end
|
||||||
while %pull.kind != :end_object
|
until %pull.kind.end_object?
|
||||||
%key_location = %pull.location
|
%key_location = %pull.location
|
||||||
key = %pull.read_object_key
|
key = %pull.read_object_key
|
||||||
case key
|
case key
|
||||||
|
@ -119,7 +119,7 @@ module Kemal
|
|||||||
|
|
||||||
config = Kemal.config.serve_static
|
config = Kemal.config.serve_static
|
||||||
original_path = context.request.path.not_nil!
|
original_path = context.request.path.not_nil!
|
||||||
request_path = URI.unescape(original_path)
|
request_path = URI.decode_www_form(original_path)
|
||||||
|
|
||||||
# File path cannot contains '\0' (NUL) because all filesystem I know
|
# File path cannot contains '\0' (NUL) because all filesystem I know
|
||||||
# don't accept '\0' character as file name.
|
# don't accept '\0' character as file name.
|
||||||
|
@ -69,7 +69,7 @@ end
|
|||||||
def validate_request(token, session, request, key, db, locale = nil)
|
def validate_request(token, session, request, key, db, locale = nil)
|
||||||
case token
|
case token
|
||||||
when String
|
when String
|
||||||
token = JSON.parse(URI.unescape(token)).as_h
|
token = JSON.parse(URI.decode_www_form(token)).as_h
|
||||||
when JSON::Any
|
when JSON::Any
|
||||||
token = token.as_h
|
token = token.as_h
|
||||||
when Nil
|
when Nil
|
||||||
|
@ -246,7 +246,7 @@ def get_referer(env, fallback = "/", unroll = true)
|
|||||||
if referer.query
|
if referer.query
|
||||||
params = HTTP::Params.parse(referer.query.not_nil!)
|
params = HTTP::Params.parse(referer.query.not_nil!)
|
||||||
if params["referer"]?
|
if params["referer"]?
|
||||||
referer = URI.parse(URI.unescape(params["referer"]))
|
referer = URI.parse(URI.decode_www_form(params["referer"]))
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
@ -172,7 +172,7 @@ def produce_playlist_url(id, index)
|
|||||||
continuation.print data
|
continuation.print data
|
||||||
|
|
||||||
data = Base64.urlsafe_encode(continuation)
|
data = Base64.urlsafe_encode(continuation)
|
||||||
cursor = URI.escape(data)
|
cursor = URI.encode_www_form(data)
|
||||||
|
|
||||||
data = IO::Memory.new
|
data = IO::Memory.new
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ def produce_playlist_url(id, index)
|
|||||||
IO.copy data, buffer
|
IO.copy data, buffer
|
||||||
|
|
||||||
continuation = Base64.urlsafe_encode(buffer)
|
continuation = Base64.urlsafe_encode(buffer)
|
||||||
continuation = URI.escape(continuation)
|
continuation = URI.encode_www_form(continuation)
|
||||||
|
|
||||||
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ def search(query, page = 1, search_params = produce_search_params(content_type:
|
|||||||
return {0, [] of SearchItem}
|
return {0, [] of SearchItem}
|
||||||
end
|
end
|
||||||
|
|
||||||
html = client.get("/results?q=#{URI.escape(query)}&page=#{page}&sp=#{search_params}&hl=en&disable_polymer=1").body
|
html = client.get("/results?q=#{URI.encode_www_form(query)}&page=#{page}&sp=#{search_params}&hl=en&disable_polymer=1").body
|
||||||
if html.empty?
|
if html.empty?
|
||||||
return {0, [] of SearchItem}
|
return {0, [] of SearchItem}
|
||||||
end
|
end
|
||||||
@ -371,7 +371,7 @@ def produce_search_params(sort : String = "relevance", date : String = "", conte
|
|||||||
end
|
end
|
||||||
|
|
||||||
token = Base64.urlsafe_encode(token.to_slice)
|
token = Base64.urlsafe_encode(token.to_slice)
|
||||||
token = URI.escape(token)
|
token = URI.encode_www_form(token)
|
||||||
|
|
||||||
return token
|
return token
|
||||||
end
|
end
|
||||||
@ -396,7 +396,7 @@ def produce_channel_search_url(ucid, query, page)
|
|||||||
|
|
||||||
data.rewind
|
data.rewind
|
||||||
data = Base64.urlsafe_encode(data)
|
data = Base64.urlsafe_encode(data)
|
||||||
continuation = URI.escape(data)
|
continuation = URI.encode_www_form(data)
|
||||||
|
|
||||||
data = IO::Memory.new
|
data = IO::Memory.new
|
||||||
|
|
||||||
@ -421,7 +421,7 @@ def produce_channel_search_url(ucid, query, page)
|
|||||||
IO.copy data, buffer
|
IO.copy data, buffer
|
||||||
|
|
||||||
continuation = Base64.urlsafe_encode(buffer)
|
continuation = Base64.urlsafe_encode(buffer)
|
||||||
continuation = URI.escape(continuation)
|
continuation = URI.encode_www_form(continuation)
|
||||||
|
|
||||||
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
url = "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ end
|
|||||||
def extract_plid(url)
|
def extract_plid(url)
|
||||||
wrapper = HTTP::Params.parse(URI.parse(url).query.not_nil!)["bp"]
|
wrapper = HTTP::Params.parse(URI.parse(url).query.not_nil!)["bp"]
|
||||||
|
|
||||||
wrapper = URI.unescape(wrapper)
|
wrapper = URI.decode_www_form(wrapper)
|
||||||
wrapper = Base64.decode(wrapper)
|
wrapper = Base64.decode(wrapper)
|
||||||
|
|
||||||
# 0xe2 0x02 0x2e
|
# 0xe2 0x02 0x2e
|
||||||
|
@ -408,7 +408,7 @@ struct Video
|
|||||||
json.object do
|
json.object do
|
||||||
json.field "label", caption.name.simpleText
|
json.field "label", caption.name.simpleText
|
||||||
json.field "languageCode", caption.languageCode
|
json.field "languageCode", caption.languageCode
|
||||||
json.field "url", "/api/v1/captions/#{id}?label=#{URI.escape(caption.name.simpleText)}"
|
json.field "url", "/api/v1/captions/#{id}?label=#{URI.encode_www_form(caption.name.simpleText)}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
<input type="hidden" name="expire" value="<%= expire %>">
|
<input type="hidden" name="expire" value="<%= expire %>">
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(csrf_token) %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(csrf_token) %>">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<div class="pure-u-1 pure-u-lg-1-5"></div>
|
<div class="pure-u-1 pure-u-lg-1-5"></div>
|
||||||
<div class="pure-u-1 pure-u-lg-3-5">
|
<div class="pure-u-1 pure-u-lg-3-5">
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<form class="pure-form pure-form-aligned" action="/change_password?referer=<%= URI.escape(referer) %>" method="post">
|
<form class="pure-form pure-form-aligned" action="/change_password?referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||||
<legend><%= translate(locale, "Change password") %></legend>
|
<legend><%= translate(locale, "Change password") %></legend>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@ -23,7 +23,7 @@
|
|||||||
<%= translate(locale, "Change password") %>
|
<%= translate(locale, "Change password") %>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(csrf_token) %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(csrf_token) %>">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<form class="pure-form pure-form-aligned" action="/clear_watch_history?referer=<%= URI.escape(referer) %>" method="post">
|
<form class="pure-form pure-form-aligned" action="/clear_watch_history?referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||||
<legend><%= translate(locale, "Clear watch history?") %></legend>
|
<legend><%= translate(locale, "Clear watch history?") %></legend>
|
||||||
|
|
||||||
<div class="pure-g">
|
<div class="pure-g">
|
||||||
@ -13,12 +13,12 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="pure-u-1-2">
|
<div class="pure-u-1-2">
|
||||||
<a class="pure-button" href="<%= URI.escape(referer) %>">
|
<a class="pure-button" href="<%= URI.encode_www_form(referer) %>">
|
||||||
<%= translate(locale, "No") %>
|
<%= translate(locale, "No") %>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(csrf_token) %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(csrf_token) %>">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
||||||
<% if env.get? "show_watched" %>
|
<% if env.get? "show_watched" %>
|
||||||
<form onsubmit="return false" action="/watch_ajax?action_mark_watched=1&id=<%= item.id %>&referer=<%= env.get("current_page") %>" method="post">
|
<form onsubmit="return false" action="/watch_ajax?action_mark_watched=1&id=<%= item.id %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<p class="watched">
|
<p class="watched">
|
||||||
<a onclick="mark_watched(this)" data-id="<%= item.id %>" href="javascript:void(0)">
|
<a onclick="mark_watched(this)" data-id="<%= item.id %>" href="javascript:void(0)">
|
||||||
<button type="submit" style="all:unset">
|
<button type="submit" style="all:unset">
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<% if subscriptions.includes? ucid %>
|
<% if subscriptions.includes? ucid %>
|
||||||
<p>
|
<p>
|
||||||
<form action="/subscription_ajax?action_remove_subscriptions=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>" method="post">
|
<form action="/subscription_ajax?action_remove_subscriptions=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<button data-type="unsubscribe" id="subscribe" class="pure-button pure-button-primary">
|
<button data-type="unsubscribe" id="subscribe" class="pure-button pure-button-primary">
|
||||||
<b><input style="all:unset" type="submit" value="<%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %>"></b>
|
<b><input style="all:unset" type="submit" value="<%= translate(locale, "Unsubscribe") %> | <%= sub_count_text %>"></b>
|
||||||
</button>
|
</button>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<% else %>
|
<% else %>
|
||||||
<p>
|
<p>
|
||||||
<form action="/subscription_ajax?action_create_subscription_to_channel=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>" method="post">
|
<form action="/subscription_ajax?action_create_subscription_to_channel=1&c=<%= ucid %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<button data-type="subscribe" id="subscribe" class="pure-button pure-button-primary">
|
<button data-type="subscribe" id="subscribe" class="pure-button pure-button-primary">
|
||||||
<b><input style="all:unset" type="submit" value="<%= translate(locale, "Subscribe") %> | <%= sub_count_text %>"></b>
|
<b><input style="all:unset" type="submit" value="<%= translate(locale, "Subscribe") %> | <%= sub_count_text %>"></b>
|
||||||
</button>
|
</button>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
ucid: '<%= ucid %>',
|
ucid: '<%= ucid %>',
|
||||||
author: '<%= HTML.escape(author) %>',
|
author: '<%= HTML.escape(author) %>',
|
||||||
sub_count_text: '<%= HTML.escape(sub_count_text) %>',
|
sub_count_text: '<%= HTML.escape(sub_count_text) %>',
|
||||||
csrf_token: '<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>',
|
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||||
subscribe_text: '<%= HTML.escape(translate(locale, "Subscribe")) %>',
|
subscribe_text: '<%= HTML.escape(translate(locale, "Subscribe")) %>',
|
||||||
unsubscribe_text: '<%= HTML.escape(translate(locale, "Unsubscribe")) %>'
|
unsubscribe_text: '<%= HTML.escape(translate(locale, "Unsubscribe")) %>'
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<form class="pure-form pure-form-aligned" enctype="multipart/form-data" action="/data_control?referer=<%= URI.escape(referer) %>" method="post">
|
<form class="pure-form pure-form-aligned" enctype="multipart/form-data" action="/data_control?referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend><%= translate(locale, "Import") %></legend>
|
<legend><%= translate(locale, "Import") %></legend>
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<form class="pure-form pure-form-aligned" action="/delete_account?referer=<%= URI.escape(referer) %>" method="post">
|
<form class="pure-form pure-form-aligned" action="/delete_account?referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||||
<legend><%= translate(locale, "Delete account?") %></legend>
|
<legend><%= translate(locale, "Delete account?") %></legend>
|
||||||
|
|
||||||
<div class="pure-g">
|
<div class="pure-g">
|
||||||
@ -13,12 +13,12 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="pure-u-1-2">
|
<div class="pure-u-1-2">
|
||||||
<a class="pure-button" href="<%= URI.escape(referer) %>">
|
<a class="pure-button" href="<%= URI.encode_www_form(referer) %>">
|
||||||
<%= translate(locale, "No") %>
|
<%= translate(locale, "No") %>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(csrf_token) %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(csrf_token) %>">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
var watched_data = {
|
var watched_data = {
|
||||||
csrf_token: '<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>',
|
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/watched_widget.js"></script>
|
<script src="/js/watched_widget.js"></script>
|
||||||
@ -35,7 +35,7 @@ var watched_data = {
|
|||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/>
|
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/>
|
||||||
<form onsubmit="return false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
|
<form onsubmit="return false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<p class="watched">
|
<p class="watched">
|
||||||
<a onclick="mark_unwatched(this)" data-id="<%= item %>" href="javascript:void(0)">
|
<a onclick="mark_unwatched(this)" data-id="<%= item %>" href="javascript:void(0)">
|
||||||
<button type="submit" style="all:unset">
|
<button type="submit" style="all:unset">
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<% if account_type == "invidious" %>
|
<% if account_type == "invidious" %>
|
||||||
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.escape(referer) %>&type=invidious" method="post">
|
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=invidious" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<% if email %>
|
<% if email %>
|
||||||
<input name="email" type="hidden" value="<%= email %>">
|
<input name="email" type="hidden" value="<%= email %>">
|
||||||
@ -44,7 +44,7 @@
|
|||||||
<% captcha = captcha.not_nil! %>
|
<% captcha = captcha.not_nil! %>
|
||||||
<img style="width:100%" src='<%= captcha[:question] %>'/>
|
<img style="width:100%" src='<%= captcha[:question] %>'/>
|
||||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.escape(token) %>">
|
<input type="hidden" name="token[<%= i %>]" value="<%= URI.encode_www_form(token) %>">
|
||||||
<% end %>
|
<% end %>
|
||||||
<input type="hidden" name="captcha_type" value="image">
|
<input type="hidden" name="captcha_type" value="image">
|
||||||
<label for="answer"><%= translate(locale, "Time (h:mm:ss):") %></label>
|
<label for="answer"><%= translate(locale, "Time (h:mm:ss):") %></label>
|
||||||
@ -52,7 +52,7 @@
|
|||||||
<% when "text" %>
|
<% when "text" %>
|
||||||
<% captcha = captcha.not_nil! %>
|
<% captcha = captcha.not_nil! %>
|
||||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.escape(token) %>">
|
<input type="hidden" name="token[<%= i %>]" value="<%= URI.encode_www_form(token) %>">
|
||||||
<% end %>
|
<% end %>
|
||||||
<input type="hidden" name="captcha_type" value="text">
|
<input type="hidden" name="captcha_type" value="text">
|
||||||
<label for="answer"><%= captcha[:question] %></label>
|
<label for="answer"><%= captcha[:question] %></label>
|
||||||
@ -85,7 +85,7 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
<% elsif account_type == "google" %>
|
<% elsif account_type == "google" %>
|
||||||
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.escape(referer) %>&type=google" method="post">
|
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=google" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<% if email %>
|
<% if email %>
|
||||||
<input name="email" type="hidden" value="<%= email %>">
|
<input name="email" type="hidden" value="<%= email %>">
|
||||||
|
@ -9,7 +9,7 @@ function update_value(element) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<form class="pure-form pure-form-aligned" action="/preferences?referer=<%= URI.escape(referer) %>" method="post">
|
<form class="pure-form pure-form-aligned" action="/preferences?referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend><%= translate(locale, "Player preferences") %></legend>
|
<legend><%= translate(locale, "Player preferences") %></legend>
|
||||||
|
|
||||||
@ -242,15 +242,15 @@ function update_value(element) {
|
|||||||
<legend><%= translate(locale, "Data preferences") %></legend>
|
<legend><%= translate(locale, "Data preferences") %></legend>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<a href="/clear_watch_history?referer=<%= URI.escape(referer) %>"><%= translate(locale, "Clear watch history") %></a>
|
<a href="/clear_watch_history?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Clear watch history") %></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<a href="/change_password?referer=<%= URI.escape(referer) %>"><%= translate(locale, "Change password") %></a>
|
<a href="/change_password?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Change password") %></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<a href="/data_control?referer=<%= URI.escape(referer) %>"><%= translate(locale, "Import/export data") %></a>
|
<a href="/data_control?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Import/export data") %></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
@ -266,7 +266,7 @@ function update_value(element) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<a href="/delete_account?referer=<%= URI.escape(referer) %>"><%= translate(locale, "Delete account") %></a>
|
<a href="/delete_account?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Delete account") %></a>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
@ -3,73 +3,53 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<%= Markdown.to_html(<<-END_PRIVACY_POLICY
|
<h2>Privacy</h2>
|
||||||
## Privacy
|
<p>This document concerns what data you provide to this website, the purpose of the data, how the data is stored, and how the data can be removed.</p>
|
||||||
|
|
||||||
This document concerns what data you provide to this website, the purpose of the data, how the data is stored, and how the data can be removed.
|
<h3>Data you directly provide</h3>
|
||||||
|
<p>Data that you provide to the website for the purpose of the site's operation (for example: an account name, account password, or channel subscription) will be stored in the website's database until the user decides to remove it. This data will not be intentionally shared with anyone or anything.</p>
|
||||||
|
<p>Information stored about a registered user is limited to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>a list of session tokens for remaining logged in across devices</li>
|
||||||
|
<li>the last time an account was updated (to provide accurate notifications)</li>
|
||||||
|
<li>a list of video IDs identifying notifications from a user's subscriptions</li>
|
||||||
|
<li>a list of channel UCIDs the user is subscribed to</li>
|
||||||
|
<li>a user ID (for persistent storage of subscriptions and preferences)</li>
|
||||||
|
<li>a json object containing user preferences</li>
|
||||||
|
<li>a hashed password if applicable (not present on google accounts)</li>
|
||||||
|
<li>a randomly generated token for providing an RSS feed of a user's subscriptions</li>
|
||||||
|
<li>a list of video IDs identifying watched videos</li>
|
||||||
|
</ul>
|
||||||
|
<p>The above list reflects <a href="https://github.com/omarroth/invidious/blob/master/src/invidious/users.cr#L14-L51">this code</a>.</p>
|
||||||
|
<p>Users can clear their watch history using the <a href="/clear_watch_history">clear watch history</a> page.</p>
|
||||||
|
<p>If a user is logged in with a Google account, no password will ever be stored. This website uses the session token provided by Google to identify a user, but does not store the information required to make requests on a user's behalf without their knowledge or consent.</p>
|
||||||
|
|
||||||
### Data you directly provide
|
<h3>Data you passively provide</h3>
|
||||||
|
<p>When you request any resource from this website (for example: a page, a font, an image, or an API endpoint) information about the request may be logged.</p>
|
||||||
|
<p>Information about a request is limited to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>the time the request was made</li>
|
||||||
|
<li>the status code of the response</li>
|
||||||
|
<li>the method of the request</li>
|
||||||
|
<li>the requested URL</li>
|
||||||
|
<li>how long it took to complete the request.</li>
|
||||||
|
</ul>
|
||||||
|
<p>No identifying information is logged, such as the visitor's cookie, user-agent, or IP address. Here are a couple lines to serve as an example:</p>
|
||||||
|
<pre><code>2019-01-19 16:37:47 +00:00 200 GET /api/v1/comments/xrlETJYzH-c?format=html&hl=en-US 1345.88ms
|
||||||
|
2019-01-19 16:37:53 +00:00 200 GET /vi/r5P-f5arPXE/maxres.jpg 1085.41ms
|
||||||
|
2019-01-19 16:37:54 +00:00 200 GET /watch 7.04ms</code></pre>
|
||||||
|
<p>This website does not store the visitor's user-agent or IP address and does not use fingerprinting, advertisements, or tracking of any form.</p>
|
||||||
|
<p>This website provides links to googlevideo.com to provide audio and video playback. googlevideo.com is owned by Google and is subject to their <a href="https://policies.google.com/privacy">privacy policy</a>.</p>
|
||||||
|
|
||||||
Data that you provide to the website for the purpose of the site's operation (for example: an account name, account password, or channel subscription) will be stored in the website's database until the user decides to remove it. This data will not be intentionally shared with anyone or anything.
|
<h3>Data stored in your browser</h3>
|
||||||
|
<p>This website uses browser cookies to authenticate registered users. This data consists of:</p>
|
||||||
|
<ul>
|
||||||
|
<li>An account token to keep you logged into the website between visits, which is sent when any page is loaded while you are logged in</li>
|
||||||
|
</ul>
|
||||||
|
<p>This website also provides an option to store site preferences, such as the theme or locale, without an account. Using this feature will store a cookie in the visitor's browser containing their preferences. This cookie is sent on every request and does not contain any identifying information.</p>
|
||||||
|
<p>You can remove this data from your browser by logging out of this website, or by using your browser's cookie-related controls to delete the data.</p>
|
||||||
|
|
||||||
Information stored about a registered user is limited to:
|
<h3>Removal of data</h3>
|
||||||
|
<p>To remove data stored in your browser, you can log out of the website, or you can use your browser's cookie-related controls to delete the data.</p>
|
||||||
- a list of session tokens for remaining logged in across devices
|
<p>To remove data that has been stored in the website's database, you can use the <a href="/delete_account">delete my account</a> page.</p>
|
||||||
- the last time an account was updated (to provide accurate notifications)
|
|
||||||
- a list of video IDs identifying notifications from a user's subscriptions
|
|
||||||
- a list of channel UCIDs the user is subscribed to
|
|
||||||
- a user ID (for persistent storage of subscriptions and preferences)
|
|
||||||
- a json object containing user preferences
|
|
||||||
- a hashed password if applicable (not present on google accounts)
|
|
||||||
- a randomly generated token for providing an RSS feed of a user's subscriptions
|
|
||||||
- a list of video IDs identifying watched videos
|
|
||||||
|
|
||||||
The above list reflects [this code](https://github.com/omarroth/invidious/blob/master/src/invidious/users.cr#L14-L51).
|
|
||||||
|
|
||||||
Users can clear their watch history using the [clear watch history](/clear_watch_history) page.
|
|
||||||
|
|
||||||
If a user is logged in with a Google account, no password will ever be stored. This website uses the session token provided by Google to identify a user, but does not store the information required to make requests on a user's behalf without their knowledge or consent.
|
|
||||||
|
|
||||||
### Data you passively provide
|
|
||||||
|
|
||||||
When you request any resource from this website (for example: a page, a font, an image, or an API endpoint) information about the request may be logged.
|
|
||||||
|
|
||||||
Information about a request is limited to:
|
|
||||||
|
|
||||||
- the time the request was made
|
|
||||||
- the status code of the response
|
|
||||||
- the method of the request
|
|
||||||
- the requested URL
|
|
||||||
- how long it took to complete the request.
|
|
||||||
|
|
||||||
No identifying information is logged, such as the visitor's cookie, user-agent, or IP address. Here are a couple lines to serve as an example:
|
|
||||||
|
|
||||||
```
|
|
||||||
2019-01-19 16:37:47 +00:00 200 GET /api/v1/comments/xrlETJYzH-c?format=html&hl=en-US 1345.88ms
|
|
||||||
2019-01-19 16:37:53 +00:00 200 GET /vi/r5P-f5arPXE/maxres.jpg 1085.41ms
|
|
||||||
2019-01-19 16:37:54 +00:00 200 GET /watch 7.04ms
|
|
||||||
```
|
|
||||||
|
|
||||||
This website does not store the visitor's user-agent or IP address and does not use fingerprinting, advertisements, or tracking of any form.
|
|
||||||
|
|
||||||
This website provides links to googlevideo.com to provide audio and video playback. googlevideo.com is owned by Google and is subject to their [privacy policy](https://policies.google.com/privacy).
|
|
||||||
|
|
||||||
### Data stored in your browser
|
|
||||||
|
|
||||||
This website uses browser cookies to authenticate registered users. This data consists of:
|
|
||||||
|
|
||||||
- An account token to keep you logged into the website between visits, which is sent when any page is loaded while you are logged in
|
|
||||||
|
|
||||||
This website also provides an option to store site preferences, such as the theme or locale, without an account. Using this feature will store a cookie in the visitor's browser containing their preferences. This cookie is sent on every request and does not contain any identifying information.
|
|
||||||
|
|
||||||
You can remove this data from your browser by logging out of this website, or by using your browser's cookie-related controls to delete the data.
|
|
||||||
|
|
||||||
### Removal of data
|
|
||||||
|
|
||||||
To remove data stored in your browser, you can log out of the website, or you can use your browser's cookie-related controls to delete the data.
|
|
||||||
|
|
||||||
To remove data that has been stored in the website's database, you can use the [delete my account](/delete_account) page.
|
|
||||||
END_PRIVACY_POLICY
|
|
||||||
)
|
|
||||||
%>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pure-u-1-3" style="text-align:right">
|
<div class="pure-u-1-3" style="text-align:right">
|
||||||
<h3>
|
<h3>
|
||||||
<a href="/data_control?referer=<%= URI.escape(referer) %>">
|
<a href="/data_control?referer=<%= URI.encode_www_form(referer) %>">
|
||||||
<%= translate(locale, "Import/export") %>
|
<%= translate(locale, "Import/export") %>
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
@ -38,7 +38,7 @@
|
|||||||
<div class="pure-u-1-5" style="text-align:right">
|
<div class="pure-u-1-5" style="text-align:right">
|
||||||
<h3 style="padding-right:0.5em">
|
<h3 style="padding-right:0.5em">
|
||||||
<form onsubmit="return false" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>&referer=<%= env.get("current_page") %>" method="post">
|
<form onsubmit="return false" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<a onclick="remove_subscription(this)" data-ucid="<%= channel.id %>" href="#">
|
<a onclick="remove_subscription(this)" data-ucid="<%= channel.id %>" href="#">
|
||||||
<input style="all:unset" type="submit" value="<%= translate(locale, "unsubscribe") %>">
|
<input style="all:unset" type="submit" value="<%= translate(locale, "unsubscribe") %>">
|
||||||
</a>
|
</a>
|
||||||
@ -78,6 +78,6 @@ function remove_subscription(target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xhr.send('csrf_token=<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>');
|
xhr.send('csrf_token=<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
var watched_data = {
|
var watched_data = {
|
||||||
csrf_token: '<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>',
|
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/watched_widget.js"></script>
|
<script src="/js/watched_widget.js"></script>
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pure-u-1-4">
|
<div class="pure-u-1-4">
|
||||||
<form action="/signout?referer=<%= env.get?("current_page") %>" method="post">
|
<form action="/signout?referer=<%= env.get?("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<a class="pure-menu-heading" href="#">
|
<a class="pure-menu-heading" href="#">
|
||||||
<input style="all:unset" type="submit" value="<%= translate(locale, "Log out") %>">
|
<input style="all:unset" type="submit" value="<%= translate(locale, "Log out") %>">
|
||||||
</a>
|
</a>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<div class="pure-u-1-3"></div>
|
<div class="pure-u-1-3"></div>
|
||||||
<div class="pure-u-1-3" style="text-align:right">
|
<div class="pure-u-1-3" style="text-align:right">
|
||||||
<h3>
|
<h3>
|
||||||
<a href="/preferences?referer=<%= URI.escape(referer) %>"><%= translate(locale, "Preferences") %></a>
|
<a href="/preferences?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Preferences") %></a>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<div class="pure-u-1-5" style="text-align:right">
|
<div class="pure-u-1-5" style="text-align:right">
|
||||||
<h3 style="padding-right:0.5em">
|
<h3 style="padding-right:0.5em">
|
||||||
<form onsubmit="return false" action="/token_ajax?action_revoke_token=1&session=<%= token[:session] %>&referer=<%= env.get("current_page") %>" method="post">
|
<form onsubmit="return false" action="/token_ajax?action_revoke_token=1&session=<%= token[:session] %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<a onclick="revoke_token(this)" data-session="<%= token[:session] %>" href="#">
|
<a onclick="revoke_token(this)" data-session="<%= token[:session] %>" href="#">
|
||||||
<input style="all:unset" type="submit" value="<%= translate(locale, "revoke") %>">
|
<input style="all:unset" type="submit" value="<%= translate(locale, "revoke") %>">
|
||||||
</a>
|
</a>
|
||||||
@ -70,6 +70,6 @@ function revoke_token(target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xhr.send('csrf_token=<%= URI.escape(env.get?("csrf_token").try &.as(String) || "") %>');
|
xhr.send('csrf_token=<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -106,22 +106,22 @@ var video_data = {
|
|||||||
<label for="download_widget"><%= translate(locale, "Download as: ") %></label>
|
<label for="download_widget"><%= translate(locale, "Download as: ") %></label>
|
||||||
<select style="width:100%" name="download_widget" id="download_widget">
|
<select style="width:100%" name="download_widget" id="download_widget">
|
||||||
<% fmt_stream.each do |option| %>
|
<% fmt_stream.each do |option| %>
|
||||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
||||||
<%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["type"].split(";")[0] %>
|
<%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["type"].split(";")[0] %>
|
||||||
</option>
|
</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% video_streams.each do |option| %>
|
<% video_streams.each do |option| %>
|
||||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
||||||
<%= option["quality_label"] %> - <%= option["type"].split(";")[0] %> @ <%= option["fps"] %>fps - video only
|
<%= option["quality_label"] %> - <%= option["type"].split(";")[0] %> @ <%= option["fps"] %>fps - video only
|
||||||
</option>
|
</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% audio_streams.each do |option| %>
|
<% audio_streams.each do |option| %>
|
||||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
||||||
<%= option["type"].split(";")[0] %> @ <%= option["bitrate"] %>k - audio only
|
<%= option["type"].split(";")[0] %> @ <%= option["bitrate"] %>k - audio only
|
||||||
</option>
|
</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% captions.each do |caption| %>
|
<% captions.each do |caption| %>
|
||||||
<option value='{"id":"<%= video.id %>","label":"<%= caption.name.simpleText %>","title":"<%= URI.escape(video.title) %>-<%= video.id %>.<%= caption.languageCode %>.vtt"}'>
|
<option value='{"id":"<%= video.id %>","label":"<%= caption.name.simpleText %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= caption.languageCode %>.vtt"}'>
|
||||||
<%= translate(locale, "Subtitles - `x` (.vtt)", caption.name.simpleText) %>
|
<%= translate(locale, "Subtitles - `x` (.vtt)", caption.name.simpleText) %>
|
||||||
</option>
|
</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
Loading…
Reference in New Issue
Block a user