class Drum::CLI
The command line interface for drum.
Public Class Methods
# File lib/drum.rb, line 48 def self.exit_on_failure? true end
Sets up the CLI
by registering the services.
# File lib/drum.rb, line 23 def initialize(*args) super @hl = HighLine.new # Set up .drum directory @dot_dir = Pathname.new(Dir.home) / '.drum' @dot_dir.mkdir unless @dot_dir.directory? @cache_dir = @dot_dir / 'cache' @cache_dir.mkdir unless @cache_dir.directory? # Declare services in descending order of parse priority @services = [ MockService.new, StdioService.new, AppleMusicService.new(@cache_dir), SpotifyService.new(@cache_dir), # The file service should be last since it may # successfully parse refs that overlap with other # services. FileService.new ].map { |s| [s.name, s] }.to_h end
Public Instance Methods
Prints the version.
@return [void]
# File lib/drum.rb, line 246 def __print_version log.all VERSION end
Prompts the user for confirmation.
@param [String] prompt The message to be displayed
# File lib/drum.rb, line 86 def confirm(prompt) answer = @hl.ask "#{prompt} [y/n]" unless answer == 'y' log.info 'Okay, exiting.' exit end end
Copies a playlist from the source to the given destination.
@param [String] raw_src_ref The source playlist ref. @param [String] raw_dest_ref The destination playlist ref. @return [void]
# File lib/drum.rb, line 146 def cp(raw_src_ref, raw_dest_ref) src_ref = self.parse_ref(raw_src_ref) dest_ref = self.parse_ref(raw_dest_ref) if src_ref.nil? raise "Could not parse src ref: #{raw_src_ref}" end if dest_ref.nil? raise "Could not parse dest ref: #{raw_dest_ref}" end self.with_service(src_ref.service_name) do |src_name, src_service| self.with_service(dest_ref.service_name) do |dest_name, dest_service| log.info "Copying from #{src_name} to #{dest_name}..." # TODO: Should we handle merging at all or just copy (as currently done)? playlists = src_service.download(src_ref).lazy unless playlists.size.nil? bar = ProgressBar.new(playlists.size) # Redirect log output so the bar stays at the bottom log.output = bar.method(:puts) end # Apply transformations to the downloaded playlists. # Note that we use 'map' despite mutating the playlists # in-place to preserve laziness in the iteration. playlists = playlists.map do |playlist| bar&.increment! if options[:group_by_author] author_name = playlist.author_id.try { |id| playlist.users[id] }&.display_name || 'Other' playlist.path.unshift(author_name) end if options[:recase_paths] casing = options[:recase_paths] playlist.path.map! do |n| case casing when 'kebabcase' then n.kebabcase when 'startcase' then n.startcase when 'camelcase' then n.camelcase when 'pascalcase' then n.pascalcase else raise "Casing '#{casing}' is not implemented (yet)!" end end end if options[:note_date] unless playlist.description.end_with?("\n") || playlist.description.empty? playlist.description += "\n" end playlist.description += Time.now.strftime("Pushed with Drum on %Y-%m-%d") end playlist end dest_service.upload(dest_ref, playlists) end end end
Parses a ref using the registered services.
@param [String] raw The raw ref to parse @return [optional, Ref] The ref, if parsed successfully with any of the services
# File lib/drum.rb, line 72 def parse_ref(raw) raw_ref = RawRef.parse(raw) @services.each_value do |service| ref = service.parse_ref(raw_ref) unless ref.nil? return ref end end return nil end
Removes a playlist from the corresponding service.
@param [String] raw_ref The playlist ref. @return [void]
# File lib/drum.rb, line 218 def rm(raw_ref) ref = self.parse_ref(raw_ref) if ref.nil? raise "Could not parse ref: #{raw_ref}" end self.with_service(ref.service_name) do |name, service| log.info "Removing from #{name}..." service.remove(ref) end end
Lists available services.
@return [void]
# File lib/drum.rb, line 236 def services log.info @services.each_key.to_a.join("\n") end
Previews a playlist in a simplified format.
@param [String] raw_ref The (raw) playlist ref.
# File lib/drum.rb, line 100 def show(raw_ref) ref = self.parse_ref(raw_ref) if ref.nil? raise "Could not parse ref: #{raw_ref}" end self.with_service(ref.service_name) do |name, service| playlists = service.download(ref) playlists.each do |playlist| log.all({ 'name' => playlist.name, 'description' => playlist&.description, 'tracks' => playlist.tracks.each_with_index.map do |track, i| artists = (track.artist_ids&.filter_map { |id| playlist.artists[id]&.name } || []).join(', ') "#{i + 1}. #{artists} - #{track.name}" end }.compact.to_yaml) end end end
Performs a block with the given service, if registered.
@yield [name, service] The block to run @yieldparam [String] name The name of the service @yieldparam [Service] service The service @param [String] raw_name The name of the service
# File lib/drum.rb, line 59 def with_service(raw_name) name = raw_name.downcase service = @services[name] if service.nil? raise "Sorry, #{name} is not a valid service! Try one of these: #{@services.keys}" end yield(name, service) end