make youtube url validation safer

This commit is contained in:
imsamuka 2022-01-02 18:04:05 -03:00
parent ac7bc02ec5
commit f962a0ab75
No known key found for this signature in database
GPG key ID: AF9ACFEF1FD372EE
2 changed files with 16 additions and 27 deletions

View file

@ -115,8 +115,9 @@ class Song
outputter("url", 1) outputter("url", 1)
else else
outputter("url", 2) outputter("url", 2)
if !Youtube.is_valid_url(url) url = Youtube.validate_url(url)
raise("The url '#{url}' is an invalid youtube URL " + if !url
raise("The url is an invalid youtube URL " +
"Check the URL and try again") "Check the URL and try again")
end end
outputter("url", 3) outputter("url", 3)

View file

@ -170,45 +170,33 @@ module Youtube
return video_metadata return video_metadata
end end
# Checks if the given URL is a valid youtube URL # Returns as a valid URL if possible
# #
# ``` # ```
# Youtube.is_valid_url("https://www.youtube.com/watch?v=NOTANACTUALVIDEOID") # Youtube.validate_url("https://www.youtube.com/watch?v=NOTANACTUALVIDEOID")
# => false # => nil
# ``` # ```
def is_valid_url(url : String) : Bool def validate_url(url : String) : String | Nil
uri = URI.parse url uri = URI.parse url
return nil if !uri
# is it a video on youtube, with a query
query = uri.query query = uri.query
return nil if !query
if !uri || !query || !uri.host || uri.path != "/watch" ||
!uri.host.not_nil!.ends_with?("youtube.com")
return false
end
queries = query.split('&')
# find the video ID # find the video ID
i = 0 vID = nil
while i < queries.size query.split('&').each do |q|
if queries[i].starts_with?("v=") if q.starts_with?("v=")
vID = queries[i][2..-1] vID = q[2..-1]
break
end end
i += 1
end
if !vID
return false
end end
return nil if !vID
url = "https://www.youtube.com/watch?v=#{vID}"
# this is an internal endpoint to validate the video ID # this is an internal endpoint to validate the video ID
response = HTTP::Client.get "https://www.youtube.com/oembed?format=json&url=#{url}" response = HTTP::Client.get "https://www.youtube.com/oembed?format=json&url=#{url}"
return response.success? return response.success? ? url : nil
end end
end end