mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-10-31 20:51:56 +00:00 
			
		
		
		
	Merge pull request #2428 from syeopite/ameba-fixes
Fix (some) issues detected by Ameba
This commit is contained in:
		| @@ -655,7 +655,7 @@ get "/subscription_manager" do |env| | ||||
|   end | ||||
|  | ||||
|   subscriptions = PG_DB.query_all("SELECT * FROM channels WHERE id = ANY(#{values})", as: InvidiousChannel) | ||||
|   subscriptions.sort_by! { |channel| channel.author.downcase } | ||||
|   subscriptions.sort_by!(&.author.downcase) | ||||
|  | ||||
|   if action_takeout | ||||
|     if format == "json" | ||||
| @@ -703,13 +703,13 @@ get "/subscription_manager" do |env| | ||||
|             xml.element("outline", text: title, title: title) do | ||||
|               subscriptions.each do |channel| | ||||
|                 if format == "newpipe" | ||||
|                   xmlUrl = "https://www.youtube.com/feeds/videos.xml?channel_id=#{channel.id}" | ||||
|                   xml_url = "https://www.youtube.com/feeds/videos.xml?channel_id=#{channel.id}" | ||||
|                 else | ||||
|                   xmlUrl = "#{HOST_URL}/feed/channel/#{channel.id}" | ||||
|                   xml_url = "#{HOST_URL}/feed/channel/#{channel.id}" | ||||
|                 end | ||||
|  | ||||
|                 xml.element("outline", text: channel.author, title: channel.author, | ||||
|                   "type": "rss", xmlUrl: xmlUrl) | ||||
|                   "type": "rss", xmlUrl: xml_url) | ||||
|               end | ||||
|             end | ||||
|           end | ||||
| @@ -759,7 +759,7 @@ post "/data_control" do |env| | ||||
|         body = JSON.parse(body) | ||||
|  | ||||
|         if body["subscriptions"]? | ||||
|           user.subscriptions += body["subscriptions"].as_a.map { |a| a.as_s } | ||||
|           user.subscriptions += body["subscriptions"].as_a.map(&.as_s) | ||||
|           user.subscriptions.uniq! | ||||
|  | ||||
|           user.subscriptions = get_batch_channels(user.subscriptions, PG_DB, false, false) | ||||
| @@ -768,7 +768,7 @@ post "/data_control" do |env| | ||||
|         end | ||||
|  | ||||
|         if body["watch_history"]? | ||||
|           user.watched += body["watch_history"].as_a.map { |a| a.as_s } | ||||
|           user.watched += body["watch_history"].as_a.map(&.as_s) | ||||
|           user.watched.uniq! | ||||
|           PG_DB.exec("UPDATE users SET watched = $1 WHERE email = $2", user.watched, user.email) | ||||
|         end | ||||
| @@ -876,12 +876,12 @@ post "/data_control" do |env| | ||||
|               File.write(tempfile.path, entry.io.gets_to_end) | ||||
|               db = DB.open("sqlite3://" + tempfile.path) | ||||
|  | ||||
|               user.watched += db.query_all("SELECT url FROM streams", as: String).map { |url| url.lchop("https://www.youtube.com/watch?v=") } | ||||
|               user.watched += db.query_all("SELECT url FROM streams", as: String).map(&.lchop("https://www.youtube.com/watch?v=")) | ||||
|               user.watched.uniq! | ||||
|  | ||||
|               PG_DB.exec("UPDATE users SET watched = $1 WHERE email = $2", user.watched, user.email) | ||||
|  | ||||
|               user.subscriptions += db.query_all("SELECT url FROM subscriptions", as: String).map { |url| url.lchop("https://www.youtube.com/channel/") } | ||||
|               user.subscriptions += db.query_all("SELECT url FROM subscriptions", as: String).map(&.lchop("https://www.youtube.com/channel/")) | ||||
|               user.subscriptions.uniq! | ||||
|  | ||||
|               user.subscriptions = get_batch_channels(user.subscriptions, PG_DB, false, false) | ||||
| @@ -1351,7 +1351,7 @@ error 500 do |env, ex| | ||||
|   error_template(500, ex) | ||||
| end | ||||
|  | ||||
| static_headers do |response, filepath, filestat| | ||||
| static_headers do |response| | ||||
|   response.headers.add("Cache-Control", "max-age=2629800") | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -62,7 +62,7 @@ def get_about_info(ucid, locale) | ||||
|     description_html = HTML.escape(description).gsub("\n", "<br>") | ||||
|  | ||||
|     is_family_friendly = initdata["microformat"]["microformatDataRenderer"]["familySafe"].as_bool | ||||
|     allowed_regions = initdata["microformat"]["microformatDataRenderer"]["availableCountries"].as_a.map { |a| a.as_s } | ||||
|     allowed_regions = initdata["microformat"]["microformatDataRenderer"]["availableCountries"].as_a.map(&.as_s) | ||||
|  | ||||
|     related_channels = [] of AboutRelatedChannel | ||||
|   else | ||||
| @@ -84,7 +84,7 @@ def get_about_info(ucid, locale) | ||||
|     description_html = HTML.escape(description).gsub("\n", "<br>") | ||||
|  | ||||
|     is_family_friendly = initdata["microformat"]["microformatDataRenderer"]["familySafe"].as_bool | ||||
|     allowed_regions = initdata["microformat"]["microformatDataRenderer"]["availableCountries"].as_a.map { |a| a.as_s } | ||||
|     allowed_regions = initdata["microformat"]["microformatDataRenderer"]["availableCountries"].as_a.map(&.as_s) | ||||
|  | ||||
|     related_channels = initdata["contents"]["twoColumnBrowseResultsRenderer"] | ||||
|       .["secondaryContents"]?.try &.["browseSecondaryContentsRenderer"]["contents"][0]? | ||||
| @@ -149,7 +149,7 @@ def get_about_info(ucid, locale) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|     tabs = tabs_json.reject { |node| node["tabRenderer"]?.nil? }.map { |node| node["tabRenderer"]["title"].as_s.downcase } | ||||
|     tabs = tabs_json.reject { |node| node["tabRenderer"]?.nil? }.map(&.["tabRenderer"]["title"].as_s.downcase) | ||||
|   end | ||||
|  | ||||
|   sub_count = initdata["header"]["c4TabbedHeaderRenderer"]?.try &.["subscriberCountText"]?.try &.["simpleText"]?.try &.as_s? | ||||
|   | ||||
| @@ -101,7 +101,7 @@ struct ChannelVideo | ||||
|   def to_tuple | ||||
|     {% begin %} | ||||
|       { | ||||
|         {{*@type.instance_vars.map { |var| var.name }}} | ||||
|         {{*@type.instance_vars.map(&.name)}} | ||||
|       } | ||||
|     {% end %} | ||||
|   end | ||||
|   | ||||
| @@ -242,7 +242,7 @@ def produce_channel_community_continuation(ucid, cursor) | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
| @@ -255,11 +255,11 @@ def extract_channel_community_cursor(continuation) | ||||
|     .try { |i| Base64.decode(i) } | ||||
|     .try { |i| IO::Memory.new(i) } | ||||
|     .try { |i| Protodec::Any.parse(i) } | ||||
|     .try { |i| i["80226972:0:embedded"]["3:1:base64"].as_h } | ||||
|     .try(&.["80226972:0:embedded"]["3:1:base64"].as_h) | ||||
|  | ||||
|   if object["53:2:embedded"]?.try &.["3:0:embedded"]? | ||||
|     object["53:2:embedded"]["3:0:embedded"]["2:0:string"] = object["53:2:embedded"]["3:0:embedded"] | ||||
|       .try { |i| i["2:0:base64"].as_h } | ||||
|       .try(&.["2:0:base64"].as_h) | ||||
|       .try { |i| Protodec::Any.cast_json(i) } | ||||
|       .try { |i| Protodec::Any.from_json(i) } | ||||
|       .try { |i| Base64.urlsafe_encode(i, padding: false) } | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
| def fetch_channel_playlists(ucid, author, continuation, sort_by) | ||||
|   if continuation | ||||
|     response_json = YoutubeAPI.browse(continuation) | ||||
|     continuationItems = response_json["onResponseReceivedActions"]? | ||||
|     continuation_items = response_json["onResponseReceivedActions"]? | ||||
|       .try &.[0]["appendContinuationItemsAction"]["continuationItems"] | ||||
|  | ||||
|     return [] of SearchItem, nil if !continuationItems | ||||
|     return [] of SearchItem, nil if !continuation_items | ||||
|  | ||||
|     items = [] of SearchItem | ||||
|     continuationItems.as_a.select(&.as_h.has_key?("gridPlaylistRenderer")).each { |item| | ||||
|     continuation_items.as_a.select(&.as_h.has_key?("gridPlaylistRenderer")).each { |item| | ||||
|       extract_item(item, author, ucid).try { |t| items << t } | ||||
|     } | ||||
|  | ||||
|     continuation = continuationItems.as_a.last["continuationItemRenderer"]? | ||||
|     continuation = continuation_items.as_a.last["continuationItemRenderer"]? | ||||
|       .try &.["continuationEndpoint"]["continuationCommand"]["token"].as_s | ||||
|   else | ||||
|     url = "/channel/#{ucid}/playlists?flow=list&view=1" | ||||
| @@ -84,7 +84,7 @@ def produce_channel_playlists_url(ucid, cursor, sort = "newest", auto_generated | ||||
|   object["80226972:embedded"]["3:string"] = Base64.urlsafe_encode(Protodec::Any.from_json(Protodec::Any.cast_json(object["80226972:embedded"]["3:base64"]))) | ||||
|   object["80226972:embedded"].delete("3:base64") | ||||
|  | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
|   | ||||
| @@ -49,7 +49,7 @@ def produce_channel_videos_continuation(ucid, page = 1, auto_generated = nil, so | ||||
|   object["80226972:embedded"]["3:string"] = Base64.urlsafe_encode(Protodec::Any.from_json(Protodec::Any.cast_json(object["80226972:embedded"]["3:base64"]))) | ||||
|   object["80226972:embedded"].delete("3:base64") | ||||
|  | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
|   | ||||
| @@ -72,10 +72,9 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b | ||||
|   response = YoutubeAPI.next(continuation: ctoken, client_config: client_config) | ||||
|   contents = nil | ||||
|  | ||||
|   if response["onResponseReceivedEndpoints"]? | ||||
|     onResponseReceivedEndpoints = response["onResponseReceivedEndpoints"] | ||||
|   if on_response_received_endpoints = response["onResponseReceivedEndpoints"]? | ||||
|     header = nil | ||||
|     onResponseReceivedEndpoints.as_a.each do |item| | ||||
|     on_response_received_endpoints.as_a.each do |item| | ||||
|       if item["reloadContinuationItemsCommand"]? | ||||
|         case item["reloadContinuationItemsCommand"]["slot"] | ||||
|         when "RELOAD_CONTINUATION_SLOT_HEADER" | ||||
| @@ -97,7 +96,8 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b | ||||
|     contents = body["contents"]? | ||||
|     header = body["header"]? | ||||
|     if body["continuations"]? | ||||
|       moreRepliesContinuation = body["continuations"][0]["nextContinuationData"]["continuation"].as_s | ||||
|       # Removable? Doesn't seem like this is used. | ||||
|       more_replies_continuation = body["continuations"][0]["nextContinuationData"]["continuation"].as_s | ||||
|     end | ||||
|   else | ||||
|     raise InfoException.new("Could not fetch comments") | ||||
| @@ -111,10 +111,10 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   continuationItemRenderer = nil | ||||
|   continuation_item_renderer = nil | ||||
|   contents.as_a.reject! do |item| | ||||
|     if item["continuationItemRenderer"]? | ||||
|       continuationItemRenderer = item["continuationItemRenderer"] | ||||
|       continuation_item_renderer = item["continuationItemRenderer"] | ||||
|       true | ||||
|     end | ||||
|   end | ||||
| @@ -232,14 +232,14 @@ def fetch_youtube_comments(id, cursor, format, locale, thin_mode, region, sort_b | ||||
|         end | ||||
|       end | ||||
|  | ||||
|       if continuationItemRenderer | ||||
|         if continuationItemRenderer["continuationEndpoint"]? | ||||
|           continuationEndpoint = continuationItemRenderer["continuationEndpoint"] | ||||
|         elsif continuationItemRenderer["button"]? | ||||
|           continuationEndpoint = continuationItemRenderer["button"]["buttonRenderer"]["command"] | ||||
|       if continuation_item_renderer | ||||
|         if continuation_item_renderer["continuationEndpoint"]? | ||||
|           continuation_endpoint = continuation_item_renderer["continuationEndpoint"] | ||||
|         elsif continuation_item_renderer["button"]? | ||||
|           continuation_endpoint = continuation_item_renderer["button"]["buttonRenderer"]["command"] | ||||
|         end | ||||
|         if continuationEndpoint | ||||
|           json.field "continuation", continuationEndpoint["continuationCommand"]["token"].as_s | ||||
|         if continuation_endpoint | ||||
|           json.field "continuation", continuation_endpoint["continuationCommand"]["token"].as_s | ||||
|         end | ||||
|       end | ||||
|     end | ||||
| @@ -638,7 +638,7 @@ def produce_comment_continuation(video_id, cursor = "", sort_by = "top") | ||||
|     object["6:embedded"].as(Hash)["4:embedded"].as(Hash)["6:varint"] = 0_i64 | ||||
|   end | ||||
|  | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
| @@ -673,7 +673,7 @@ def produce_comment_reply_continuation(video_id, ucid, comment_id) | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
|   | ||||
| @@ -132,8 +132,6 @@ def error_redirect_helper(env : HTTP::Server::Context, locale : Hash(String, JSO | ||||
|         </li> | ||||
|       </ul> | ||||
|     END_HTML | ||||
|  | ||||
|     return next_step_html | ||||
|   else | ||||
|     return "" | ||||
|   end | ||||
|   | ||||
| @@ -89,14 +89,14 @@ def check_table(db, table_name, struct_type = nil) | ||||
|   struct_array = struct_type.type_array | ||||
|   column_array = get_column_array(db, table_name) | ||||
|   column_types = File.read("config/sql/#{table_name}.sql").match(/CREATE TABLE public\.#{table_name}\n\((?<types>[\d\D]*?)\);/) | ||||
|     .try &.["types"].split(",").map { |line| line.strip }.reject &.starts_with?("CONSTRAINT") | ||||
|     .try &.["types"].split(",").map(&.strip).reject &.starts_with?("CONSTRAINT") | ||||
|  | ||||
|   return if !column_types | ||||
|  | ||||
|   struct_array.each_with_index do |name, i| | ||||
|     if name != column_array[i]? | ||||
|       if !column_array[i]? | ||||
|         new_column = column_types.select { |line| line.starts_with? name }[0] | ||||
|         new_column = column_types.select(&.starts_with?(name))[0] | ||||
|         LOGGER.info("check_table: ALTER TABLE #{table_name} ADD COLUMN #{new_column}") | ||||
|         db.exec("ALTER TABLE #{table_name} ADD COLUMN #{new_column}") | ||||
|         next | ||||
| @@ -104,14 +104,14 @@ def check_table(db, table_name, struct_type = nil) | ||||
|  | ||||
|       # Column doesn't exist | ||||
|       if !column_array.includes? name | ||||
|         new_column = column_types.select { |line| line.starts_with? name }[0] | ||||
|         new_column = column_types.select(&.starts_with?(name))[0] | ||||
|         db.exec("ALTER TABLE #{table_name} ADD COLUMN #{new_column}") | ||||
|       end | ||||
|  | ||||
|       # Column exists but in the wrong position, rotate | ||||
|       if struct_array.includes? column_array[i] | ||||
|         until name == column_array[i] | ||||
|           new_column = column_types.select { |line| line.starts_with? column_array[i] }[0]?.try &.gsub("#{column_array[i]}", "#{column_array[i]}_new") | ||||
|           new_column = column_types.select(&.starts_with?(column_array[i]))[0]?.try &.gsub("#{column_array[i]}", "#{column_array[i]}_new") | ||||
|  | ||||
|           # There's a column we didn't expect | ||||
|           if !new_column | ||||
|   | ||||
| @@ -62,7 +62,7 @@ struct SearchVideo | ||||
|     if xml | ||||
|       to_xml(HOST_URL, auto_generated, query_params, xml) | ||||
|     else | ||||
|       XML.build do |json| | ||||
|       XML.build do |xml| | ||||
|         to_xml(HOST_URL, auto_generated, query_params, xml) | ||||
|       end | ||||
|     end | ||||
|   | ||||
| @@ -30,7 +30,7 @@ struct DecryptFunction | ||||
|  | ||||
|       case op_body | ||||
|       when "{a.reverse()" | ||||
|         operations[op_name] = ->(a : Array(String), b : Int32) { a.reverse } | ||||
|         operations[op_name] = ->(a : Array(String), _b : Int32) { a.reverse } | ||||
|       when "{a.splice(0,b)" | ||||
|         operations[op_name] = ->(a : Array(String), b : Int32) { a.delete_at(0..(b - 1)); a } | ||||
|       else | ||||
|   | ||||
| @@ -173,7 +173,7 @@ module Kemal | ||||
|             return | ||||
|           end | ||||
|  | ||||
|           if @cached_files.sum { |element| element[1][:data].bytesize } + (size = File.size(file_path)) < CACHE_LIMIT | ||||
|           if @cached_files.sum(&.[1][:data].bytesize) + (size = File.size(file_path)) < CACHE_LIMIT | ||||
|             data = Bytes.new(size) | ||||
|             File.open(file_path) do |file| | ||||
|               file.read(data) | ||||
|   | ||||
| @@ -46,7 +46,7 @@ def sign_token(key, hash) | ||||
|     next if key == "signature" | ||||
|  | ||||
|     if value.is_a?(JSON::Any) && value.as_a? | ||||
|       value = value.as_a.map { |i| i.as_s } | ||||
|       value = value.as_a.map(&.as_s) | ||||
|     end | ||||
|  | ||||
|     case value | ||||
| @@ -82,7 +82,7 @@ def validate_request(token, session, request, key, db, locale = nil) | ||||
|     raise InfoException.new("Erroneous token") | ||||
|   end | ||||
|  | ||||
|   scopes = token["scopes"].as_a.map { |v| v.as_s } | ||||
|   scopes = token["scopes"].as_a.map(&.as_s) | ||||
|   scope = "#{request.method}:#{request.path.lchop("/api/v1/auth/").lstrip("/")}" | ||||
|   if !scopes_include_scope(scopes, scope) | ||||
|     raise InfoException.new("Invalid scope") | ||||
| @@ -105,11 +105,11 @@ end | ||||
|  | ||||
| def scope_includes_scope(scope, subset) | ||||
|   methods, endpoint = scope.split(":") | ||||
|   methods = methods.split(";").map { |method| method.upcase }.reject { |method| method.empty? }.sort | ||||
|   methods = methods.split(";").map(&.upcase).reject(&.empty?).sort! | ||||
|   endpoint = endpoint.downcase | ||||
|  | ||||
|   subset_methods, subset_endpoint = subset.split(":") | ||||
|   subset_methods = subset_methods.split(";").map { |method| method.upcase }.sort | ||||
|   subset_methods = subset_methods.split(";").map(&.upcase).sort! | ||||
|   subset_endpoint = subset_endpoint.downcase | ||||
|  | ||||
|   if methods.empty? | ||||
|   | ||||
| @@ -15,8 +15,8 @@ class Invidious::Jobs::PullPopularVideosJob < Invidious::Jobs::BaseJob | ||||
|   def begin | ||||
|     loop do | ||||
|       videos = db.query_all(QUERY, as: ChannelVideo) | ||||
|         .sort_by(&.published) | ||||
|         .reverse | ||||
|         .sort_by!(&.published) | ||||
|         .reverse! | ||||
|  | ||||
|       POPULAR_VIDEOS.set(videos) | ||||
|  | ||||
|   | ||||
| @@ -72,7 +72,7 @@ def fetch_mix(rdid, video_id, cookies = nil, locale = nil) | ||||
|     videos += next_page.videos | ||||
|   end | ||||
|  | ||||
|   videos.uniq! { |video| video.id } | ||||
|   videos.uniq!(&.id) | ||||
|   videos = videos.first(50) | ||||
|   return Mix.new({ | ||||
|     title:  mix_title, | ||||
|   | ||||
| @@ -51,7 +51,7 @@ struct PlaylistVideo | ||||
|     if xml | ||||
|       to_xml(auto_generated, xml) | ||||
|     else | ||||
|       XML.build do |json| | ||||
|       XML.build do |xml| | ||||
|         to_xml(auto_generated, xml) | ||||
|       end | ||||
|     end | ||||
| @@ -143,7 +143,7 @@ struct Playlist | ||||
|       json.field "videos" do | ||||
|         json.array do | ||||
|           videos = get_playlist_videos(PG_DB, self, offset: offset, locale: locale, video_id: video_id) | ||||
|           videos.each_with_index do |video, index| | ||||
|           videos.each do |video| | ||||
|             video.to_json(locale, json) | ||||
|           end | ||||
|         end | ||||
| @@ -336,7 +336,7 @@ def produce_playlist_continuation(id, index) | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
|   | ||||
| @@ -47,7 +47,7 @@ module Invidious::Routes::API::Manifest | ||||
|     end | ||||
|  | ||||
|     audio_streams = video.audio_streams | ||||
|     video_streams = video.video_streams.sort_by { |stream| {stream["width"].as_i, stream["fps"].as_i} }.reverse | ||||
|     video_streams = video.video_streams.sort_by { |stream| {stream["width"].as_i, stream["fps"].as_i} }.reverse! | ||||
|  | ||||
|     manifest = XML.build(indent: "  ", encoding: "UTF-8") do |xml| | ||||
|       xml.element("MPD", "xmlns": "urn:mpeg:dash:schema:mpd:2011", | ||||
|   | ||||
| @@ -335,11 +335,11 @@ module Invidious::Routes::API::V1::Authenticated | ||||
|  | ||||
|     case env.request.headers["Content-Type"]? | ||||
|     when "application/x-www-form-urlencoded" | ||||
|       scopes = env.params.body.select { |k, v| k.match(/^scopes\[\d+\]$/) }.map { |k, v| v } | ||||
|       scopes = env.params.body.select { |k, _| k.match(/^scopes\[\d+\]$/) }.map { |_, v| v } | ||||
|       callback_url = env.params.body["callbackUrl"]? | ||||
|       expire = env.params.body["expire"]?.try &.to_i? | ||||
|     when "application/json" | ||||
|       scopes = env.params.json["scopes"].as(Array).map { |v| v.as_s } | ||||
|       scopes = env.params.json["scopes"].as(Array).map(&.as_s) | ||||
|       callback_url = env.params.json["callbackUrl"]?.try &.as(String) | ||||
|       expire = env.params.json["expire"]?.try &.as(Int64) | ||||
|     else | ||||
|   | ||||
| @@ -20,7 +20,7 @@ module Invidious::Routes::API::V1::Search | ||||
|     duration = env.params.query["duration"]?.try &.downcase | ||||
|     duration ||= "" | ||||
|  | ||||
|     features = env.params.query["features"]?.try &.split(",").map { |feature| feature.downcase } | ||||
|     features = env.params.query["features"]?.try &.split(",").map(&.downcase) | ||||
|     features ||= [] of String | ||||
|  | ||||
|     content_type = env.params.query["type"]?.try &.downcase | ||||
|   | ||||
| @@ -58,7 +58,7 @@ module Invidious::Routes::API::V1::Videos | ||||
|               captions.each do |caption| | ||||
|                 json.object do | ||||
|                   json.field "label", caption.name | ||||
|                   json.field "languageCode", caption.languageCode | ||||
|                   json.field "languageCode", caption.language_code | ||||
|                   json.field "url", "/api/v1/captions/#{id}?label=#{URI.encode_www_form(caption.name)}" | ||||
|                 end | ||||
|               end | ||||
| @@ -73,7 +73,7 @@ module Invidious::Routes::API::V1::Videos | ||||
|     env.response.content_type = "text/vtt; charset=UTF-8" | ||||
|  | ||||
|     if lang | ||||
|       caption = captions.select { |caption| caption.languageCode == lang } | ||||
|       caption = captions.select { |caption| caption.language_code == lang } | ||||
|     else | ||||
|       caption = captions.select { |caption| caption.name == label } | ||||
|     end | ||||
| @@ -84,7 +84,7 @@ module Invidious::Routes::API::V1::Videos | ||||
|       caption = caption[0] | ||||
|     end | ||||
|  | ||||
|     url = URI.parse("#{caption.baseUrl}&tlang=#{tlang}").request_target | ||||
|     url = URI.parse("#{caption.base_url}&tlang=#{tlang}").request_target | ||||
|  | ||||
|     # Auto-generated captions often have cues that aren't aligned properly with the video, | ||||
|     # as well as some other markup that makes it cumbersome, so we try to fix that here | ||||
| @@ -96,7 +96,7 @@ module Invidious::Routes::API::V1::Videos | ||||
|         str << <<-END_VTT | ||||
|         WEBVTT | ||||
|         Kind: captions | ||||
|         Language: #{tlang || caption.languageCode} | ||||
|         Language: #{tlang || caption.language_code} | ||||
|  | ||||
|  | ||||
|         END_VTT | ||||
|   | ||||
| @@ -29,8 +29,8 @@ module Invidious::Routes::Channels | ||||
|           item.author | ||||
|         end | ||||
|       end | ||||
|       items = items.select(&.is_a?(SearchPlaylist)).map(&.as(SearchPlaylist)) | ||||
|       items.each { |item| item.author = "" } | ||||
|       items = items.select(SearchPlaylist).map(&.as(SearchPlaylist)) | ||||
|       items.each(&.author = "") | ||||
|     else | ||||
|       sort_options = {"newest", "oldest", "popular"} | ||||
|       sort_by ||= "newest" | ||||
| @@ -57,8 +57,8 @@ module Invidious::Routes::Channels | ||||
|     end | ||||
|  | ||||
|     items, continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) | ||||
|     items = items.select { |item| item.is_a?(SearchPlaylist) }.map { |item| item.as(SearchPlaylist) } | ||||
|     items.each { |item| item.author = "" } | ||||
|     items = items.select(SearchPlaylist).map(&.as(SearchPlaylist)) | ||||
|     items.each(&.author = "") | ||||
|  | ||||
|     templated "playlists" | ||||
|   end | ||||
|   | ||||
| @@ -168,11 +168,11 @@ module Invidious::Routes::Embed | ||||
|  | ||||
|     preferred_captions = captions.select { |caption| | ||||
|       params.preferred_captions.includes?(caption.name) || | ||||
|         params.preferred_captions.includes?(caption.languageCode.split("-")[0]) | ||||
|         params.preferred_captions.includes?(caption.language_code.split("-")[0]) | ||||
|     } | ||||
|     preferred_captions.sort_by! { |caption| | ||||
|       (params.preferred_captions.index(caption.name) || | ||||
|         params.preferred_captions.index(caption.languageCode.split("-")[0])).not_nil! | ||||
|         params.preferred_captions.index(caption.language_code.split("-")[0])).not_nil! | ||||
|     } | ||||
|     captions = captions - preferred_captions | ||||
|  | ||||
|   | ||||
| @@ -395,7 +395,7 @@ module Invidious::Routes::Login | ||||
|             return templated "login" | ||||
|           end | ||||
|  | ||||
|           tokens = env.params.body.select { |k, v| k.match(/^token\[\d+\]$/) }.map { |k, v| v } | ||||
|           tokens = env.params.body.select { |k, _| k.match(/^token\[\d+\]$/) }.map { |_, v| v } | ||||
|  | ||||
|           answer ||= "" | ||||
|           captcha_type ||= "image" | ||||
| @@ -419,7 +419,7 @@ module Invidious::Routes::Login | ||||
|  | ||||
|             found_valid_captcha = false | ||||
|             error_exception = Exception.new | ||||
|             tokens.each_with_index do |token, i| | ||||
|             tokens.each do |token| | ||||
|               begin | ||||
|                 validate_request(token, answer, env.request, HMAC_KEY, PG_DB, locale) | ||||
|                 found_valid_captcha = true | ||||
|   | ||||
| @@ -245,7 +245,7 @@ module Invidious::Routes::Playlists | ||||
|     if query | ||||
|       begin | ||||
|         search_query, count, items, operators = process_search_query(query, page, user, region: nil) | ||||
|         videos = items.select { |item| item.is_a? SearchVideo }.map { |item| item.as(SearchVideo) } | ||||
|         videos = items.select(SearchVideo).map(&.as(SearchVideo)) | ||||
|       rescue ex | ||||
|         videos = [] of SearchVideo | ||||
|         count = 0 | ||||
|   | ||||
| @@ -20,7 +20,7 @@ module Invidious::Routes::VideoPlayback | ||||
|       host = "https://r#{fvip}---#{mns.pop}.googlevideo.com" | ||||
|     end | ||||
|  | ||||
|     url = "/videoplayback?#{query_params.to_s}" | ||||
|     url = "/videoplayback?#{query_params}" | ||||
|  | ||||
|     headers = HTTP::Headers.new | ||||
|     REQUEST_HEADERS_WHITELIST.each do |header| | ||||
|   | ||||
| @@ -153,11 +153,11 @@ module Invidious::Routes::Watch | ||||
|  | ||||
|     preferred_captions = captions.select { |caption| | ||||
|       params.preferred_captions.includes?(caption.name) || | ||||
|         params.preferred_captions.includes?(caption.languageCode.split("-")[0]) | ||||
|         params.preferred_captions.includes?(caption.language_code.split("-")[0]) | ||||
|     } | ||||
|     preferred_captions.sort_by! { |caption| | ||||
|       (params.preferred_captions.index(caption.name) || | ||||
|         params.preferred_captions.index(caption.languageCode.split("-")[0])).not_nil! | ||||
|         params.preferred_captions.index(caption.language_code.split("-")[0])).not_nil! | ||||
|     } | ||||
|     captions = captions - preferred_captions | ||||
|  | ||||
|   | ||||
| @@ -14,13 +14,13 @@ def channel_search(query, page, channel) | ||||
|   continuation = produce_channel_search_continuation(ucid, query, page) | ||||
|   response_json = YoutubeAPI.browse(continuation) | ||||
|  | ||||
|   continuationItems = response_json["onResponseReceivedActions"]? | ||||
|   continuation_items = response_json["onResponseReceivedActions"]? | ||||
|     .try &.[0]["appendContinuationItemsAction"]["continuationItems"] | ||||
|  | ||||
|   return 0, [] of SearchItem if !continuationItems | ||||
|   return 0, [] of SearchItem if !continuation_items | ||||
|  | ||||
|   items = [] of SearchItem | ||||
|   continuationItems.as_a.select(&.as_h.has_key?("itemSectionRenderer")).each { |item| | ||||
|   continuation_items.as_a.select(&.as_h.has_key?("itemSectionRenderer")).each { |item| | ||||
|     extract_item(item["itemSectionRenderer"]["contents"].as_a[0]) | ||||
|       .try { |t| items << t } | ||||
|   } | ||||
| @@ -128,7 +128,7 @@ def produce_search_params(page = 1, sort : String = "relevance", date : String = | ||||
|     object.delete("2:embedded") | ||||
|   end | ||||
|  | ||||
|   params = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   params = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
| @@ -161,7 +161,7 @@ def produce_channel_search_continuation(ucid, query, page) | ||||
|     }, | ||||
|   } | ||||
|  | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(object) } | ||||
|   continuation = object.try { |i| Protodec::Any.cast_json(i) } | ||||
|     .try { |i| Protodec::Any.from_json(i) } | ||||
|     .try { |i| Base64.urlsafe_encode(i) } | ||||
|     .try { |i| URI.encode_www_form(i) } | ||||
| @@ -183,7 +183,7 @@ def process_search_query(query, page, user, region) | ||||
|   sort = "relevance" | ||||
|   subscriptions = nil | ||||
|  | ||||
|   operators = query.split(" ").select { |a| a.match(/\w+:[\w,]+/) } | ||||
|   operators = query.split(" ").select(&.match(/\w+:[\w,]+/)) | ||||
|   operators.each do |operator| | ||||
|     key, value = operator.downcase.split(":") | ||||
|  | ||||
|   | ||||
| @@ -248,17 +248,17 @@ def get_subscription_feed(db, user, max_results = 40, page = 1) | ||||
|     notifications = db.query_all("SELECT * FROM channel_videos WHERE id IN (#{args}) ORDER BY published DESC", args: notifications, as: ChannelVideo) | ||||
|     videos = [] of ChannelVideo | ||||
|  | ||||
|     notifications.sort_by! { |video| video.published }.reverse! | ||||
|     notifications.sort_by!(&.published).reverse! | ||||
|  | ||||
|     case user.preferences.sort | ||||
|     when "alphabetically" | ||||
|       notifications.sort_by! { |video| video.title } | ||||
|       notifications.sort_by!(&.title) | ||||
|     when "alphabetically - reverse" | ||||
|       notifications.sort_by! { |video| video.title }.reverse! | ||||
|       notifications.sort_by!(&.title).reverse! | ||||
|     when "channel name" | ||||
|       notifications.sort_by! { |video| video.author } | ||||
|       notifications.sort_by!(&.author) | ||||
|     when "channel name - reverse" | ||||
|       notifications.sort_by! { |video| video.author }.reverse! | ||||
|       notifications.sort_by!(&.author).reverse! | ||||
|     else nil # Ignore | ||||
|     end | ||||
|   else | ||||
| @@ -279,7 +279,7 @@ def get_subscription_feed(db, user, max_results = 40, page = 1) | ||||
|         videos = PG_DB.query_all("SELECT DISTINCT ON (ucid) * FROM #{view_name} ORDER BY ucid, published DESC", as: ChannelVideo) | ||||
|       end | ||||
|  | ||||
|       videos.sort_by! { |video| video.published }.reverse! | ||||
|       videos.sort_by!(&.published).reverse! | ||||
|     else | ||||
|       if user.preferences.unseen_only | ||||
|         # Only show unwatched | ||||
| @@ -299,15 +299,15 @@ def get_subscription_feed(db, user, max_results = 40, page = 1) | ||||
|  | ||||
|     case user.preferences.sort | ||||
|     when "published - reverse" | ||||
|       videos.sort_by! { |video| video.published } | ||||
|       videos.sort_by!(&.published) | ||||
|     when "alphabetically" | ||||
|       videos.sort_by! { |video| video.title } | ||||
|       videos.sort_by!(&.title) | ||||
|     when "alphabetically - reverse" | ||||
|       videos.sort_by! { |video| video.title }.reverse! | ||||
|       videos.sort_by!(&.title).reverse! | ||||
|     when "channel name" | ||||
|       videos.sort_by! { |video| video.author } | ||||
|       videos.sort_by!(&.author) | ||||
|     when "channel name - reverse" | ||||
|       videos.sort_by! { |video| video.author }.reverse! | ||||
|       videos.sort_by!(&.author).reverse! | ||||
|     else nil # Ignore | ||||
|     end | ||||
|  | ||||
|   | ||||
| @@ -426,7 +426,7 @@ struct Video | ||||
|           self.captions.each do |caption| | ||||
|             json.object do | ||||
|               json.field "label", caption.name | ||||
|               json.field "languageCode", caption.languageCode | ||||
|               json.field "language_code", caption.language_code | ||||
|               json.field "url", "/api/v1/captions/#{id}?label=#{URI.encode_www_form(caption.name)}" | ||||
|             end | ||||
|           end | ||||
| @@ -703,10 +703,10 @@ struct Video | ||||
|     return @captions.as(Array(Caption)) if @captions | ||||
|     captions = info["captions"]?.try &.["playerCaptionsTracklistRenderer"]?.try &.["captionTracks"]?.try &.as_a.map do |caption| | ||||
|       name = caption["name"]["simpleText"]? || caption["name"]["runs"][0]["text"] | ||||
|       languageCode = caption["languageCode"].to_s | ||||
|       baseUrl = caption["baseUrl"].to_s | ||||
|       language_code = caption["languageCode"].to_s | ||||
|       base_url = caption["baseUrl"].to_s | ||||
|  | ||||
|       caption = Caption.new(name.to_s, languageCode, baseUrl) | ||||
|       caption = Caption.new(name.to_s, language_code, base_url) | ||||
|       caption.name = caption.name.split(" - ")[0] | ||||
|       caption | ||||
|     end | ||||
| @@ -785,16 +785,16 @@ end | ||||
|  | ||||
| struct Caption | ||||
|   property name | ||||
|   property languageCode | ||||
|   property baseUrl | ||||
|   property language_code | ||||
|   property base_url | ||||
|  | ||||
|   getter name : String | ||||
|   getter languageCode : String | ||||
|   getter baseUrl : String | ||||
|   getter language_code : String | ||||
|   getter base_url : String | ||||
|  | ||||
|   setter name | ||||
|  | ||||
|   def initialize(@name, @languageCode, @baseUrl) | ||||
|   def initialize(@name, @language_code, @base_url) | ||||
|   end | ||||
| end | ||||
|  | ||||
| @@ -880,7 +880,7 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_ | ||||
|  | ||||
|   primary_results = player_response.try &.["contents"]?.try &.["twoColumnWatchNextResults"]?.try &.["results"]? | ||||
|     .try &.["results"]?.try &.["contents"]? | ||||
|   sentiment_bar = primary_results.try &.as_a.select { |object| object["videoPrimaryInfoRenderer"]? }[0]? | ||||
|   sentiment_bar = primary_results.try &.as_a.select(&.["videoPrimaryInfoRenderer"]?)[0]? | ||||
|     .try &.["videoPrimaryInfoRenderer"]? | ||||
|       .try &.["sentimentBar"]? | ||||
|         .try &.["sentimentBarRenderer"]? | ||||
| @@ -891,11 +891,11 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_ | ||||
|   params["likes"] = JSON::Any.new(likes) | ||||
|   params["dislikes"] = JSON::Any.new(dislikes) | ||||
|  | ||||
|   params["descriptionHtml"] = JSON::Any.new(primary_results.try &.as_a.select { |object| object["videoSecondaryInfoRenderer"]? }[0]? | ||||
|   params["descriptionHtml"] = JSON::Any.new(primary_results.try &.as_a.select(&.["videoSecondaryInfoRenderer"]?)[0]? | ||||
|     .try &.["videoSecondaryInfoRenderer"]?.try &.["description"]?.try &.["runs"]? | ||||
|       .try &.as_a.try { |t| content_to_comment_html(t).gsub("\n", "<br/>") } || "<p></p>") | ||||
|  | ||||
|   metadata = primary_results.try &.as_a.select { |object| object["videoSecondaryInfoRenderer"]? }[0]? | ||||
|   metadata = primary_results.try &.as_a.select(&.["videoSecondaryInfoRenderer"]?)[0]? | ||||
|     .try &.["videoSecondaryInfoRenderer"]? | ||||
|       .try &.["metadataRowContainer"]? | ||||
|         .try &.["metadataRowContainerRenderer"]? | ||||
| @@ -928,7 +928,7 @@ def extract_video_info(video_id : String, proxy_region : String? = nil, context_ | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   author_info = primary_results.try &.as_a.select { |object| object["videoSecondaryInfoRenderer"]? }[0]? | ||||
|   author_info = primary_results.try &.as_a.select(&.["videoSecondaryInfoRenderer"]?)[0]? | ||||
|     .try &.["videoSecondaryInfoRenderer"]?.try &.["owner"]?.try &.["videoOwnerRenderer"]? | ||||
|  | ||||
|   params["authorThumbnail"] = JSON::Any.new(author_info.try &.["thumbnail"]? | ||||
| @@ -1023,13 +1023,13 @@ end | ||||
| def process_video_params(query, preferences) | ||||
|   annotations = query["iv_load_policy"]?.try &.to_i? | ||||
|   autoplay = query["autoplay"]?.try { |q| (q == "true" || q == "1").to_unsafe } | ||||
|   comments = query["comments"]?.try &.split(",").map { |a| a.downcase } | ||||
|   comments = query["comments"]?.try &.split(",").map(&.downcase) | ||||
|   continue = query["continue"]?.try { |q| (q == "true" || q == "1").to_unsafe } | ||||
|   continue_autoplay = query["continue_autoplay"]?.try { |q| (q == "true" || q == "1").to_unsafe } | ||||
|   listen = query["listen"]?.try { |q| (q == "true" || q == "1").to_unsafe } | ||||
|   local = query["local"]?.try { |q| (q == "true" || q == "1").to_unsafe } | ||||
|   player_style = query["player_style"]? | ||||
|   preferred_captions = query["subtitles"]?.try &.split(",").map { |a| a.downcase } | ||||
|   preferred_captions = query["subtitles"]?.try &.split(",").map(&.downcase) | ||||
|   quality = query["quality"]? | ||||
|   quality_dash = query["quality_dash"]? | ||||
|   region = query["region"]? | ||||
|   | ||||
| @@ -184,7 +184,7 @@ we're going to need to do it here in order to allow for translations. | ||||
|                                 </option> | ||||
|                             <% end %> | ||||
|                             <% captions.each do |caption| %> | ||||
|                                 <option value='{"id":"<%= video.id %>","label":"<%= caption.name %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= caption.languageCode %>.vtt"}'> | ||||
|                                 <option value='{"id":"<%= video.id %>","label":"<%= caption.name %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= caption.language_code %>.vtt"}'> | ||||
|                                     <%= translate(locale, "Subtitles - `x` (.vtt)", caption.name) %> | ||||
|                                 </option> | ||||
|                             <% end %> | ||||
|   | ||||
| @@ -40,7 +40,7 @@ def extract_videos(initial_data : Hash(String, JSON::Any), author_fallback : Str | ||||
|       target << i | ||||
|     end | ||||
|   end | ||||
|   return target.select(&.is_a?(SearchVideo)).map(&.as(SearchVideo)) | ||||
|   return target.select(SearchVideo).map(&.as(SearchVideo)) | ||||
| end | ||||
|  | ||||
| def extract_selected_tab(tabs) | ||||
|   | ||||
| @@ -236,7 +236,7 @@ def get_spys_proxies(country_code = "US") | ||||
|     proxies << {ip: ip, port: port, score: score} | ||||
|   end | ||||
|  | ||||
|   proxies = proxies.sort_by { |proxy| proxy[:score] }.reverse | ||||
|   proxies = proxies.sort_by!(&.[:score]).reverse! | ||||
|   return proxies | ||||
| end | ||||
|  | ||||
| @@ -256,7 +256,7 @@ def decrypt_port(p, x) | ||||
|   p = p.gsub(/\b\w+\b/, x) | ||||
|  | ||||
|   p = p.split(";") | ||||
|   p = p.map { |item| item.split("=") } | ||||
|   p = p.map(&.split("=")) | ||||
|  | ||||
|   mapping = {} of String => Int32 | ||||
|   p.each do |item| | ||||
|   | ||||
| @@ -410,8 +410,8 @@ module YoutubeAPI | ||||
|  | ||||
|     # Logging | ||||
|     LOGGER.debug("YoutubeAPI: Using endpoint: \"#{endpoint}\"") | ||||
|     LOGGER.trace("YoutubeAPI: ClientConfig: #{client_config.to_s}") | ||||
|     LOGGER.trace("YoutubeAPI: POST data: #{data.to_s}") | ||||
|     LOGGER.trace("YoutubeAPI: ClientConfig: #{client_config}") | ||||
|     LOGGER.trace("YoutubeAPI: POST data: #{data}") | ||||
|  | ||||
|     # Send the POST request | ||||
|     if client_config.proxy_region | ||||
| @@ -436,7 +436,7 @@ module YoutubeAPI | ||||
|       # Logging | ||||
|       LOGGER.error("YoutubeAPI: Got error #{code} when requesting #{endpoint}") | ||||
|       LOGGER.error("YoutubeAPI: #{message}") | ||||
|       LOGGER.info("YoutubeAPI: POST data was: #{data.to_s}") | ||||
|       LOGGER.info("YoutubeAPI: POST data was: #{data}") | ||||
|  | ||||
|       raise InfoException.new("Could not extract JSON. Youtube API returned \ | ||||
|       error #{code} with message:<br>\"#{message}\"") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Samantaz Fox
					Samantaz Fox