turntabler 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +14 -0
- data/README.md +1 -1
- data/examples/Gemfile.lock +1 -1
- data/lib/turntabler/authorized_user.rb +4 -1
- data/lib/turntabler/client.rb +74 -6
- data/lib/turntabler/event.rb +84 -21
- data/lib/turntabler/playlist.rb +1 -1
- data/lib/turntabler/song.rb +55 -26
- data/lib/turntabler/user.rb +2 -1
- data/lib/turntabler/version.rb +2 -2
- data/lib/turntabler.rb +1 -1
- metadata +98 -74
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# master
|
2
2
|
|
3
|
+
## 0.3.0 / 2013-02-23
|
4
|
+
|
5
|
+
* Fix playlist order not being maintained properly in process
|
6
|
+
* Rename Song#enqueue to Song#add and Song#dequeue to Song#remove
|
7
|
+
* Song#dequeue and #move no longer allow the playlist to be specified since it's known upfront
|
8
|
+
* Fix Song#load not getting metadata from the correct playlist
|
9
|
+
* Add Song#playlist
|
10
|
+
* Add room_description_updated event
|
11
|
+
* Add song_skipped / song_moderated events
|
12
|
+
* Add #started_at, #ends_at, and #seconds_remaining to Song
|
13
|
+
* Add dj_escorted_off / dj_booed_off events
|
14
|
+
* Add fan_added / fan_removed events
|
15
|
+
* Add user_name_updated / user_avatar_updated / user_stickers_updated events
|
16
|
+
|
3
17
|
## 0.2.1 / 2013-02-16
|
4
18
|
|
5
19
|
* Fix exceptions on initial connection not causing reconnection process to kick in
|
data/README.md
CHANGED
data/examples/Gemfile.lock
CHANGED
@@ -250,8 +250,11 @@ module Turntabler
|
|
250
250
|
def update_status(status = self.status)
|
251
251
|
assert_valid_values(status, *%w(available unavailable away))
|
252
252
|
|
253
|
+
now = Time.now.to_i
|
253
254
|
result = api('presence.update', :status => status)
|
254
|
-
|
255
|
+
|
256
|
+
client.reset_keepalive(result['interval'])
|
257
|
+
client.clock_delta = ((now + Time.now.to_i) / 2 - result['now']).round
|
255
258
|
self.attributes = {'status' => status}
|
256
259
|
|
257
260
|
true
|
data/lib/turntabler/client.rb
CHANGED
@@ -36,6 +36,10 @@ module Turntabler
|
|
36
36
|
# @return [Fixnum]
|
37
37
|
attr_reader :timeout
|
38
38
|
|
39
|
+
# The difference of time (in seconds) between this client and Turntable servers
|
40
|
+
# @return [Fixnum]
|
41
|
+
attr_accessor :clock_delta
|
42
|
+
|
39
43
|
# Creates a new client for communicating with Turntable.fm with the given
|
40
44
|
# email / password.
|
41
45
|
#
|
@@ -67,6 +71,7 @@ module Turntabler
|
|
67
71
|
@timeout = options[:timeout]
|
68
72
|
@reconnect = options[:reconnect]
|
69
73
|
@reconnect_wait = options[:reconnect_wait]
|
74
|
+
@clock_delta = 0
|
70
75
|
|
71
76
|
# Setup default event handlers
|
72
77
|
on(:heartbeat) { on_heartbeat }
|
@@ -192,19 +197,27 @@ module Turntabler
|
|
192
197
|
# == Room Events
|
193
198
|
#
|
194
199
|
# * +:room_updated+ - Information about the room was updated
|
200
|
+
# * +:room_description_updated+ - The room's description was updated
|
195
201
|
#
|
196
202
|
# @example
|
197
203
|
# client.on :room_updated do |room| # Room
|
198
204
|
# puts room.description
|
199
205
|
# # ...
|
200
206
|
# end
|
207
|
+
#
|
208
|
+
# client.on :room_description_updated do |room| # Room
|
209
|
+
# puts room.description
|
210
|
+
# # ...
|
211
|
+
# end
|
201
212
|
#
|
202
213
|
# == User Events
|
203
214
|
#
|
204
215
|
# * +:user_entered+ - A user entered the room
|
205
216
|
# * +:user_left+ - A user left the room
|
206
217
|
# * +:user_booted+ - A user has been booted from the room
|
207
|
-
# * +:user_updated+ - A user's
|
218
|
+
# * +:user_updated+ - A user's profile was updated
|
219
|
+
# * +:user_name_updated+ - A user's name was updated
|
220
|
+
# * +:user_avatar_updated+ - A user's avatar was updated
|
208
221
|
# * +:user_spoke+ - A user spoke in the chat room
|
209
222
|
#
|
210
223
|
# @example
|
@@ -225,7 +238,22 @@ module Turntabler
|
|
225
238
|
# end
|
226
239
|
#
|
227
240
|
# client.on :user_updated do |user| # User
|
228
|
-
# puts user.
|
241
|
+
# puts user.name
|
242
|
+
# # ...
|
243
|
+
# end
|
244
|
+
#
|
245
|
+
# client.on :user_name_updated do |user| # User
|
246
|
+
# puts user.name
|
247
|
+
# # ...
|
248
|
+
# end
|
249
|
+
#
|
250
|
+
# client.on :user_avatar_updated do |user| # User
|
251
|
+
# puts user.avatar.id
|
252
|
+
# # ...
|
253
|
+
# end
|
254
|
+
#
|
255
|
+
# client.on :user_stickers_updated do |user| # User
|
256
|
+
# puts user.stickers.map {|sticker| sticker.id}
|
229
257
|
# # ...
|
230
258
|
# end
|
231
259
|
#
|
@@ -236,8 +264,26 @@ module Turntabler
|
|
236
264
|
#
|
237
265
|
# == DJ Events
|
238
266
|
#
|
239
|
-
# * +:
|
240
|
-
# * +:
|
267
|
+
# * +:fan_added+ - A new fan was added by a user in the room
|
268
|
+
# * +:fan_removed+ - A fan was removed from a user in the room
|
269
|
+
#
|
270
|
+
# @example
|
271
|
+
# client.on :fan_added do |user, fan_of| # User, User
|
272
|
+
# puts user.id
|
273
|
+
# # ...
|
274
|
+
# end
|
275
|
+
#
|
276
|
+
# client.on :fan_removed do |user, count| # User, Fixnum
|
277
|
+
# puts user.id
|
278
|
+
# # ...
|
279
|
+
# end
|
280
|
+
#
|
281
|
+
# == DJ Events
|
282
|
+
#
|
283
|
+
# * +:dj_added+ - A new DJ was added to the stage
|
284
|
+
# * +:dj_removed+ - A DJ was removed from the stage
|
285
|
+
# * +:dj_escorted_off+ - A DJ was escorted off the stage by a moderator
|
286
|
+
# * +:dj_booed_off+ - A DJ was booed off the stage
|
241
287
|
#
|
242
288
|
# @example
|
243
289
|
# client.on :dj_added do |user| # User
|
@@ -249,6 +295,16 @@ module Turntabler
|
|
249
295
|
# puts user.id
|
250
296
|
# # ...
|
251
297
|
# end
|
298
|
+
#
|
299
|
+
# client.on :dj_escorted_off do |user, moderator| # User, User
|
300
|
+
# puts user.id
|
301
|
+
# # ...
|
302
|
+
# end
|
303
|
+
#
|
304
|
+
# client.on :dj_booed_off do |user| # User
|
305
|
+
# puts user.id
|
306
|
+
# # ...
|
307
|
+
# end
|
252
308
|
#
|
253
309
|
# == Moderator Events
|
254
310
|
#
|
@@ -273,8 +329,9 @@ module Turntabler
|
|
273
329
|
# * +:song_ended+ - The current song has ended. This is typically followed by a +:song_started+ or +:song_unavailable+ event.
|
274
330
|
# * +:song_voted+ - One or more votes were cast for the song
|
275
331
|
# * +:song_snagged+ - A user in the room has queued the current song onto their playlist
|
276
|
-
# * +:
|
277
|
-
# * +:
|
332
|
+
# * +:song_skipped+ - A song was skipped due to either the dj skipping it or too many downvotes
|
333
|
+
# * +:song_moderated+ - A song was forcefully skipped by a moderator
|
334
|
+
# * +:song_blocked+ - A song was prevented from playing due to a copyright claim
|
278
335
|
#
|
279
336
|
# @example
|
280
337
|
# client.on :song_unavailable do
|
@@ -304,6 +361,17 @@ module Turntabler
|
|
304
361
|
# # ...
|
305
362
|
# end
|
306
363
|
#
|
364
|
+
# client.on :song_skipped do |song| # Song
|
365
|
+
# puts song.title
|
366
|
+
# # ...
|
367
|
+
# end
|
368
|
+
#
|
369
|
+
# client.on :song_moderated do |song, moderator| # Song, User
|
370
|
+
# puts song.title
|
371
|
+
# puts moderator.id
|
372
|
+
# # ...
|
373
|
+
# end
|
374
|
+
#
|
307
375
|
# client.on :song_blocked do |song| # Song
|
308
376
|
# puts song.id
|
309
377
|
# # ...
|
data/lib/turntabler/event.rb
CHANGED
@@ -23,7 +23,7 @@ module Turntabler
|
|
23
23
|
# @yieldreturn The typecasted data that should be passed into any handlers bound to the event
|
24
24
|
# @return [nil]
|
25
25
|
def handle(name, command = name, &block)
|
26
|
-
block ||= lambda {}
|
26
|
+
block ||= lambda { [args] }
|
27
27
|
commands[command] = name
|
28
28
|
|
29
29
|
define_method("typecast_#{command}_event", &block)
|
@@ -71,9 +71,17 @@ module Turntabler
|
|
71
71
|
# Information about the room was updated
|
72
72
|
handle :room_updated, :update_room do
|
73
73
|
room.attributes = data
|
74
|
+
|
75
|
+
# Trigger detailed events for exactly what changed to make it easier to
|
76
|
+
# detect the various situations
|
77
|
+
client.trigger(:room_description_updated, room) if data['description']
|
78
|
+
|
74
79
|
room
|
75
80
|
end
|
76
81
|
|
82
|
+
# A room's description has been updated
|
83
|
+
handle :room_description_updated
|
84
|
+
|
77
85
|
# One or more users have entered the room
|
78
86
|
handle :user_entered, :registered do
|
79
87
|
data['user'].map do |attrs|
|
@@ -101,43 +109,78 @@ module Turntabler
|
|
101
109
|
|
102
110
|
# A user's name / profile has been updated
|
103
111
|
handle :user_updated, :update_user do
|
104
|
-
fans_change = data.delete('fans')
|
112
|
+
fans_change = data.delete('fans') || 0
|
105
113
|
user = room.build_user(data)
|
106
|
-
user.attributes = {'fans' => user.fans_count + fans_change}
|
114
|
+
user.attributes = {'fans' => user.fans_count + fans_change}
|
115
|
+
|
116
|
+
# Trigger detailed events for exactly what changed to make it easier to
|
117
|
+
# detect the various situations
|
118
|
+
client.trigger(:user_name_updated, user) if data['name']
|
119
|
+
client.trigger(:user_avatar_updated, user) if data['avatarid']
|
120
|
+
client.trigger(:fan_added, user, room.build_user(:_id => data['fanid'])) if fans_change > 0
|
121
|
+
client.trigger(:fan_removed, user, fans_change.abs) if fans_change < 0
|
122
|
+
|
107
123
|
user
|
108
124
|
end
|
109
125
|
|
126
|
+
# A user's name has been updated
|
127
|
+
handle :user_name_updated
|
128
|
+
|
129
|
+
# A user's avatar has been updated
|
130
|
+
handle :user_avatar_updated
|
131
|
+
|
110
132
|
# A user's stickers have been updated
|
111
133
|
handle :user_updated, :update_sticker_placements do
|
112
|
-
room.build_user(data)
|
134
|
+
user = room.build_user(data)
|
135
|
+
client.trigger(:user_stickers_updated, user)
|
136
|
+
user
|
113
137
|
end
|
114
138
|
|
139
|
+
# A user's stickers have been updated
|
140
|
+
handle :user_stickers_updated
|
141
|
+
|
115
142
|
# A user spoke in the chat room
|
116
143
|
handle :user_spoke, :speak do
|
117
144
|
data['senderid'] = data.delete('userid')
|
118
145
|
Message.new(client, data)
|
119
146
|
end
|
120
147
|
|
121
|
-
# A new
|
148
|
+
# A new fan was added by a user in the room
|
149
|
+
handle :fan_added
|
150
|
+
|
151
|
+
# A fan has been removed by a user in the room
|
152
|
+
handle :fan_removed
|
153
|
+
|
154
|
+
# A new dj was added to the stage
|
122
155
|
handle :dj_added, :add_dj do
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
new_djs << [user]
|
127
|
-
room.djs << user
|
128
|
-
end
|
129
|
-
new_djs
|
156
|
+
user = room.build_user(data['user'][0].merge('placements' => data['placements']))
|
157
|
+
room.djs << user
|
158
|
+
user
|
130
159
|
end
|
131
160
|
|
132
|
-
# A dj was removed from the
|
161
|
+
# A dj was removed from the stage
|
133
162
|
handle :dj_removed, :rem_dj do
|
134
|
-
data['user']
|
135
|
-
|
136
|
-
|
137
|
-
|
163
|
+
user = room.build_user(data['user'][0])
|
164
|
+
room.djs.delete(user)
|
165
|
+
|
166
|
+
if moderator_id = data['modid']
|
167
|
+
if moderator_id == 1
|
168
|
+
client.trigger(:dj_booed_off, user)
|
169
|
+
else
|
170
|
+
moderator = room.build_user(:_id => data['user'][0])
|
171
|
+
client.trigger(:dj_escorted_off, user, moderator)
|
172
|
+
end
|
138
173
|
end
|
174
|
+
|
175
|
+
[user]
|
139
176
|
end
|
140
177
|
|
178
|
+
# A dj was escorted off the stage by a moderator
|
179
|
+
handle :dj_escorted_off
|
180
|
+
|
181
|
+
# A dj was booed off the stage
|
182
|
+
handle :dj_booed_off
|
183
|
+
|
141
184
|
# A new moderator was added to the room
|
142
185
|
handle :moderator_added, :new_moderator do
|
143
186
|
user = room.build_user(data)
|
@@ -155,7 +198,8 @@ module Turntabler
|
|
155
198
|
# There are no more songs to play in the room
|
156
199
|
handle :song_unavailable, :nosong do
|
157
200
|
client.trigger(:song_ended) if room.current_song
|
158
|
-
|
201
|
+
data['room'].delete('current_song')
|
202
|
+
room.attributes = data['room']
|
159
203
|
nil
|
160
204
|
end
|
161
205
|
|
@@ -163,12 +207,20 @@ module Turntabler
|
|
163
207
|
handle :song_started, :newsong do
|
164
208
|
client.trigger(:song_ended) if room.current_song
|
165
209
|
room.attributes = data['room']
|
166
|
-
room.current_song
|
210
|
+
current_song = room.current_song
|
211
|
+
|
212
|
+
# Update playlist order if it was played by the current user
|
213
|
+
current_song.dequeue if current_song.played_by == client.user
|
214
|
+
|
215
|
+
current_song
|
167
216
|
end
|
168
217
|
|
169
218
|
# The current song has ended
|
170
219
|
handle :song_ended do
|
171
|
-
room.current_song
|
220
|
+
current_song = room.current_song
|
221
|
+
client.trigger(:song_skipped) if current_song.seconds_remaining > 10
|
222
|
+
room.attributes = {'current_song' => nil}
|
223
|
+
current_song
|
172
224
|
end
|
173
225
|
|
174
226
|
# A vote was cast for the song
|
@@ -201,6 +253,16 @@ module Turntabler
|
|
201
253
|
Song.new(client, data)
|
202
254
|
end
|
203
255
|
|
256
|
+
# A song was forcefully skipped by a moderator
|
257
|
+
handle :song_moderated, :stop_song do
|
258
|
+
moderator = room.build_user(:_id => data['skipperId'])
|
259
|
+
[[room.current_song, moderator]]
|
260
|
+
end
|
261
|
+
|
262
|
+
# A song was ended before it completed, either because the dj skipped it or
|
263
|
+
# it was booed off
|
264
|
+
handle :song_skipped
|
265
|
+
|
204
266
|
# A private message was received from another user in the room
|
205
267
|
handle :message_received, :pmmed do
|
206
268
|
Message.new(client, data)
|
@@ -233,7 +295,8 @@ module Turntabler
|
|
233
295
|
# Creates a new event triggered with the given data
|
234
296
|
#
|
235
297
|
# @param [Turntabler::Client] client The client that this event is bound to
|
236
|
-
# @param [
|
298
|
+
# @param [Symbol] command The name of the command that fired the event
|
299
|
+
# @param [Array] args The raw argument data from the event
|
237
300
|
def initialize(client, command, args)
|
238
301
|
@client = client
|
239
302
|
@args = args
|
data/lib/turntabler/playlist.rb
CHANGED
@@ -16,7 +16,7 @@ module Turntabler
|
|
16
16
|
# The songs that have been added to this playlist
|
17
17
|
# @return [Array<Turntabler::Song>]
|
18
18
|
attribute :songs, :list do |songs|
|
19
|
-
songs.map {|attrs| Song.new(client, attrs)}
|
19
|
+
songs.map {|attrs| Song.new(client, attrs.merge(:playlist => id))}
|
20
20
|
end
|
21
21
|
|
22
22
|
# Loads the attributes for this playlist. Attributes will automatically load
|
data/lib/turntabler/song.rb
CHANGED
@@ -49,6 +49,16 @@ module Turntabler
|
|
49
49
|
# @return [String]
|
50
50
|
attribute :source_id, :sourceid
|
51
51
|
|
52
|
+
# The playlist this song is referenced from
|
53
|
+
# @return [Turntabler::Playlist]
|
54
|
+
attribute :playlist do |id|
|
55
|
+
client.user.playlists.build(:_id => id)
|
56
|
+
end
|
57
|
+
|
58
|
+
# The time at which the song was started
|
59
|
+
# @return [Time]
|
60
|
+
attribute :started_at, :starttime
|
61
|
+
|
52
62
|
# The number of up votes this song has received.
|
53
63
|
# @note This is only available for the current song playing in a room
|
54
64
|
# @return [Fixnum]
|
@@ -84,14 +94,33 @@ module Turntabler
|
|
84
94
|
end
|
85
95
|
|
86
96
|
# @api private
|
87
|
-
def initialize(*)
|
97
|
+
def initialize(client, *)
|
88
98
|
@up_votes_count = 0
|
89
99
|
@down_votes_count = 0
|
90
100
|
@votes = []
|
91
101
|
@score = 0
|
102
|
+
@playlist = client.user.playlists.build(:_id => 'default')
|
92
103
|
super
|
93
104
|
end
|
94
105
|
|
106
|
+
# The time at which this song will end playing.
|
107
|
+
#
|
108
|
+
# @return [Time]
|
109
|
+
# @example
|
110
|
+
# song.ends_at # => 2013-01-05 12:14:25 -0500
|
111
|
+
def ends_at
|
112
|
+
started_at + client.clock_delta + length if started_at
|
113
|
+
end
|
114
|
+
|
115
|
+
# The number of seconds remaining to play in the song
|
116
|
+
#
|
117
|
+
# @return [Fixnum]
|
118
|
+
# @example
|
119
|
+
# song.seconds_remaining # => 12
|
120
|
+
def seconds_remaining
|
121
|
+
ends_at ? (ends_at - started_at).round : 0
|
122
|
+
end
|
123
|
+
|
95
124
|
# Loads the attributes for this song. Attributes will automatically load
|
96
125
|
# when accessed, but this allows data to be forcefully loaded upfront.
|
97
126
|
#
|
@@ -101,7 +130,7 @@ module Turntabler
|
|
101
130
|
# song.load # => true
|
102
131
|
# song.title # => "..."
|
103
132
|
def load
|
104
|
-
data = api('playlist.get_metadata', :playlist_name =>
|
133
|
+
data = api('playlist.get_metadata', :playlist_name => playlist.id, :files => [id])
|
105
134
|
self.attributes = data['files'][id]
|
106
135
|
super
|
107
136
|
end
|
@@ -172,37 +201,35 @@ module Turntabler
|
|
172
201
|
# Adds the song to one of the user's playlists.
|
173
202
|
#
|
174
203
|
# @param [Hash] options The options for where to add the song
|
175
|
-
# @option options [String] :playlist ("default") The playlist to
|
204
|
+
# @option options [String] :playlist ("default") The playlist to add the song in
|
176
205
|
# @option options [Fixnum] :index (0) The location in the playlist to insert the song
|
177
206
|
# @return [true]
|
178
207
|
# @raise [ArgumentError] if an invalid option is specified
|
179
208
|
# @raise [Turntabler::Error] if the command fails
|
180
209
|
# @example
|
181
|
-
# song.
|
182
|
-
def
|
210
|
+
# song.add(:index => 1) # => true
|
211
|
+
def add(options = {})
|
183
212
|
assert_valid_keys(options, :playlist, :index)
|
184
|
-
options = {:playlist =>
|
185
|
-
|
213
|
+
options = {:playlist => playlist.id, :index => 0}.merge(options)
|
214
|
+
|
215
|
+
# Create a copy of the song so that the playlist can get set properly
|
216
|
+
song = dup
|
217
|
+
song.attributes = {:playlist => options[:playlist]}
|
218
|
+
playlist, index = song.playlist, options[:index]
|
186
219
|
|
187
220
|
api('playlist.add', :playlist_name => playlist.id, :song_dict => {:fileid => id}, :index => index)
|
188
|
-
playlist.songs.insert(index,
|
221
|
+
playlist.songs.insert(index, song) if playlist.loaded?
|
189
222
|
true
|
190
223
|
end
|
191
224
|
|
192
225
|
# Removes the song from the playlist at the given index.
|
193
226
|
#
|
194
|
-
# @param [Hash] options The options for where to remove the song
|
195
|
-
# @option options [String] :playlist ("default") The playlist to dequeue the song from
|
196
227
|
# @return [true]
|
197
228
|
# @raise [ArgumentError] if an invalid option is specified
|
198
229
|
# @raise [Turntabler::Error] if the command fails
|
199
230
|
# @example
|
200
|
-
# song.
|
201
|
-
def
|
202
|
-
assert_valid_keys(options, :playlist)
|
203
|
-
options = {:playlist => 'default'}.merge(options)
|
204
|
-
playlist, index = index(options[:playlist])
|
205
|
-
|
231
|
+
# song.remove # => true
|
232
|
+
def remove
|
206
233
|
api('playlist.remove', :playlist_name => playlist.id, :index => index)
|
207
234
|
playlist.songs.delete(self)
|
208
235
|
true
|
@@ -211,22 +238,25 @@ module Turntabler
|
|
211
238
|
# Move a song from one location in the playlist to another.
|
212
239
|
#
|
213
240
|
# @param [Fixnum] to_index The index to move the song to
|
214
|
-
# @param [Hash] options The options for where to remove the song
|
215
|
-
# @option options [String] :playlist ("default") The playlist to move the song within
|
216
241
|
# @return [true]
|
217
242
|
# @raise [ArgumentError] if an invalid option is specified
|
218
243
|
# @raise [Turntabler::Error] if the command fails
|
219
244
|
# song.move(5) # => true
|
220
|
-
def move(to_index
|
221
|
-
assert_valid_keys(options, :playlist)
|
222
|
-
options = {:playlist => 'default'}.merge(options)
|
223
|
-
playlist, index = index(options[:playlist])
|
224
|
-
|
245
|
+
def move(to_index)
|
225
246
|
api('playlist.reorder', :playlist_name => playlist.id, :index_from => index, :index_to => to_index)
|
226
247
|
playlist.songs.insert(to_index, playlist.songs.delete(self))
|
227
248
|
true
|
228
249
|
end
|
229
250
|
|
251
|
+
# Moves this song to the back of the playlist it's associated with. If there
|
252
|
+
# are other songs in front of it, those will be moved to the back as well.
|
253
|
+
#
|
254
|
+
# @api private
|
255
|
+
def dequeue
|
256
|
+
playlist.songs.concat(playlist.songs.slice!(0, index + 1))
|
257
|
+
true
|
258
|
+
end
|
259
|
+
|
230
260
|
private
|
231
261
|
# Asserts that this is the song currently being played in the room the user
|
232
262
|
# is in. Raises Turntabler::Error if this is not the case.
|
@@ -236,11 +266,10 @@ module Turntabler
|
|
236
266
|
|
237
267
|
# Gets the index of this song within the given playlist. Raises Turntabler::Error
|
238
268
|
# if the song cannot be found in the playlist.
|
239
|
-
def index
|
240
|
-
playlist = client.user.playlist(playlist_id)
|
269
|
+
def index
|
241
270
|
index = playlist.songs.index(self)
|
242
271
|
raise(APIError, "Song \"#{id}\" is not in playlist \"#{playlist.id}\"") unless index
|
243
|
-
|
272
|
+
index
|
244
273
|
end
|
245
274
|
end
|
246
275
|
end
|
data/lib/turntabler/user.rb
CHANGED
@@ -68,7 +68,8 @@ module Turntabler
|
|
68
68
|
|
69
69
|
# The placements of stickers on the user's laptop
|
70
70
|
# @return [Array<Turntabler::StickerPlacement>]
|
71
|
-
attribute :sticker_placements, :placements do |placements|
|
71
|
+
attribute :sticker_placements, :sticker_placements, :placements do |placements|
|
72
|
+
placements = placements.keys if placements.is_a?(Hash)
|
72
73
|
placements.map {|attrs| StickerPlacement.new(client, attrs)}
|
73
74
|
end
|
74
75
|
|
data/lib/turntabler/version.rb
CHANGED
data/lib/turntabler.rb
CHANGED
metadata
CHANGED
@@ -1,94 +1,121 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: turntabler
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.1
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Aaron Pfeifer
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-02-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: em-synchrony
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
24
22
|
type: :runtime
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: em-http-request
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
25
|
none: false
|
31
|
-
requirements:
|
32
|
-
- -
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: em-http-request
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
35
38
|
type: :runtime
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: faye-websocket
|
39
39
|
prerelease: false
|
40
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version:
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: faye-websocket
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
46
54
|
type: :runtime
|
47
|
-
version_requirements: *id003
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: rake
|
50
55
|
prerelease: false
|
51
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
52
65
|
none: false
|
53
|
-
requirements:
|
54
|
-
- -
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version:
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
57
70
|
type: :development
|
58
|
-
version_requirements: *id004
|
59
|
-
- !ruby/object:Gem::Dependency
|
60
|
-
name: rspec
|
61
71
|
prerelease: false
|
62
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
63
81
|
none: false
|
64
|
-
requirements:
|
82
|
+
requirements:
|
65
83
|
- - ~>
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version:
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '2.11'
|
68
86
|
type: :development
|
69
|
-
version_requirements: *id005
|
70
|
-
- !ruby/object:Gem::Dependency
|
71
|
-
name: simplecov
|
72
87
|
prerelease: false
|
73
|
-
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
89
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
version:
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '2.11'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: simplecov
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
79
102
|
type: :development
|
80
|
-
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
81
110
|
description: Turntable.FM API for Ruby
|
82
111
|
email: aaron.pfeifer@gmail.com
|
83
112
|
executables: []
|
84
|
-
|
85
113
|
extensions: []
|
86
|
-
|
87
|
-
extra_rdoc_files:
|
114
|
+
extra_rdoc_files:
|
88
115
|
- README.md
|
89
116
|
- CHANGELOG.md
|
90
117
|
- LICENSE
|
91
|
-
files:
|
118
|
+
files:
|
92
119
|
- .gitignore
|
93
120
|
- .rspec
|
94
121
|
- .yardopts
|
@@ -139,36 +166,33 @@ files:
|
|
139
166
|
- turntabler.gemspec
|
140
167
|
homepage: http://github.com/obrie/turntabler
|
141
168
|
licenses: []
|
142
|
-
|
143
169
|
post_install_message:
|
144
|
-
rdoc_options:
|
170
|
+
rdoc_options:
|
145
171
|
- --line-numbers
|
146
172
|
- --inline-source
|
147
173
|
- --title
|
148
174
|
- turntabler
|
149
175
|
- --main
|
150
176
|
- README.md
|
151
|
-
require_paths:
|
177
|
+
require_paths:
|
152
178
|
- lib
|
153
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
180
|
none: false
|
155
|
-
requirements:
|
156
|
-
- -
|
157
|
-
- !ruby/object:Gem::Version
|
158
|
-
version:
|
159
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
|
+
requirements:
|
182
|
+
- - ! '>='
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: '0'
|
185
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
186
|
none: false
|
161
|
-
requirements:
|
162
|
-
- -
|
163
|
-
- !ruby/object:Gem::Version
|
164
|
-
version:
|
187
|
+
requirements:
|
188
|
+
- - ! '>='
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
165
191
|
requirements: []
|
166
|
-
|
167
192
|
rubyforge_project:
|
168
|
-
rubygems_version: 1.8.
|
193
|
+
rubygems_version: 1.8.25
|
169
194
|
signing_key:
|
170
195
|
specification_version: 3
|
171
196
|
summary: Turntable.FM API for Ruby
|
172
197
|
test_files: []
|
173
|
-
|
174
198
|
has_rdoc:
|