shellify 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c748de7e87dfdb2e9567cac439dc39d3f5db091658150abebfe0e1ac3ce23ab7
4
- data.tar.gz: 568c613808ae76d1ef896cf6b5c66bb6e46d87e9a1df0a44ff0dc4e569f4fc4c
3
+ metadata.gz: f62fa09eb7f90e2bc486320a18dc252ffb8a751a6d67e72ce3fb5a149e1965ef
4
+ data.tar.gz: b9cb6abde7095e6b5f2e358e6962897dbb797b3e90823bfb8c3422b1bacf7766
5
5
  SHA512:
6
- metadata.gz: e271d469bb73af4ab35d10e405ea03f68d62014e4ed5bcc4fc715dee83683013ecc9e9187233d5876b73c23f672a8992625ee22f919c026fc7e48cda1a4936e5
7
- data.tar.gz: a80d854ea294d1646136bbd92dbcd2b34bafb4fbd78d11a1e97d415d6fab0d7fb97a6388a375d0a2fca250d41f00bc64d6b84ee2d99a7bdae0f29b2a87b7108a
6
+ metadata.gz: cd101fc048837d34a1db93c0c36c8ebb3270ea2779628f154309d58837f4d0666ba673b53c954d4b6ca06ee7efdf30fa214f8e561c70a391d1dfc35dba0926fc
7
+ data.tar.gz: c2fa18b6cebc2eff9ca4406576ba24efb98d77fbfd015ee9d1312b84ac98a4dd7ce0ce0d18f6dd7cf458f8ee32d92514a23734b3ec618d84bc2de83a9533ab9d
data/lib/shellify/cli.rb CHANGED
@@ -22,8 +22,8 @@ module Shellify
22
22
  command :configure do |c|
23
23
  c.description = 'Set the Spotify client_id and client_secret'
24
24
  c.action do
25
- client_id = ask("Spotify Client ID: ")
26
- client_secret = ask("Spotify Client Secret: ") { |q| q.echo = '*' }
25
+ client_id = ask('Spotify Client ID: ')
26
+ client_secret = ask('Spotify Client Secret: ') { |q| q.echo = '*' }
27
27
  @config.client_id = client_id
28
28
  @config.client_secret = client_secret
29
29
  @config.save!
@@ -58,15 +58,15 @@ module Shellify
58
58
  command :playing do |c|
59
59
  c.description = 'List information about the current song'
60
60
  c.action do
61
- return puts " Nothing playing" unless @user.player.playing?
61
+ return puts ' Nothing playing' unless @user.player.playing?
62
62
 
63
- print_current_song
63
+ print_currently_playing
64
64
  end
65
65
  end
66
66
 
67
67
  command :volume do |c|
68
68
  c.description = 'Set the volume of the current playback device'
69
- c.action do |args, options|
69
+ c.action do |args, _options|
70
70
  @user.player.volume(args[0])
71
71
  end
72
72
  end
@@ -91,50 +91,73 @@ module Shellify
91
91
  c.description = 'List your playlists'
92
92
  c.action do
93
93
  @user.playlists.each do |playlist|
94
- puts " #{playlist.name} - #{playlist.owner.display_name}#{" - Collaborative" if playlist.collaborative}"
94
+ puts " #{playlist.name} - #{playlist.owner.display_name}#{' - Collaborative' if playlist.collaborative}"
95
95
  end
96
96
  end
97
97
  end
98
98
 
99
99
  command :add do |c|
100
- c.description = 'Add the current song to the provided playlist'
100
+ c.description = 'Add the current song or album to the provided playlist'
101
+ c.option '-a', '--album'
101
102
  c.action do |args, options|
102
- return puts " Nothing playing" unless @user.player.playing?
103
+ return puts ' Nothing playing' unless @user.player.playing?
103
104
 
104
105
  exit_with_message(local_track_message, 0) if track_is_local?(playing)
105
106
  playlist = @user.playlists.find { |p| p.name == args[0] }
106
- return puts " Playlist not found" unless playlist
107
+ return puts ' Playlist not found' unless playlist
108
+
109
+ exit_with_message(add_to_collaborative_playlist_message, 0) if playlist.owner.id != @user.id
107
110
 
108
- playlist.add_tracks!([playing])
111
+ item = options.album ? playing.album.tracks : [playing]
112
+ playlist.add_tracks!(item)
113
+ end
114
+ end
115
+
116
+ command :queue do |c|
117
+ c.description = 'List the next songs in the queue'
118
+ c.action do
119
+ items = @user.player.next_up
120
+ exit_with_message(' Nothing in the queue', 0) if items.empty?
121
+ items.each.with_index(1) do |item, i|
122
+ case item.type
123
+ when 'episode'
124
+ puts " #{i.to_s.rjust(items.size.to_s.size, ' ')} - #{item.name} - #{item.show.name}"
125
+ when 'track'
126
+ puts " #{i.to_s.rjust(items.size.to_s.size, ' ')} - #{item.name} - "\
127
+ "#{item.artists.map(&:name).join(', ')}"
128
+ end
129
+ end
109
130
  end
110
131
  end
111
132
 
112
133
  command :remove do |c|
113
- c.description = 'Remove the currently playing song from the provided playlist'
134
+ c.description = 'Remove the currently playing song or album from the provided playlist'
135
+ c.option '-a', '--album'
114
136
  c.action do |args, options|
115
- return puts " Nothing playing" unless @user.player.playing?
137
+ return puts ' Nothing playing' unless @user.player.playing?
116
138
 
117
139
  exit_with_message(local_track_message, 0) if track_is_local?(playing)
118
140
  playlist = @user.playlists.find { |p| p.name == args[0] }
119
- return puts " Playlist not found" unless playlist
141
+ return puts ' Playlist not found' unless playlist
142
+
143
+ exit_with_message(add_to_collaborative_playlist_message, 0) if playlist.owner.id != @user.id
120
144
 
121
- playlist.remove_tracks!([playing])
145
+ item = options.album ? playing.album.tracks : [playing]
146
+ playlist.remove_tracks!(item)
122
147
  end
123
148
  end
124
149
 
125
150
  command :play do |c|
126
151
  c.description = 'Play or Pause on the currently playing device'
127
152
  c.action do
128
- begin
129
- if @user.player.playing?
130
- @user.player.pause
131
- else
132
- @user.player.play
133
- print_current_song
134
- end
135
- rescue RestClient::NotFound
136
- @user.player.play(@user.devices.first.id)
153
+ if @user.player.playing?
154
+ @user.player.pause
155
+ else
156
+ @user.player.play
157
+ print_currently_playing
137
158
  end
159
+ rescue RestClient::NotFound
160
+ @user.player.play(@user.devices.first.id)
138
161
  end
139
162
  end
140
163
 
@@ -142,7 +165,7 @@ module Shellify
142
165
  c.description = 'Skip to the next song in the queue'
143
166
  c.action do
144
167
  @user.player.next
145
- print_current_song
168
+ print_currently_playing
146
169
  end
147
170
  end
148
171
 
@@ -150,7 +173,7 @@ module Shellify
150
173
  c.description = 'Skip the the previous song in the queue'
151
174
  c.action do
152
175
  @user.player.previous
153
- print_current_song
176
+ print_currently_playing
154
177
  end
155
178
  end
156
179
 
@@ -158,15 +181,15 @@ module Shellify
158
181
  c.description = 'Restart the currently playing song'
159
182
  c.action do
160
183
  @user.player.seek 0
161
- print_current_song
184
+ print_currently_playing
162
185
  end
163
186
  end
164
187
 
165
188
  command :seek do |c|
166
189
  c.description = 'Seek to the specified time in the current song'
167
- c.action do |args, option|
190
+ c.action do |args, _option|
168
191
  @user.player.seek(time_to_ms(args[0]))
169
- print_current_song
192
+ print_currently_playing
170
193
  end
171
194
  end
172
195
 
@@ -188,17 +211,29 @@ module Shellify
188
211
  " Shellify can't perform this action for local tracks"
189
212
  end
190
213
 
214
+ def add_to_collaborative_playlist_message
215
+ " Shellify can't perform this action for collaborative playlists you don't own"
216
+ end
217
+
191
218
  def track_is_local?(track)
192
219
  track.uri.split(':')[1] == 'local'
193
220
  end
194
221
 
195
- def print_current_song
196
- puts ' Now Playing:'
197
- puts " #{playing.name} - #{playing.artists.first.name} - "\
198
- "#{duration_to_s(@user.player.progress)}/#{duration_to_s(playing.duration_ms)}"\
199
- "#{" - ♥" if !track_is_local?(playing) && @user.saved_tracks?([playing]).first}"\
200
- "#{" - local" if track_is_local?(playing)}"
222
+ def current_song
223
+ puts "Now Playing - #{duration_to_s(@user.player.progress)}/#{duration_to_s(playing.duration_ms)}"\
224
+ "#{' - ♥' if !track_is_local?(playing) && @user.saved_tracks?([playing]).first}"\
225
+ "#{' - local' if track_is_local?(playing)}\n"\
226
+ " #{playing.name}\n"\
227
+ " #{playing.album.name}\n"\
228
+ " #{playing.artists.map(&:name).join(', ')}"
229
+ end
201
230
 
231
+ def print_currently_playing
232
+ if playing.nil?
233
+ puts "Now Playing - Podcast - #{duration_to_s(@user.player.progress)}"
234
+ else
235
+ current_song
236
+ end
202
237
  end
203
238
 
204
239
  def exit_with_message(message, code = 1)
@@ -4,8 +4,8 @@ module Shellify
4
4
  class Config
5
5
  attr_accessor :client_id, :client_secret, :config_dir
6
6
 
7
- CONFIG_DIR = ENV['HOME'] + '/.config/shellify'
8
- CONFIG_FILE = CONFIG_DIR + '/config.json'
7
+ CONFIG_DIR = "#{ENV['HOME']}/.config/shellify"
8
+ CONFIG_FILE = "#{CONFIG_DIR}/config.json"
9
9
  SPOTIFY_AUTHORIZATION_SCOPES = %w[
10
10
  user-read-playback-state
11
11
  user-modify-playback-state
@@ -31,16 +31,16 @@ module Shellify
31
31
 
32
32
  def save!
33
33
  File.open(CONFIG_FILE, 'w') do |file|
34
- file.write(JSON.pretty_generate({client_id: @client_id, client_secret: @client_secret}))
34
+ file.write(JSON.pretty_generate({ client_id: @client_id, client_secret: @client_secret }))
35
35
  end
36
36
  end
37
37
 
38
38
  private
39
39
 
40
40
  def load_config
41
- return unless File.exists?(CONFIG_FILE)
41
+ return unless File.exist?(CONFIG_FILE)
42
42
 
43
- JSON.parse(File.read(CONFIG_FILE)).each_pair { |k,v| instance_variable_set("@#{k}", v) }
43
+ JSON.parse(File.read(CONFIG_FILE)).each_pair { |k, v| instance_variable_set("@#{k}", v) }
44
44
  end
45
45
  end
46
46
  end
@@ -25,7 +25,7 @@ module Shellify
25
25
  begin
26
26
  tokens = fetch_tokens(params['code'])
27
27
  rescue RestClient::Exception => e
28
- body = "Spotify didn't like that\n" + e.response
28
+ body = "Spotify didn't like that\n#{e.response}"
29
29
  end
30
30
 
31
31
  @client.puts headers(body.length)
@@ -41,7 +41,7 @@ module Shellify
41
41
  def headers(content_length)
42
42
  [
43
43
  'HTTP/1.1 200 Ok',
44
- "date: #{Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")}",
44
+ "date: #{Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')}",
45
45
  'server: ruby',
46
46
  "Content-Length: #{content_length}",
47
47
  '',
@@ -51,7 +51,7 @@ module Shellify
51
51
 
52
52
  def fetch_tokens(code)
53
53
  headers = {
54
- 'Authorization': "Basic " + Base64.strict_encode64("#{@config.client_id}:#{@config.client_secret}"),
54
+ 'Authorization': 'Basic ' + Base64.strict_encode64("#{@config.client_id}:#{@config.client_secret}"),
55
55
  }
56
56
 
57
57
  params = {
@@ -62,7 +62,7 @@ module Shellify
62
62
  code: code,
63
63
  }
64
64
 
65
- JSON.parse(RestClient.post("https://accounts.spotify.com/api/token", params, headers))
65
+ JSON.parse(RestClient.post('https://accounts.spotify.com/api/token', params, headers))
66
66
  end
67
67
  end
68
68
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpotify
4
+ class Player
5
+ def next_up
6
+ url = 'me/player/queue'
7
+ response = User.oauth_get(@user.id, url)
8
+ return response if RSpotify.raw_response
9
+
10
+ response['queue'].map do |item|
11
+ type_class = RSpotify.const_get(item['type'].capitalize)
12
+ type_class.new item
13
+ end
14
+ end
15
+
16
+ def currently_playing
17
+ url = 'me/player/currently-playing'
18
+ response = User.oauth_get(@user.id, url)
19
+ return response if RSpotify.raw_response
20
+
21
+ type_class = RSpotify.const_get(response['currently_playing_type'].capitalize)
22
+ type_class.new response['item'] unless response['item'].nil?
23
+ end
24
+ end
25
+ end
data/lib/shellify/user.rb CHANGED
@@ -28,25 +28,25 @@ module Shellify
28
28
 
29
29
  def save!
30
30
  File.open(@user_file_path, 'w') do |file|
31
- file.write(JSON.pretty_generate({id: @id, token: @token, refresh_token: @refresh_token}))
31
+ file.write(JSON.pretty_generate({ id: @id, token: @token, refresh_token: @refresh_token }))
32
32
  end
33
33
  end
34
34
 
35
35
  private
36
36
 
37
37
  def load_persisted_user
38
- JSON.parse(File.read(@user_file_path)).each_pair { |k,v| instance_variable_set("@#{k}", v) }
38
+ JSON.parse(File.read(@user_file_path)).each_pair { |k, v| instance_variable_set("@#{k}", v) }
39
39
  end
40
40
 
41
41
  def access_refresh_callback
42
- Proc.new do |new_access_token, _token_lifetime|
42
+ proc do |new_access_token, _token_lifetime|
43
43
  @token = new_access_token
44
44
  save!
45
45
  end
46
46
  end
47
47
 
48
48
  def create_user_file
49
- return if File.exists?(@user_file_path)
49
+ return if File.exist?(@user_file_path)
50
50
 
51
51
  FileUtils.mkdir_p(@config_dir)
52
52
  FileUtils.touch(@user_file_path)
@@ -56,7 +56,7 @@ module Shellify
56
56
  return unless File.zero?(@user_file_path)
57
57
 
58
58
  File.open(@user_file_path, 'w') do |file|
59
- file.write(JSON.pretty_generate({id: '', token: '', refresh_token: '',}))
59
+ file.write(JSON.pretty_generate({ id: '', token: '', refresh_token: '' }))
60
60
  end
61
61
  end
62
62
  end
@@ -14,7 +14,7 @@ module Shellify
14
14
  end
15
15
 
16
16
  def time_to_ms(time)
17
- time.split(':').map { |a| a.to_i }.inject(0) { |a, b| a * 60 + b} * 1000
17
+ time.split(':').map(&:to_i).inject(0) { |a, b| a * 60 + b } * 1000
18
18
  end
19
19
 
20
20
  def generate_oauth_url
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Shellify
4
- VERSION = '1.1.1'
4
+ VERSION = '1.3.0'
5
5
  end
data/lib/shellify.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'fileutils'
4
4
  require 'json'
5
5
  require 'rspotify'
6
+ require 'shellify/rspotify_patch'
6
7
  require 'shellify/version'
7
8
 
8
9
  module Shellify
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shellify
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Povah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-01 00:00:00.000000000 Z
11
+ date: 2023-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander
@@ -81,6 +81,7 @@ files:
81
81
  - lib/shellify/cli.rb
82
82
  - lib/shellify/config.rb
83
83
  - lib/shellify/oauth_callback_handler.rb
84
+ - lib/shellify/rspotify_patch.rb
84
85
  - lib/shellify/user.rb
85
86
  - lib/shellify/utils.rb
86
87
  - lib/shellify/version.rb
@@ -99,14 +100,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
100
  requirements:
100
101
  - - ">="
101
102
  - !ruby/object:Gem::Version
102
- version: 2.4.0
103
+ version: 2.7.0
103
104
  required_rubygems_version: !ruby/object:Gem::Requirement
104
105
  requirements:
105
106
  - - ">="
106
107
  - !ruby/object:Gem::Version
107
108
  version: '0'
108
109
  requirements: []
109
- rubygems_version: 3.3.3
110
+ rubygems_version: 3.4.17
110
111
  signing_key:
111
112
  specification_version: 4
112
113
  summary: Use Spotify from the command line