mirror of
https://github.com/cooperhammond/irs.git
synced 2025-01-02 19:15:26 +00:00
Spotify searcher is now minimum viable product.
This commit is contained in:
parent
09154058bc
commit
ddcd611585
|
@ -42,26 +42,6 @@ class SpotifySearcher
|
|||
return self
|
||||
end
|
||||
|
||||
# Searches spotify and returns track metadata in `Hash` format.
|
||||
#
|
||||
# ```
|
||||
# spotify_searcher.find_track("Bohemian Rhapsody", "Queen")
|
||||
# => hash of metadata
|
||||
# ```
|
||||
def find_track(track_name : String, artist_name : String)
|
||||
|
||||
query = "track:#{track_name.sub(" ", "+")}+" +
|
||||
"artist:#{artist_name.sub(" ", "+")}" +
|
||||
"&type=track"
|
||||
|
||||
url = @root_url.join("search?q=#{query}").to_s()
|
||||
|
||||
response = HTTP::Client.get(url, headers: @access_header)
|
||||
|
||||
puts response.body
|
||||
|
||||
end
|
||||
|
||||
# Searches spotify with the specified parameters for the specified items
|
||||
#
|
||||
# ```
|
||||
|
@ -69,14 +49,11 @@ class SpotifySearcher
|
|||
# "artist" => "Queen",
|
||||
# "track" => "Bohemian Rhapsody"
|
||||
# })
|
||||
# => {track metadata}
|
||||
# ```
|
||||
def find_item(item_type : String, item_parameters : Hash)
|
||||
query = ""
|
||||
def find_item(item_type : String, item_parameters : Hash, offset=0, limit=20)
|
||||
|
||||
item_parameters.keys.each do |i|
|
||||
query += "#{i.sub(" ", "+")}:#{item_parameters[i].sub(" ", "+")}+"
|
||||
end
|
||||
query += "&type=#{item_type}"
|
||||
query = __generate_query(item_type, item_parameters, offset, limit)
|
||||
|
||||
url = @root_url.join("search?q=#{query}").to_s()
|
||||
|
||||
|
@ -84,21 +61,125 @@ class SpotifySearcher
|
|||
|
||||
if response.status_code != 200
|
||||
puts "There was an error with your request."
|
||||
puts "Status code #{response.status_code}"
|
||||
puts "Status code: #{response.status_code}"
|
||||
puts "Reponse: \n#{response.body}"
|
||||
return nil
|
||||
end
|
||||
|
||||
items = JSON.parse(response.body)[item_type + "s"]
|
||||
items = JSON.parse(response.body)[item_type + "s"]["items"].as_a
|
||||
|
||||
points = __rank_items(items, item_parameters)
|
||||
|
||||
return items[points[0][1]]
|
||||
|
||||
end
|
||||
|
||||
# Generates url to run a GET request against
|
||||
private def __generate_query(item_type : String, item_parameters : Hash,
|
||||
offset : Int32, limit : Int32)
|
||||
query = ""
|
||||
|
||||
# parameter keys to exclude in the api request. These values will be put
|
||||
# in, just not their keys.
|
||||
query_exclude = ["username"]
|
||||
|
||||
item_parameters.keys.each do |k|
|
||||
# This will map album, playlist, and track from the name key to the query
|
||||
if k == "name"
|
||||
query += __param_encode(item_type, item_parameters[k])
|
||||
|
||||
# check if the key is to be excluded
|
||||
elsif !query_exclude.includes?(k)
|
||||
query += item_parameters[k].gsub(" ", "+") + "+"
|
||||
|
||||
# if it's none of the above, treat it normally
|
||||
else
|
||||
query += __param_encode(k, item_parameters[k])
|
||||
end
|
||||
end
|
||||
|
||||
# extra api info
|
||||
query += "&type=#{item_type}&offset=#{offset}&limit=#{limit}"
|
||||
|
||||
return query
|
||||
end
|
||||
|
||||
# Ranks the given items based off of the info from parameters.
|
||||
# Meant to find the item that the user desires.
|
||||
private def __rank_items(items : Array, parameters : Hash)
|
||||
points = [] of Array(Int32)
|
||||
index = 0
|
||||
|
||||
items.each do |item|
|
||||
pts = 0
|
||||
|
||||
# Think about whether this following logic is worth having in one method.
|
||||
# Is it nice to have a single method that handles it all or having a few
|
||||
# methods for each of the item types? (track, album, playlist)
|
||||
parameters.keys.each do |k|
|
||||
val = parameters[k]
|
||||
|
||||
# The key to compare to for artist
|
||||
if k == "artist"
|
||||
pts += __points_compare(item["artists"][0]["name"].to_s, val)
|
||||
end
|
||||
|
||||
# The key to compare to for playlists
|
||||
if k == "username"
|
||||
pts += __points_compare(item["owner"]["display_name"].to_s, val)
|
||||
end
|
||||
|
||||
# The key regardless of whether item is track, album,or playlist
|
||||
if k == "name"
|
||||
pts += __points_compare(item["name"].to_s, val)
|
||||
end
|
||||
end
|
||||
|
||||
points.push([pts, index])
|
||||
index += 1
|
||||
end
|
||||
|
||||
points.sort!{ |a, b| b[0] <=> a[0] }
|
||||
|
||||
return points
|
||||
end
|
||||
|
||||
# Returns an `Int` based off the number of points worth assigning to the
|
||||
# matchiness of the string. First the strings are downcased and then all
|
||||
# nonalphanumeric characters are stripped.
|
||||
# If the strings are the exact same, return 3 pts.
|
||||
# If *item1* includes *item2*, return 1 pt.
|
||||
# Else, return 0 pts.
|
||||
private def __points_compare(item1 : String, item2 : String)
|
||||
item1 = item1.downcase.gsub(/[^a-z0-9]/, "")
|
||||
item2 = item2.downcase.gsub(/[^a-z0-9]/, "")
|
||||
|
||||
if item1 == item2
|
||||
return 3
|
||||
elsif item1.includes?(item2)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a parameter encoded for the spotify api
|
||||
#
|
||||
# ```
|
||||
# __query_encode("album", "A Night At The Opera")
|
||||
# => "album:A+Night+At+The+Opera"
|
||||
# ```
|
||||
private def __param_encode(key : String, value : String)
|
||||
return key.gsub(" ", "+") + ":" + value.gsub(" ", "+") + "+"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
SpotifySearcher.new
|
||||
puts SpotifySearcher.new()
|
||||
.authorize("e4198f6a3f7b48029366f22528b5dc66",
|
||||
"ba057d0621a5496bbb64edccf758bde5")
|
||||
.find_item("track", {
|
||||
"artist" => "Queen",
|
||||
"track" => "Bohemian Rhapsody"
|
||||
"name" => "Bohemian Rhapsody",
|
||||
"artist" => "Queen"
|
||||
})
|
Loading…
Reference in a new issue