From 5f8acac053cac13ae4928e6ae7596b0fdb24ecba Mon Sep 17 00:00:00 2001 From: Cooper Hammond Date: Thu, 21 May 2020 19:23:44 -0700 Subject: [PATCH] feature: CLI download messages have been updated to be prettier --- src/bottle/styles.cr | 10 ++++---- src/glue/list.cr | 18 ++++++++++++++ src/glue/song.cr | 56 ++++++++++++++++++++++++++++++++++++------ src/interact/ripper.cr | 5 ++-- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/bottle/styles.cr b/src/bottle/styles.cr index a79928d..f965378 100755 --- a/src/bottle/styles.cr +++ b/src/bottle/styles.cr @@ -2,22 +2,22 @@ require "colorize" class Style def self.bold(txt) - txt.colorize.mode(:bold) + txt.colorize.mode(:bold).to_s end def self.dim(txt) - txt.colorize.mode(:dim) + txt.colorize.mode(:dim).to_s end def self.blue(txt) - txt.colorize(:light_blue) + txt.colorize(:light_blue).to_s end def self.green(txt) - txt.colorize(:light_green) + txt.colorize(:light_green).to_s end def self.red(txt) - txt.colorize(:light_red) + txt.colorize(:light_red).to_s end end diff --git a/src/glue/list.cr b/src/glue/list.cr index 7a233f5..4d4d583 100755 --- a/src/glue/list.cr +++ b/src/glue/list.cr @@ -13,6 +13,13 @@ abstract class SpotifyList @spotify_searcher = SpotifySearcher.new @file_names = [] of String + @outputs : Hash(String, Array(String)) = { + "searching" => [ + Style.bold("Searching for %l by %a ... \r"), + Style.green("+ ") + Style.bold("%l by %a \n") + ] + } + def initialize(@list_name : String, @list_author : String?) end @@ -22,7 +29,9 @@ abstract class SpotifyList raise("Need to call provide_client_keys on Album or Playlist class.") end + outputter("searching", 0) list = find_it() + outputter("searching", 1) contents = list["tracks"]["items"].as_a i = 0 @@ -36,6 +45,8 @@ abstract class SpotifyList song = Song.new(data["name"].to_s, data["artists"][0]["name"].to_s) song.provide_spotify(@spotify_searcher) song.provide_metadata(data) + + puts Style.bold("[#{data["track_number"]}/#{contents.size}]") song.grab_it organize(song) @@ -49,6 +60,13 @@ abstract class SpotifyList @spotify_searcher.authorize(client_key, client_secret) end + private def outputter(key : String, index : Int32) + text = @outputs[key][index] + .gsub("%l", @list_name) + .gsub("%a", @list_author) + print text + end + # Defined in subclasses, will return the appropriate information or call an # error if the info is not found and exit abstract def find_it : JSON::Any diff --git a/src/glue/song.cr b/src/glue/song.cr index 964e370..e512ba9 100755 --- a/src/glue/song.cr +++ b/src/glue/song.cr @@ -4,6 +4,8 @@ require "../search/youtube" require "../interact/ripper" require "../interact/tagger" +require "../bottle/styles" + class Song @spotify_searcher = SpotifySearcher.new @client_id = "" @@ -14,6 +16,33 @@ class Song @artist = "" @album = "" + @outputs : Hash(String, Array(String)) = { + "intro" => [Style.bold("[%s by %a]\n")], + "metadata" => [ + " Searching for metadata ...\r", + Style.green(" + ") + Style.dim("Metadata found \n") + ], + "url" => [ + " Searching for URL ...\r", + Style.green(" + ") + Style.dim("URL found \n") + ], + "download" => [ + " Downloading video:\n", + Style.green("\r + ") + Style.dim("Converted to mp3 \n") + ], + "albumart" => [ + " Downloading album art ...\r", + Style.green(" + ") + Style.dim("Album art downloaded \n") + ], + "tagging" => [ + " Attaching metadata ...\r", + Style.green(" + ") + Style.dim("Metadata attached \n") + ], + "finished" => [ + Style.green(" + ") + "Finished!\n" + ] + } + def initialize(@song_name : String, @artist_name : String) end @@ -23,6 +52,8 @@ class Song # Song.new("Bohemian Rhapsody", "Queen").grab_it # ``` def grab_it + outputter("intro", 0) + if !@spotify_searcher.authorized? && !@metadata if @client_id != "" && @client_secret != "" @spotify_searcher.authorize(@client_id, @client_secret) @@ -33,7 +64,7 @@ class Song end if !@metadata - puts "Searching for metadata ..." + outputter("metadata", 0) @metadata = @spotify_searcher.find_item("track", { "name" => @song_name, "artist" => @artist_name, @@ -44,28 +75,31 @@ class Song %("#{@song_name}" by "#{@artist_name}". ) + "Check your input and try again.") end + outputter("metadata", 1) end data = @metadata.as(JSON::Any) @filename = data["track_number"].to_s + " - #{data["name"].to_s}.mp3" - puts "Searching for url ..." - # TODO: should this search_term be here? + outputter("url", 0) url = Youtube.find_url(@song_name, @artist_name, search_terms: "lyrics") - if !url raise("There was no url found on youtube for " + %("#{@song_name}" by "#{@artist_name}. ) + "Check your input and try again.") end + outputter("url", 1) - puts "Downloading video:" + outputter("download", 0) Ripper.download_mp3(url.as(String), @filename) + outputter("download", 1) + outputter("albumart", 0) temp_albumart_filename = ".tempalbumart.jpg" HTTP::Client.get(data["album"]["images"][0]["url"].to_s) do |response| File.write(temp_albumart_filename, response.body_io) end + outputter("albumart", 0) # check if song's metadata has been modded in playlist, update artist accordingly if data["artists"][-1]["owner"]? @@ -85,11 +119,12 @@ class Song tagger.add_text_tag("track", data["track_number"].to_s) tagger.add_text_tag("disc", data["disc_number"].to_s) - puts "Tagging metadata ..." + outputter("tagging", 0) tagger.save File.delete(temp_albumart_filename) + outputter("tagging", 1) - puts %("#{data["name"].to_s}" by "#{data["artists"][0]["name"].to_s}" downloaded.) + outputter("finished", 0) end # Will organize the song into the user's provided music directory as @@ -150,4 +185,11 @@ class Song @client_secret = client_secret return self end + + private def outputter(key : String, index : Int32) + text = @outputs[key][index] + .gsub("%s", @song_name) + .gsub("%a", @artist_name) + print text + end end diff --git a/src/interact/ripper.cr b/src/interact/ripper.cr index 35e84e0..5a5aa38 100755 --- a/src/interact/ripper.cr +++ b/src/interact/ripper.cr @@ -1,5 +1,6 @@ require "./logger" require "../bottle/config" +require "../bottle/styles" module Ripper extend self @@ -54,11 +55,11 @@ module Ripper print "\e[1A" print "\e[0K\r" end - puts line.sub("[download]", " ") + puts line.sub("[download]", " ") @dl_status_index += 1 if line.includes? "100%" - puts "Converting to mp3 ..." + print " Converting to mp3 ..." end end end