Remove user supplied po_token and visitor_data

This commit is contained in:
Fijxu 2024-11-16 12:00:01 -03:00
parent 9b9efc6841
commit 3615bbd893
No known key found for this signature in database
GPG Key ID: 32C1DDF333EDA6A4
8 changed files with 26 additions and 73 deletions

View File

@ -45,8 +45,6 @@ struct ConfigPreferences
property vr_mode : Bool = true property vr_mode : Bool = true
property show_nick : Bool = true property show_nick : Bool = true
property save_player_pos : Bool = false property save_player_pos : Bool = false
property po_token : String = ""
property visitor_data : String = ""
def to_tuple def to_tuple
{% begin %} {% begin %}

View File

@ -86,12 +86,6 @@ module Invidious::Routes::PreferencesRoute
show_nick ||= "off" show_nick ||= "off"
show_nick = show_nick == "on" show_nick = show_nick == "on"
po_token = env.params.body["po_token"]?.try &.as(String)
po_token ||= CONFIG.default_user_preferences.po_token
visitor_data = env.params.body["visitor_data"]?.try &.as(String)
visitor_data ||= CONFIG.default_user_preferences.visitor_data
comments = [] of String comments = [] of String
2.times do |i| 2.times do |i|
comments << (env.params.body["comments[#{i}]"]?.try &.as(String) || CONFIG.default_user_preferences.comments[i]) comments << (env.params.body["comments[#{i}]"]?.try &.as(String) || CONFIG.default_user_preferences.comments[i])
@ -186,8 +180,6 @@ module Invidious::Routes::PreferencesRoute
vr_mode: vr_mode, vr_mode: vr_mode,
show_nick: show_nick, show_nick: show_nick,
save_player_pos: save_player_pos, save_player_pos: save_player_pos,
po_token: po_token,
visitor_data: visitor_data,
}.to_json) }.to_json)
if user = env.get? "user" if user = env.get? "user"

View File

@ -3,14 +3,6 @@
module Invidious::Routes::Watch module Invidious::Routes::Watch
def self.handle(env) def self.handle(env)
locale = env.get("preferences").as(Preferences).locale locale = env.get("preferences").as(Preferences).locale
if !CONFIG.ignore_user_tokens
user_po_token = env.get("preferences").as(Preferences).po_token
user_visitor_data = env.get("preferences").as(Preferences).visitor_data
else
user_po_token = ""
user_visitor_data = ""
end
region = env.params.query["region"]? region = env.params.query["region"]?
if env.params.query.to_s.includes?("%20") || env.params.query.to_s.includes?("+") if env.params.query.to_s.includes?("%20") || env.params.query.to_s.includes?("+")
@ -60,7 +52,7 @@ module Invidious::Routes::Watch
env.params.query.delete_all("listen") env.params.query.delete_all("listen")
begin begin
video = get_video(id, region: params.region, po_token: user_po_token, visitor_data: user_visitor_data) video = get_video(id, region: params.region)
rescue ex : NotFoundException rescue ex : NotFoundException
LOGGER.error("get_video not found: #{id} : #{ex.message}") LOGGER.error("get_video not found: #{id} : #{ex.message}")
return error_template(404, ex) return error_template(404, ex)
@ -152,7 +144,7 @@ module Invidious::Routes::Watch
end end
end end
# Removes non default audio tracks # Removes non default audio tracks
audio_streams.reject! do |z| audio_streams.reject! do |z|
z if z.dig?("audioTrack", "audioIsDefault") == false z if z.dig?("audioTrack", "audioIsDefault") == false
end end
@ -219,11 +211,11 @@ module Invidious::Routes::Watch
captions: video.captions captions: video.captions
) )
begin begin
video_url = fmt_stream[0]["url"].to_s video_url = fmt_stream[0]["url"].to_s
rescue rescue
video_url = nil video_url = nil
end end
templated "watch" templated "watch"
end end

View File

@ -57,10 +57,6 @@ struct Preferences
property volume : Int32 = CONFIG.default_user_preferences.volume property volume : Int32 = CONFIG.default_user_preferences.volume
property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos
@[YAML::Field(converter: Preferences::ProcessString)]
property po_token : String = ""
property visitor_data : String = ""
module BoolToString module BoolToString
def self.to_json(value : String, json : JSON::Builder) def self.to_json(value : String, json : JSON::Builder)
json.string value json.string value

View File

@ -294,7 +294,7 @@ struct Video
predicate_bool upcoming, isUpcoming predicate_bool upcoming, isUpcoming
end end
def get_video(id, refresh = true, region = nil, force_refresh = false, po_token = "", visitor_data = "") def get_video(id, refresh = true, region = nil, force_refresh = false)
if (video = Invidious::Database::Videos.select(id)) && !region if (video = Invidious::Database::Videos.select(id)) && !region
# If record was last updated over 10 minutes ago, or video has since premiered, # If record was last updated over 10 minutes ago, or video has since premiered,
# refresh (expire param in response lasts for 6 hours) # refresh (expire param in response lasts for 6 hours)
@ -304,7 +304,7 @@ def get_video(id, refresh = true, region = nil, force_refresh = false, po_token
force_refresh || force_refresh ||
video.schema_version != Video::SCHEMA_VERSION # cache control video.schema_version != Video::SCHEMA_VERSION # cache control
begin begin
video = fetch_video(id, region, po_token, visitor_data) video = fetch_video(id, region)
Invidious::Database::Videos.insert(video) Invidious::Database::Videos.insert(video)
rescue ex rescue ex
Invidious::Database::Videos.delete(id) Invidious::Database::Videos.delete(id)
@ -312,7 +312,7 @@ def get_video(id, refresh = true, region = nil, force_refresh = false, po_token
end end
end end
else else
video = fetch_video(id, region, po_token, visitor_data) video = fetch_video(id, region)
Invidious::Database::Videos.insert(video) if !region Invidious::Database::Videos.insert(video) if !region
end end
@ -320,11 +320,11 @@ def get_video(id, refresh = true, region = nil, force_refresh = false, po_token
rescue DB::Error rescue DB::Error
# Avoid common `DB::PoolRetryAttemptsExceeded` error and friends # Avoid common `DB::PoolRetryAttemptsExceeded` error and friends
# Note: All DB errors inherit from `DB::Error` # Note: All DB errors inherit from `DB::Error`
return fetch_video(id, region, po_token, visitor_data) return fetch_video(id, region)
end end
def fetch_video(id, region, po_token, visitor_data) def fetch_video(id, region)
info = extract_video_info(video_id: id, user_po_token: po_token, user_visitor_data: visitor_data) info = extract_video_info(video_id: id)
if reason = info["reason"]? if reason = info["reason"]?
if reason == "Video unavailable" if reason == "Video unavailable"

View File

@ -50,17 +50,17 @@ def parse_related_video(related : JSON::Any) : Hash(String, JSON::Any)?
} }
end end
def extract_video_info(video_id : String, user_po_token, user_visitor_data) def extract_video_info(video_id : String)
# Init client config for the API # Init client config for the API
client_config = YoutubeAPI::ClientConfig.new client_config = YoutubeAPI::ClientConfig.new
redis_po_token, redis_visitor_data = Tokens.get_tokens redis_po_token, redis_visitor_data = Tokens.get_tokens
po_token = (user_po_token if !user_po_token.empty?) || redis_po_token || CONFIG.po_token po_token = redis_po_token || CONFIG.po_token
visitor_data = (user_visitor_data if !user_visitor_data.empty?) || redis_visitor_data || CONFIG.visitor_data visitor_data = redis_visitor_data || CONFIG.visitor_data
# Fetch data from the player endpoint # Fetch data from the player endpoint
player_response = YoutubeAPI.player(video_id: video_id, params: "2AMB", client_config: client_config, po_token: po_token, visitor_data: visitor_data) player_response = YoutubeAPI.player(video_id: video_id, params: "2AMB", client_config: client_config)
playability_status = player_response.dig?("playabilityStatus", "status").try &.as_s playability_status = player_response.dig?("playabilityStatus", "status").try &.as_s
@ -115,7 +115,7 @@ def extract_video_info(video_id : String, user_po_token, user_visitor_data)
# following issue for an explanation about decrypted URLs: # following issue for an explanation about decrypted URLs:
# https://github.com/TeamNewPipe/NewPipeExtractor/issues/562 # https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite client_config.client_type = YoutubeAPI::ClientType::AndroidTestSuite
new_player_response = try_fetch_streaming_data(video_id, client_config, po_token, visitor_data) new_player_response = try_fetch_streaming_data(video_id, client_config)
end end
# Replace player response and reset reason # Replace player response and reset reason
@ -136,7 +136,7 @@ def extract_video_info(video_id : String, user_po_token, user_visitor_data)
if streaming_data = player_response["streamingData"]? if streaming_data = player_response["streamingData"]?
%w[formats adaptiveFormats].each do |key| %w[formats adaptiveFormats].each do |key|
streaming_data.as_h[key]?.try &.as_a.each do |format| streaming_data.as_h[key]?.try &.as_a.each do |format|
format.as_h["url"] = JSON::Any.new(convert_url(format, po_token)) format.as_h["url"] = JSON::Any.new(convert_url(format))
end end
end end
@ -149,9 +149,9 @@ def extract_video_info(video_id : String, user_po_token, user_visitor_data)
return params return params
end end
def try_fetch_streaming_data(id : String, client_config : YoutubeAPI::ClientConfig, po_token, visitor_data) : Hash(String, JSON::Any)? def try_fetch_streaming_data(id : String, client_config : YoutubeAPI::ClientConfig) : Hash(String, JSON::Any)?
LOGGER.debug("try_fetch_streaming_data: [#{id}] Using #{client_config.client_type} client.") LOGGER.debug("try_fetch_streaming_data: [#{id}] Using #{client_config.client_type} client.")
response = YoutubeAPI.player(video_id: id, params: "2AMB", client_config: client_config, po_token: po_token, visitor_data: visitor_data) response = YoutubeAPI.player(video_id: id, params: "2AMB", client_config: client_config)
playability_status = response["playabilityStatus"]["status"] playability_status = response["playabilityStatus"]["status"]
LOGGER.debug("try_fetch_streaming_data: [#{id}] Got playabilityStatus == #{playability_status}.") LOGGER.debug("try_fetch_streaming_data: [#{id}] Got playabilityStatus == #{playability_status}.")
@ -460,7 +460,7 @@ def parse_video_info(video_id : String, player_response : Hash(String, JSON::Any
return params return params
end end
private def convert_url(fmt, po_token) private def convert_url(fmt)
if cfr = fmt["signatureCipher"]?.try { |json| HTTP::Params.parse(json.as_s) } if cfr = fmt["signatureCipher"]?.try { |json| HTTP::Params.parse(json.as_s) }
sp = cfr["sp"] sp = cfr["sp"]
url = URI.parse(cfr["url"]) url = URI.parse(cfr["url"])
@ -478,9 +478,7 @@ private def convert_url(fmt, po_token)
n = DECRYPT_FUNCTION.try &.decrypt_nsig(params["n"]) n = DECRYPT_FUNCTION.try &.decrypt_nsig(params["n"])
params["n"] = n if n params["n"] = n if n
if !po_token.nil? if token = CONFIG.po_token
params["pot"] = po_token
elsif token = CONFIG.po_token
params["pot"] = token params["pot"] = token
end end

View File

@ -126,22 +126,10 @@
<input name="save_player_pos" id="save_player_pos" type="checkbox" <% if preferences.save_player_pos %>checked<% end %>> <input name="save_player_pos" id="save_player_pos" type="checkbox" <% if preferences.save_player_pos %>checked<% end %>>
</div> </div>
<% if !CONFIG.ignore_user_tokens %>
<div class="pure-control-group">
<label for="po_token"><%= translate(locale, "preferences_po_token") %></label>
<input name="po_token" id="po_token" type="text" value="<%= preferences.po_token %>">
</div>
<div class="pure-control-group">
<label for="visitor_data"><%= translate(locale, "preferences_visitor_data") %></label>
<input name="visitor_data" id="visitor_data" type="text" value="<%= preferences.visitor_data %>">
</div>
<% if env.get?("user") %> <% if env.get?("user") %>
<div class="pure-control-group"> <div class="pure-control-group">
<a href="/generate_tokens?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Generate po_token and visitor_data for your account") %></a> <a href="/generate_tokens?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Generate po_token and visitor_data for your account") %></a>
</div> </div>
<% end %>
<% end %> <% end %>
<legend><%= translate(locale, "preferences_category_visual") %></legend> <legend><%= translate(locale, "preferences_category_visual") %></legend>

View File

@ -3,8 +3,6 @@
# #
module YoutubeAPI module YoutubeAPI
@@visitor_data : String = ""
extend self extend self
# For Android versions, see https://en.wikipedia.org/wiki/Android_version_history # For Android versions, see https://en.wikipedia.org/wiki/Android_version_history
@ -322,9 +320,7 @@ module YoutubeAPI
client_context["client"]["platform"] = platform client_context["client"]["platform"] = platform
end end
if !@@visitor_data.empty? if CONFIG.visitor_data.is_a?(String)
client_context["client"]["visitorData"] = @@visitor_data
elsif CONFIG.visitor_data.is_a?(String)
client_context["client"]["visitorData"] = CONFIG.visitor_data.as(String) client_context["client"]["visitorData"] = CONFIG.visitor_data.as(String)
end end
@ -460,12 +456,7 @@ module YoutubeAPI
*, # Force the following parameters to be passed by name *, # Force the following parameters to be passed by name
params : String, params : String,
client_config : ClientConfig | Nil = nil, client_config : ClientConfig | Nil = nil,
po_token : String | Nil,
visitor_data : String | Nil,
) )
if visitor_data
@@visitor_data = visitor_data
end
# Playback context, separate because it can be different between clients # Playback context, separate because it can be different between clients
playback_ctx = { playback_ctx = {
"html5Preference" => "HTML5_PREF_WANTS", "html5Preference" => "HTML5_PREF_WANTS",
@ -491,7 +482,7 @@ module YoutubeAPI
"contentPlaybackContext" => playback_ctx, "contentPlaybackContext" => playback_ctx,
}, },
"serviceIntegrityDimensions" => { "serviceIntegrityDimensions" => {
"poToken" => po_token || CONFIG.po_token, "poToken" => CONFIG.po_token,
}, },
} }
@ -625,9 +616,7 @@ module YoutubeAPI
headers["User-Agent"] = user_agent headers["User-Agent"] = user_agent
end end
if !@@visitor_data.empty? if CONFIG.visitor_data.is_a?(String)
headers["X-Goog-Visitor-Id"] = @@visitor_data
elsif CONFIG.visitor_data.is_a?(String)
headers["X-Goog-Visitor-Id"] = CONFIG.visitor_data.as(String) headers["X-Goog-Visitor-Id"] = CONFIG.visitor_data.as(String)
end end