Class: Shellify::Cli

Inherits:
Object
  • Object
show all
Includes:
Commander::Methods, Utils
Defined in:
lib/shellify/cli.rb

Instance Method Summary collapse

Methods included from Utils

#duration_to_s, #generate_oauth_url, #time_to_ms

Constructor Details

#initializeCli

Returns a new instance of Cli.



11
12
13
14
15
# File 'lib/shellify/cli.rb', line 11

def initialize
  $VERBOSE = nil # Suppress warnings from RSpotify's rest-client implementation by default
  @config = Shellify::Config.new
  @user = Shellify::User.new(@config.config_dir)
end

Instance Method Details

#runObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/shellify/cli.rb', line 17

def run
  program :name, 'Shellify'
  program :version, Shellify::VERSION
  program :description, 'Use Spotify from the command line'

  command :configure do |c|
    c.description = 'Set the Spotify client_id and client_secret'
    c.action do
      client_id = ask('Spotify Client ID: ')
      client_secret = ask('Spotify Client Secret: ') { |q| q.echo = '*' }
      @config.client_id = client_id
      @config.client_secret = client_secret
      @config.save!
    end
  end

  command :authenticate do |c|
    c.description = 'Authenticate with the Spotify API'
    c.action do
      spotify_username = ask('Your Spotify Username: ')
      puts
      puts 'Go to the link below to authorize Shellify.'
      puts generate_oauth_url
      oauth_credentials = Shellify::OauthCallbackHandler.run(@config)
      @user.id = spotify_username
      @user.token = oauth_credentials['access_token']
      @user.refresh_token = oauth_credentials['refresh_token']
      @user.save!
    end
  end

  command :devices do |c|
    c.description = 'List available playback devices'
    c.action do
      devices = @user.devices
      devices.each do |device|
        puts "  #{device.name}#{" - \e[1m𝅘𝅥𝅮\e[22m" if device.is_active}"
      end
    end
  end

  command :playing do |c|
    c.description = 'List information about the current song'
    c.action do
      return puts '  Nothing playing' unless @user.player.playing?

      print_currently_playing
    end
  end

  command :volume do |c|
    c.description = 'Set the volume of the current playback device'
    c.action do |args, _options|
      @user.player.volume(args[0])
    end
  end

  command :like do |c|
    c.description = 'Save the current song to your library'
    c.action do
      exit_with_message(local_track_message, 0) if track_is_local?(playing)
      @user.save_tracks!([playing])
    end
  end

  command :unlike do |c|
    c.description = 'Remove the current song from your library'
    c.action do
      exit_with_message(local_track_message, 0) if track_is_local?(playing)
      @user.remove_tracks!([playing])
    end
  end

  command :playlists do |c|
    c.description = 'List your playlists'
    c.action do
      @user.playlists.each do |playlist|
        puts "  #{playlist.name} - #{playlist.owner.display_name}#{' - Collaborative' if playlist.collaborative}"
      end
    end
  end

  command :add do |c|
    c.description = 'Add the current song or album to the provided playlist'
    c.option '-a', '--album'
    c.action do |args, options|
      return puts '  Nothing playing' unless @user.player.playing?

      exit_with_message(local_track_message, 0) if track_is_local?(playing)
      playlist = @user.playlists.find { |p| p.name == args[0] }
      return puts '  Playlist not found' unless playlist

      exit_with_message(add_to_collaborative_playlist_message, 0) if playlist.owner.id != @user.id

      item = options.album ? playing.album.tracks : [playing]
      playlist.add_tracks!(item)
    end
  end

  command :queue do |c|
    c.description = 'List the next songs in the queue'
    c.action do
      items = @user.player.next_up
      exit_with_message('  Nothing in the queue', 0) if items.empty?
      items.each.with_index(1) do |item, i|
        case item.type
        when 'episode'
          puts "  #{i.to_s.rjust(items.size.to_s.size, ' ')} - #{item.name} - #{item.show.name}"
        when 'track'
          puts "  #{i.to_s.rjust(items.size.to_s.size, ' ')} - #{item.name} - "\
               "#{item.artists.map(&:name).join(', ')}"
        end
      end
    end
  end

  command :remove do |c|
    c.description = 'Remove the currently playing song or album from the provided playlist'
    c.option '-a', '--album'
    c.action do |args, options|
      return puts '  Nothing playing' unless @user.player.playing?

      exit_with_message(local_track_message, 0) if track_is_local?(playing)
      playlist = @user.playlists.find { |p| p.name == args[0] }
      return puts '  Playlist not found' unless playlist

      exit_with_message(add_to_collaborative_playlist_message, 0) if playlist.owner.id != @user.id

      item = options.album ? playing.album.tracks : [playing]
      playlist.remove_tracks!(item)
    end
  end

  command :play do |c|
    c.description = 'Play or Pause on the currently playing device'
    c.action do
      if @user.player.playing?
        @user.player.pause
      else
        @user.player.play
        print_currently_playing
      end
    rescue RestClient::NotFound
      @user.player.play(@user.devices.first.id)
    end
  end

  command :next do |c|
    c.description = 'Skip to the next song in the queue'
    c.action do
      @user.player.next
      print_currently_playing
    end
  end

  command :previous do |c|
    c.description = 'Skip the the previous song in the queue'
    c.action do
      @user.player.previous
      print_currently_playing
    end
  end

  command :restart do |c|
    c.description = 'Restart the currently playing song'
    c.action do
      @user.player.seek 0
      print_currently_playing
    end
  end

  command :seek do |c|
    c.description = 'Seek to the specified time in the current song'
    c.action do |args, _option|
      @user.player.seek(time_to_ms(args[0]))
      print_currently_playing
    end
  end

  default_command :playing
  alias_command :pause, :play
  alias_command :back, :previous
  alias_command :skip, :next

  run!
end