need to add 'next' feature for spotify searches

This commit is contained in:
Cooper Hammond 2019-06-23 13:39:00 -07:00
parent 8cfb59a368
commit f849e61045
6 changed files with 122 additions and 24 deletions

25
src/glue/album.cr Normal file
View file

@ -0,0 +1,25 @@
require "./song"
require "./list"
class Album < SpotifyList
def find_it
album = @spotify_searcher.find_item("album", {
"name" => @list_name.as(String),
"artist" => @list_author.as(String)
})
if album
return album.as(JSON::Any)
else
puts "No album was found by that name and artist."
exit 1
end
end
private def set_organization(index : Int32, song : Song)
# pass
end
end
puts Album.new("A Night At The Opera", "Queen").find_it()

45
src/glue/list.cr Normal file
View file

@ -0,0 +1,45 @@
require "../search/spotify"
require "../search/youtube"
require "../interact/ripper"
require "../interact/tagger"
require "./song"
# A parent class for downloading albums and playlists from spotify
abstract class SpotifyList
@spotify_searcher = SpotifySearcher.new()
@file_names = [] of String
def initialize(@list_name : String, @list_author : String?)
@spotify_searcher.authorize(
"e4198f6a3f7b48029366f22528b5dc66",
"ba057d0621a5496bbb64edccf758bde5")
end
# Finds the list, and downloads all of the songs using the `Song` class
def grab_it
list = find_it()
contents = list["tracks"][0]["items"]
i = 0
contents.each do |data|
if song["track"]?
data = data["track"]
end
song = Song.new(data["name"].to_s, data["artists"][0]["name"].to_s)
song.provide_spotify(@spotify_searcher)
set_organization(i , song)
song.grab_it()
i += 1
end
end
abstract def find_it : JSON::Any
private abstract def set_organization(song_index : Int32, song : Song)
end

View file

@ -4,6 +4,10 @@ class Logger
@command : String @command : String
# *command* is the bash command that you want to run and capture the output
# of. *@log_name* is the name of the log file you want to temporarily create.
# *@sleept* is the time you want to wait before rechecking if the command has
# started yet, probably something you don't want to worry about
def initialize(command : String, @log_name : String, @sleept = 0.01) def initialize(command : String, @log_name : String, @sleept = 0.01)
# Have the command output its information to a log and after the command is # Have the command output its information to a log and after the command is
# finished, append an end signal to the document # finished, append an end signal to the document

View file

@ -19,8 +19,6 @@ module Ripper
# remove the extension that will be added on by ydl # remove the extension that will be added on by ydl
output_filename = output_filename.split(".")[..-2].join(".") output_filename = output_filename.split(".")[..-2].join(".")
# TODO: update the logger for this. Explore overwriting stdout and
# injecting/removing text
options = { options = {
"--output" => %("#{output_filename}.%(ext)s"), # auto-add correct ext "--output" => %("#{output_filename}.%(ext)s"), # auto-add correct ext
# "--quiet" => "", # "--quiet" => "",

View file

@ -1,11 +1,17 @@
# TODO: write comments/documentation # Uses FFMPEG binary to add metadata to mp3 files
# ```
# t = Tags.new("bohem rap.mp3")
# t.add_album_art("a night at the opera album cover.jpg")
# t.add_text_tag("title", "Bohemian Rhapsody")
# t.save()
# ```
class Tags class Tags
# TODO: export this path to a config file
@BIN_LOC = Path["~/.irs/bin".sub("~", Path.home)] @BIN_LOC = Path["~/.irs/bin".sub("~", Path.home)]
@query_args = [] of String @query_args = [] of String
# initialize the class with an already created MP3
def initialize(@filename : String) def initialize(@filename : String)
if !File.exists?(@filename) if !File.exists?(@filename)
raise "MP3 not found at location: #{@filename}" raise "MP3 not found at location: #{@filename}"
@ -15,10 +21,8 @@ class Tags
end end
def add_text_tag(key : String, value : String) : Nil # Add album art to the mp3. Album art must be added BEFORE text tags are.
@query_args.push(%(-metadata #{key}="#{value}")) # Check the usage above to see a working example.
end
def add_album_art(image_location : String) : Nil def add_album_art(image_location : String) : Nil
if !File.exists?(image_location) if !File.exists?(image_location)
raise "Image file not found at location: #{image_location}" raise "Image file not found at location: #{image_location}"
@ -33,6 +37,13 @@ class Tags
@query_args.push(%(-metadata:s:v title="Album cover")) @query_args.push(%(-metadata:s:v title="Album cover"))
end end
# Add a text tag to the mp3. If you want to see what text tags are supported,
# check out: https://wiki.multimedia.cx/index.php?title=FFmpeg_Metadata
def add_text_tag(key : String, value : String) : Nil
@query_args.push(%(-metadata #{key}="#{value}"))
end
# Run the necessary commands to attach album art to the mp3
def save : Nil def save : Nil
@query_args.push(%("_#{@filename}")) @query_args.push(%("_#{@filename}"))
command = @BIN_LOC.to_s + "/ffmpeg " + @query_args.join(" ") command = @BIN_LOC.to_s + "/ffmpeg " + @query_args.join(" ")

View file

@ -69,24 +69,34 @@ class SpotifySearcher
points = rank_items(items, item_parameters) points = rank_items(items, item_parameters)
begin begin
return items[points[0][1]] return get_item(item_type, items[points[0][1]]["id"].to_s)
rescue IndexError rescue IndexError
return nil return nil
end end
end end
# Get the complete metadata of an item based off of its id
#
# ```
# SpotifySearcher.new().authorize(...).get_item("artist", "1dfeR4HaWDbWqFHLkxsg1d")
# ```
def get_item(item_type : String, id : String) : JSON::Any?
url = @root_url.join("#{item_type}s/#{id}").to_s()
response = HTTP::Client.get(url, headers: @access_header)
error_check(response)
return JSON.parse(response.body)
end
# Find the genre of an artist based off of their id # Find the genre of an artist based off of their id
# #
# ``` # ```
# SpotifySearcher.new().authorize(...).find_genre("1dfeR4HaWDbWqFHLkxsg1d") # SpotifySearcher.new().authorize(...).find_genre("1dfeR4HaWDbWqFHLkxsg1d")
# ``` # ```
def find_genre(id : String) : String def find_genre(id : String) : String
url = @root_url.join("artists/#{id}").to_s()
response = HTTP::Client.get(url, headers: @access_header) genre = get_item("artist", id)["genres"][0].to_s
error_check(response)
genre = JSON.parse(response.body)["genres"][0].to_s
genre = genre.split(" ").map { |x| x.capitalize }.join(" ") genre = genre.split(" ").map { |x| x.capitalize }.join(" ")
return genre return genre
@ -117,8 +127,9 @@ class SpotifySearcher
query += param_encode(item_type, item_parameters[k]) query += param_encode(item_type, item_parameters[k])
# check if the key is to be excluded # check if the key is to be excluded
elsif !query_exclude.includes?(k) elsif query_exclude.includes?(k)
query += item_parameters[k].gsub(" ", "+") + "+" next
# query += item_parameters[k].gsub(" ", "+") + "+"
# if it's none of the above, treat it normally # if it's none of the above, treat it normally
else else
@ -206,10 +217,14 @@ class SpotifySearcher
end end
# puts SpotifySearcher.new() puts SpotifySearcher.new()
# .authorize("e4198f6a3f7b48029366f22528b5dc66", .authorize("e4198f6a3f7b48029366f22528b5dc66",
# "ba057d0621a5496bbb64edccf758bde5") "ba057d0621a5496bbb64edccf758bde5")
# .find_item("album", { .find_item("playlist", {
"name" => "Brain Food",
"username" => "spotify"
# "name " => "A Night At The Opera", # "name " => "A Night At The Opera",
# "artist" => "Queen" # "artist" => "Queen"
# }) # "track" => "Bohemian Rhapsody",
# "artist" => "Queen"
})