alexa_remotectl 0.4.0 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/alexa_remotectl.rb +154 -38
- data.tar.gz.sig +3 -2
- metadata +2 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3390f693c5318ae22b5c79fbe464dacd839ef331c4d3f2a07e9aeed38229be2
|
4
|
+
data.tar.gz: adb89f569f0f47f88304c5032b963e171c556d340f928dd70de0437318c9b09f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 874e773c33e46ab1843c655ba49f138ffff68f9ef7a088cf550f5791c3e6fa567545f1e1a8fab52083b860c3c512ffdebd86f312059c2fc9d1e5def5a9881539
|
7
|
+
data.tar.gz: f0f91e9861f1cd68e3d2494341f6bbc28f2d482d5766b124b66f65e9cab60fa34d03f199516bc1f75936320e620096f40d9b33c9a98dfb2991575529c1736bbe
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/alexa_remotectl.rb
CHANGED
@@ -22,14 +22,15 @@ class CodeWizard
|
|
22
22
|
|
23
23
|
return 'no curl command found' unless s =~ /curl/
|
24
24
|
|
25
|
-
cookie, serialno, type = parse(s)
|
25
|
+
cookie, csrf, serialno, type = parse(s)
|
26
26
|
|
27
27
|
@s =<<EOF
|
28
28
|
require 'alexa_remotectl'
|
29
29
|
|
30
30
|
cookie = '#{cookie}'
|
31
|
+
csrf = '#{csrf}'
|
31
32
|
device = {serialno: '#{serialno}', type: '#{type}'}
|
32
|
-
alexa = AlexaRemoteCtl.new(cookie: cookie, device: device)
|
33
|
+
alexa = AlexaRemoteCtl.new(cookie: cookie, csrf: csrf, device: device)
|
33
34
|
alexa.pause
|
34
35
|
#alexa.play
|
35
36
|
EOF
|
@@ -50,17 +51,22 @@ EOF
|
|
50
51
|
serialno = s[/deviceSerialNumber=(\w+)/,1]
|
51
52
|
type = s[/deviceType=(\w+)/,1]
|
52
53
|
cookie = s[/Cookie: ([^']+)/,1]
|
54
|
+
csrf = s[/csrf: ([^']+)/,1]
|
53
55
|
|
54
|
-
[cookie, serialno, type]
|
56
|
+
[cookie, csrf, serialno, type]
|
55
57
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
61
|
class AlexaRemoteCtl
|
60
62
|
|
61
|
-
|
63
|
+
# note: Added the Cross-site request forgery (crsf) variable
|
64
|
+
#
|
65
|
+
def initialize(domain: 'alexa.amazon.co.uk', device: {}, cookie: '',
|
66
|
+
customerid: '', csrf: '')
|
62
67
|
|
63
|
-
@domain, @device, @cookie = domain, device, cookie
|
68
|
+
@domain, @device, @cookie, @customerid = domain, device, cookie, customerid
|
69
|
+
@csrf = csrf
|
64
70
|
|
65
71
|
end
|
66
72
|
|
@@ -68,6 +74,17 @@ class AlexaRemoteCtl
|
|
68
74
|
device_player()[:playerInfo]
|
69
75
|
end
|
70
76
|
|
77
|
+
def list_ebooks()
|
78
|
+
get_json '/api/ebooks/library', "mediaOwnerCustomerId=#{@customerid}" +
|
79
|
+
"&nextToken=&size=50"
|
80
|
+
end
|
81
|
+
|
82
|
+
# list historical queue (hq)
|
83
|
+
#
|
84
|
+
def list_hq()
|
85
|
+
get_json '/api/media/historical-queue', "size=50&offset=-1"
|
86
|
+
end
|
87
|
+
|
71
88
|
def mute?()
|
72
89
|
info()[:volume][:muted]
|
73
90
|
end
|
@@ -87,6 +104,31 @@ class AlexaRemoteCtl
|
|
87
104
|
pp_cmd('Play')
|
88
105
|
end
|
89
106
|
|
107
|
+
def play_ebook(id)
|
108
|
+
|
109
|
+
serialno = @device[:serialno]
|
110
|
+
type = @device[:type]
|
111
|
+
|
112
|
+
url = "https://#{@domain}/api/ebooks/queue-and-play?"
|
113
|
+
|
114
|
+
body = {
|
115
|
+
'asin' => id,
|
116
|
+
'deviceType' => type,
|
117
|
+
'deviceSerialNumber' => serialno,
|
118
|
+
'mediaOwnerCustomerId' => @customerid
|
119
|
+
}.to_json
|
120
|
+
|
121
|
+
post_request url, body
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
# play historical queue
|
126
|
+
# note: You can find the queueid from an entry in the list_hq() result
|
127
|
+
#
|
128
|
+
def play_hq(queueid)
|
129
|
+
device_phq(queueid)
|
130
|
+
end
|
131
|
+
|
90
132
|
def playing?()
|
91
133
|
info()[:state] == 'PLAYING'
|
92
134
|
end
|
@@ -136,18 +178,51 @@ class AlexaRemoteCtl
|
|
136
178
|
serialno = @device[:serialno]
|
137
179
|
type = @device[:type]
|
138
180
|
|
139
|
-
url = "https://#{@domain}/api/np/command?
|
181
|
+
url = "https://#{@domain}/api/np/command?deviceSerial" +
|
182
|
+
"Number=#{serialno}&deviceType=#{type}"
|
140
183
|
post_command url, body
|
141
184
|
|
142
185
|
end
|
143
186
|
|
187
|
+
# play historical queue (PHQ)
|
188
|
+
#
|
189
|
+
def device_phq(queueid)
|
190
|
+
|
191
|
+
serialno = @device[:serialno]
|
192
|
+
type = @device[:type]
|
193
|
+
|
194
|
+
url = "https://#{@domain}/api/media/play-historical-queue"
|
195
|
+
|
196
|
+
body = {
|
197
|
+
'deviceType' => type,
|
198
|
+
'deviceSerialNumber' => serialno,
|
199
|
+
'queueId' => queueid,
|
200
|
+
'startTime' => nil,
|
201
|
+
'service' => nil,
|
202
|
+
'trackSource' => nil,
|
203
|
+
'mediaOwnerCustomerId' => @customerid
|
204
|
+
}.to_json
|
205
|
+
|
206
|
+
post_request url, body
|
207
|
+
|
208
|
+
end
|
209
|
+
|
144
210
|
def device_player()
|
211
|
+
get_json '/api/np/player'
|
212
|
+
end
|
213
|
+
|
214
|
+
def get_json(uri, params='')
|
215
|
+
|
145
216
|
serialno = @device[:serialno]
|
146
217
|
type = @device[:type]
|
147
218
|
|
148
|
-
url = "https://#{@domain}
|
149
|
-
|
219
|
+
url = "https://#{@domain}#{uri}?deviceSerial" +
|
220
|
+
"Number=#{serialno}&deviceType=#{type}"
|
221
|
+
url += '&' + params if params.length > 1
|
222
|
+
|
223
|
+
r = get_request url
|
150
224
|
JSON.parse(r.body, symbolize_names: true)
|
225
|
+
|
151
226
|
end
|
152
227
|
|
153
228
|
def make_response(uri, request)
|
@@ -155,16 +230,17 @@ class AlexaRemoteCtl
|
|
155
230
|
request["Accept"] = "application/json, text/javascript, */*; q=0.01"
|
156
231
|
request["Accept-Language"] = "en-GB,en-US;q=0.9,en;q=0.8"
|
157
232
|
request["Connection"] = "keep-alive"
|
158
|
-
request["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
|
159
233
|
request["Cookie"] = @cookie
|
160
234
|
|
161
235
|
request["Referer"] = "https://#{@domain}/spa/index.html"
|
162
236
|
request["Sec-Fetch-Dest"] = "empty"
|
163
237
|
request["Sec-Fetch-Mode"] = "cors"
|
164
238
|
request["Sec-Fetch-Site"] = "same-origin"
|
165
|
-
request["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64)
|
239
|
+
request["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) " +
|
240
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
241
|
+
"Chrome/101.0.4951.64 Safari/537.36"
|
166
242
|
request["X-Requested-With"] = "XMLHttpRequest"
|
167
|
-
request["csrf"] =
|
243
|
+
request["csrf"] = @csrf
|
168
244
|
request["dnt"] = "1"
|
169
245
|
request["sec-ch-ua"] = "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"101\""
|
170
246
|
request["sec-ch-ua-mobile"] = "?0"
|
@@ -181,6 +257,7 @@ class AlexaRemoteCtl
|
|
181
257
|
end
|
182
258
|
|
183
259
|
def post_command(url, body='')
|
260
|
+
|
184
261
|
uri = URI.parse(url)
|
185
262
|
request = Net::HTTP::Post.new(uri)
|
186
263
|
request.body = body
|
@@ -193,7 +270,7 @@ class AlexaRemoteCtl
|
|
193
270
|
# response.body
|
194
271
|
end
|
195
272
|
|
196
|
-
def
|
273
|
+
def get_request(url)
|
197
274
|
|
198
275
|
uri = URI.parse(url)
|
199
276
|
request = Net::HTTP::Get.new(uri)
|
@@ -204,6 +281,19 @@ class AlexaRemoteCtl
|
|
204
281
|
|
205
282
|
end
|
206
283
|
|
284
|
+
|
285
|
+
def post_request(url, body='')
|
286
|
+
|
287
|
+
uri = URI.parse(url)
|
288
|
+
request = Net::HTTP::Post.new(uri)
|
289
|
+
request.body = body
|
290
|
+
response = make_response(uri, request)
|
291
|
+
|
292
|
+
# response.code
|
293
|
+
# response.body
|
294
|
+
|
295
|
+
end
|
296
|
+
|
207
297
|
end
|
208
298
|
|
209
299
|
class AlexaDevices
|
@@ -212,59 +302,85 @@ class AlexaDevices
|
|
212
302
|
# note: label can be any identifier you choose e.g. kitchen
|
213
303
|
#
|
214
304
|
def initialize(devicesx=[], devices: devicesx,
|
215
|
-
domain: 'alexa.amazon.co.uk', cookie: ''
|
305
|
+
domain: 'alexa.amazon.co.uk', cookie: '', customerid: '',
|
306
|
+
csrf: '', debug: false)
|
216
307
|
|
217
308
|
@devices, @domain, @cookie = devices, domain, cookie
|
309
|
+
@customerid, @csrf, @debug = customerid, csrf, debug
|
218
310
|
|
219
311
|
end
|
220
312
|
|
313
|
+
def info(id=nil) invoke(:info, id) end
|
314
|
+
def list_ebooks(id) invoke(:list_ebooks, id) end
|
315
|
+
def list_hq(id=nil) invoke(:list_hq, id) end
|
316
|
+
def mute?(id=nil) invoke2(:mute?, id) end
|
317
|
+
def next(id) invoke2(:next, id) end
|
318
|
+
|
221
319
|
def playing()
|
222
320
|
|
223
|
-
@devices.map do |device, label|
|
224
|
-
alexa = AlexaRemoteCtl.new(cookie: @cookie, device: device)
|
225
|
-
alexa.playing? ? [alexa, label] : nil
|
226
|
-
end.compact
|
321
|
+
devices = @devices.map do |device, label|
|
227
322
|
|
228
|
-
|
323
|
+
puts 'label: ' + label.inspect if @debug
|
324
|
+
puts 'device: ' + device.inspect if @debug
|
229
325
|
|
230
|
-
|
326
|
+
alexa = get_alexa device
|
327
|
+
alexa.playing? ? [alexa, label] : nil
|
231
328
|
|
232
|
-
|
329
|
+
end.compact
|
233
330
|
|
234
|
-
if
|
331
|
+
puts 'devices: ' + devices.inspect if @debug
|
332
|
+
return devices
|
235
333
|
|
236
|
-
|
237
|
-
alexa.pause
|
334
|
+
end
|
238
335
|
|
239
|
-
|
336
|
+
def pause(id=nil) invoke2(:pause, id) end
|
337
|
+
def play(id) invoke(:play, id) end
|
338
|
+
def play_ebook(id) invoke(:list_hq, id) end
|
339
|
+
def play_hq(id,qid) invoke(:play_hq, id, qid) end
|
340
|
+
def playing?(id=nil) invoke(:playing, id) end
|
341
|
+
def text1(id=nil) invoke2(:text1, id) end
|
342
|
+
def text2(id=nil) invoke2(:text2, id) end
|
343
|
+
def title(id=nil) invoke2(:title, id) end
|
344
|
+
def vol(id=nil) invoke(:vol, id) end
|
345
|
+
def vol=(id=nil) invoke(:vol=, id) end
|
240
346
|
|
241
|
-
|
242
|
-
puts 'Pausing @' + label.inspect
|
243
|
-
alexa.pause
|
244
|
-
end
|
347
|
+
private
|
245
348
|
|
246
|
-
|
247
|
-
end
|
349
|
+
def get_alexa(device)
|
248
350
|
|
249
|
-
|
351
|
+
AlexaRemoteCtl.new(cookie: @cookie, device: device,
|
352
|
+
customerid: @customerid, csrf: @csrf)
|
353
|
+
end
|
250
354
|
|
251
|
-
|
355
|
+
def apply_cmd(a, cmd, id, args)
|
252
356
|
|
253
357
|
if id then
|
254
358
|
|
255
359
|
device, _ = a.find {|_, label| label.to_sym == id.to_sym}
|
256
|
-
alexa =
|
257
|
-
alexa.
|
360
|
+
alexa = get_alexa device
|
361
|
+
alexa.method(cmd).call(*args)
|
258
362
|
|
259
363
|
else
|
260
364
|
|
261
|
-
a.
|
262
|
-
|
263
|
-
|
264
|
-
alexa
|
365
|
+
a.map do |device, label|
|
366
|
+
|
367
|
+
puts cmd.to_s + ' @' + label.inspect
|
368
|
+
alexa = get_alexa device
|
369
|
+
alexa.method(cmd).call(*args)
|
370
|
+
|
265
371
|
end
|
266
372
|
|
267
373
|
end
|
268
374
|
end
|
269
375
|
|
376
|
+
def invoke(cmd, id, *args)
|
377
|
+
apply_cmd(@devices, cmd, id, args)
|
378
|
+
end
|
379
|
+
|
380
|
+
# apply command to an Alexa device which is currently playing
|
381
|
+
#
|
382
|
+
def invoke2(cmd, id, *args)
|
383
|
+
apply_cmd(playing(), cmd, id, args)
|
384
|
+
end
|
385
|
+
|
270
386
|
end
|
data.tar.gz.sig
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
:�c>j<�;Iy6A�-=�i)�+4��b�
|
2
|
+
�"M�b�*��+�jM`|����L_WM�+ѫ�5�GX�T�E>u�T�ehK�[oO�P�ф�^e�)�MƢฮ�$����k�I�9�~b��Ӭ*�Ȩ+�22��,GA-��*ϑ`�[V��8�3ݽ�snf�՜L
|
3
|
+
�
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alexa_remotectl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
d/gEwBtUmduwWZNX2NOJehf8s1cnH9OBP7s1ziHjdkZCgkQm3QewRRcdfZeYwFi6
|
36
36
|
4kVEcApgAgd+04ctE6uiRn5o
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2022-05-
|
38
|
+
date: 2022-05-23 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: clipboard
|
metadata.gz.sig
CHANGED
Binary file
|