Changed a bunch of stuff. Almost ready for release.

- updated cli for config viewing and changes
- updated config method. an environment variable `IRS_CONFIG_LOCATION` will be set pointing to a yaml file with a config
- moved album metadata changing from a janky homebrew json modifier to the core json lib
- mapper.cr is the collection of classes for messing around with json metadata
- playlists are almost done, they still need the ability to (optionally) change the metadata of the songs downloaded in
the playlist, but they (optionally) will place all downloaded playlist songs in a single folder
- added a getter to the filename in song.cr
This commit is contained in:
Cooper Hammond 2020-05-12 22:28:03 -07:00
parent 4c20735abd
commit d1657ba86d
6 changed files with 122 additions and 19 deletions

View file

@ -17,6 +17,7 @@ class CLI
[["-h", "--help"], "help", "bool"],
[["-v", "--version"], "version", "bool"],
[["-i", "--install"], "install", "bool"],
[["-c", "--config"], "config", "bool"],
[["-a", "--artist"], "artist", "string"],
[["-s", "--song"], "song", "string"],
[["-A", "--album"], "album", "string"],
@ -44,7 +45,8 @@ class CLI
#{Style.bold "Arguments:"}
#{Style.blue "-h, --help"} Show this help message and exit
#{Style.blue "-v, --version"} Show the program version and exit
#{Style.blue "-i, --install"} Download necessary binaries to #{Style.green "~/.irs/bin"}
#{Style.blue "-i, --install"} Download binaries to config location
#{Style.blue "-c, --config"} Show config file location
#{Style.blue "-a, --artist <artist>"} Specify artist name for downloading
#{Style.blue "-s, --song <song>"} Specify song name to download
#{Style.blue "-A, --album <album>"} Specify the album name to download
@ -59,13 +61,16 @@ class CLI
#{Style.dim %(# => downloads the playlist "a different drummer" by the user prakkillian)}
#{Style.bold "This project is licensed under the MIT license."}
#{Style.bold "Project page: <github.com/cooperhammond/irs>"}
#{Style.bold "Project page: <https://github.com/cooperhammond/irs>"}
EOP
puts msg
end
def act_on_args
Config.check_necessities()
if @args["help"]? || @args.keys.size == 0
help
exit
@ -75,6 +80,9 @@ class CLI
elsif @args["install"]?
YdlBinaries.get_both(Config.binary_location)
exit
elsif @args["config"]?
puts ENV["IRS_CONFIG_LOCATION"]?
exit
elsif @args["song"]? && @args["artist"]?
s = Song.new(@args["song"], @args["artist"])
s.provide_client_keys(Config.client_key, Config.client_secret)
@ -89,6 +97,10 @@ class CLI
p = Playlist.new(@args["playlist"], @args["artist"])
p.provide_client_keys(Config.client_key, Config.client_secret)
p.grab_it()
else
puts Style.red("Those arguments don't do anything when used that way.")
puts "Type `irs -h` to see usage."
exit 1
end
end
@ -124,7 +136,7 @@ class CLI
end
# ensure there's an argument if the program needs one
if flag[2] == "string" && i + 1 > argv.size
if flag[2] == "string" && i + 1 >= argv.size
arg_error argv, i, %("#{arg}" needs an argument.)
end

View file

@ -1,22 +1,105 @@
require "yaml"
require "./styles"
EXAMPLE_CONFIG = <<-EOP
#{Style.dim "exampleconfig.yml"}
#{Style.dim "===="}
binary_directory: ~/.irs/bin
music_directory: ~/Music
client_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
client_secret: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
single_folder_playlist:
enabled: true
retain_playlist_order: true
overwrite_album: false
#{Style.dim "===="}
EOP
module Config
extend self
@@arguments = [
"binary_directory",
"music_directory",
"client_key",
"client_secret",
"single_folder_playlist: enabled",
"single_folder_playlist: retain_playlist_order",
"single_folder_playlist: overwrite_album"
]
@@conf = YAML.parse("")
begin
@@conf = YAML.parse(File.read(ENV["IRS_CONFIG_LOCATION"]))
rescue
puts Style.red "Before anything else, define the environment variable IRS_CONFIG_LOCATION pointing to a .yml file like this one."
puts EXAMPLE_CONFIG
puts Style.bold "See https://github.com/cooperhammond/irs for more information on the config file"
exit 1
end
def binary_location : String
path = "~/.irs/bin"
path = @@conf["binary_directory"].to_s
return Path[path].expand(home: true).to_s
end
def music_directory : String
path = "./Music/"
path = @@conf["music_directory"].to_s
return Path[path].expand(home: true).to_s
end
def client_key : String
return "362f75b91aeb471bb392945f93eba842"
return @@conf["client_key"].to_s
end
def client_secret : String
return "013556dd71e14e1da9443dee73e23a91"
return @@conf["client_secret"].to_s
end
def single_folder_playlist? : Bool
return @@conf["single_folder_playlist"]["enabled"].as_bool
end
def retain_playlist_order? : Bool
return @@conf["single_folder_playlist"]["retain_playlist_order"].as_bool
end
def overwrite_album? : Bool
return @@conf["single_folder_playlist"]["overwrite_album"].as_bool
end
def check_necessities
missing_configs = [] of String
@@arguments.each do |argument|
if !check_conf(argument)
missing_configs.push(argument)
end
end
if missing_configs.size > 0
puts Style.red("You are missing the following key(s) in your YAML config file:")
missing_configs.each do |config|
puts " " + config
end
puts "\nHere's an example of what your config should look like:"
puts EXAMPLE_CONFIG
puts Style.bold "See https://github.com/cooperhammond/irs for more information on the config file"
exit 1
end
end
private def check_conf(key : String) : YAML::Any?
if key.includes?(": ")
args = key.split(": ")
if @@conf[args[0]]?
return @@conf[args[0]][args[1]]?
else
return @@conf[args[0]]?
end
else
return @@conf[key]?
end
end
end

View file

@ -5,8 +5,6 @@ require "./song"
require "./list"
class Album < SpotifyList
@home_music_directory = Config.music_directory
@ -37,7 +35,7 @@ class Album < SpotifyList
}
))
prepped_data = AlbumTrackMetadataMapper.from_json(datum.to_json)
prepped_data = AlbumTracksMapper.from_json(datum.to_json)
prepped_data.album = album_metadata
data = parse_to_json(prepped_data.to_json)

View file

@ -24,7 +24,7 @@ class PlaylistTracksMapper
)
end
class AlbumTrackMetadataMapper
class AlbumTracksMapper
JSON.mapping(
album: {
type: JSON::Any,

View file

@ -3,9 +3,11 @@ require "../bottle/config"
require "./song"
require "./list"
class Playlist < SpotifyList
@home_music_directory = Config.music_directory
@playlist : JSON::Any?
# Uses the `spotify_searcher` defined in parent `SpotifyList` to find the
# correct metadata of the list
@ -14,8 +16,8 @@ class Playlist < SpotifyList
"name" => @list_name.as(String),
"username" => @list_author.as(String)
})
if playlist
return playlist.as(JSON::Any)
if @playlist
return @playlist.as(JSON::Any)
else
puts "No playlists were found by that name and user."
exit 1
@ -26,16 +28,24 @@ class Playlist < SpotifyList
# of spotify's album json. Moves the title of the album and the album art
# to the json of the single song
def organize_song_metadata(list : JSON::Any, datum : JSON::Any) : JSON::Any
puts datum
puts "THIS"
exit 0
data = datum
return data
end
private def organize(song : Song)
song.organize_it(@home_music_directory)
if Config.single_folder_playlist?
path = Path[@home_music_directory].expand(home: true)
path = path / @playlist.as(JSON::Any)["name"].to_s
.gsub(/[\/]/, "").gsub(" ", " ")
strpath = path.to_s
if !File.directory?(strpath)
FileUtils.mkdir_p(strpath)
end
safe_filename = song.filename.gsub(/[\/]/, "").gsub(" ", " ")
File.rename("./" + song.filename, (path / safe_filename).to_s)
else
song.organize_it(@home_music_directory)
end
end
end

View file

@ -11,7 +11,7 @@ class Song
@client_secret = ""
@metadata : JSON::Any?
@filename = ""
getter filename = ""
@artist = ""
@album = ""