From d1657ba86da9c492096ae71c40984a7258c7d55f Mon Sep 17 00:00:00 2001 From: Cooper Hammond Date: Tue, 12 May 2020 22:28:03 -0700 Subject: [PATCH] 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 --- src/bottle/cli.cr | 18 +++++++-- src/bottle/config.cr | 91 ++++++++++++++++++++++++++++++++++++++++++-- src/glue/album.cr | 4 +- src/glue/mapper.cr | 2 +- src/glue/playlist.cr | 24 ++++++++---- src/glue/song.cr | 2 +- 6 files changed, 122 insertions(+), 19 deletions(-) diff --git a/src/bottle/cli.cr b/src/bottle/cli.cr index 13affa8..d95b7c0 100755 --- a/src/bottle/cli.cr +++ b/src/bottle/cli.cr @@ -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 "} Specify artist name for downloading #{Style.blue "-s, --song "} Specify song name to download #{Style.blue "-A, --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: "} + #{Style.bold "Project page: "} 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 diff --git a/src/bottle/config.cr b/src/bottle/config.cr index c288b5d..866f46f 100755 --- a/src/bottle/config.cr +++ b/src/bottle/config.cr @@ -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 \ No newline at end of file diff --git a/src/glue/album.cr b/src/glue/album.cr index e6f0781..e7281b0 100755 --- a/src/glue/album.cr +++ b/src/glue/album.cr @@ -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) diff --git a/src/glue/mapper.cr b/src/glue/mapper.cr index c423662..ab4cc71 100755 --- a/src/glue/mapper.cr +++ b/src/glue/mapper.cr @@ -24,7 +24,7 @@ class PlaylistTracksMapper ) end -class AlbumTrackMetadataMapper +class AlbumTracksMapper JSON.mapping( album: { type: JSON::Any, diff --git a/src/glue/playlist.cr b/src/glue/playlist.cr index 0600b3e..2ec048d 100755 --- a/src/glue/playlist.cr +++ b/src/glue/playlist.cr @@ -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 diff --git a/src/glue/song.cr b/src/glue/song.cr index 0e59155..23f9f98 100755 --- a/src/glue/song.cr +++ b/src/glue/song.cr @@ -11,7 +11,7 @@ class Song @client_secret = "" @metadata : JSON::Any? - @filename = "" + getter filename = "" @artist = "" @album = ""