alexa_remotectl 0.1.0 → 0.4.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: e11608ee8951bc2b2ee2f536c56df1bb5f8f345de55621f863e347a724f15e2a
4
- data.tar.gz: 152b8dd0ba4a2e86a598402eb87c00cc5a938b85395fe2cd0c7abbb642d1253e
3
+ metadata.gz: d3641c9d28ab824390ab0dc3aebec594eb204fdb0d09f8536ded7a7efd541e62
4
+ data.tar.gz: 8afb412ab356140e1289d1df7b49487bbc72e2b0d0593f43106f32dc8e643683
5
5
  SHA512:
6
- metadata.gz: 027e4da7333752221c6f868d105694ae4f054ff0b758f7d63550e2d75914dc42d5002413c972faf966e2e12a0fac36e3edd1cd4264884f5f05f75405624f9fde
7
- data.tar.gz: 03ac22cf51046c646f7492982a39143ea3baca5a192ae33f72cd559f27201388c53a188a6a8c5c2769b506c4224c7216b2422b8d7cf54ba8fdd0d35696e55d4f
6
+ metadata.gz: 7bf863c6ae5e8d4426a32d0b57b0c763aaff8534a0bc379eb3a30e0aaaebb564317d6463b4ab0025133d8b720721315a10c7dc00473c70bb79f4567d1961d1d9
7
+ data.tar.gz: eb8b72c82327e56afc915dbe0ed2400a05db3ea061c5ae478e61b9cfc7f8e36e3f0f0c4b73908a97e45280f618bab40a9645a7d6f02429bc8f7400675d92e0f1
checksums.yaml.gz.sig CHANGED
Binary file
@@ -7,7 +7,54 @@
7
7
 
8
8
  require 'net/http'
9
9
  require 'uri'
10
+ require 'clipboard'
11
+ require 'json'
10
12
 
13
+ # Use the CodeWizard with the cURL command you've copied using Developer
14
+ # tools on Alexa's SPA page (within the web browser).
15
+ #
16
+ # note: to find the correct url to convert, try clickin on pause or play to
17
+ # invoke an AJAX request
18
+
19
+ class CodeWizard
20
+
21
+ def initialize(s='')
22
+
23
+ return 'no curl command found' unless s =~ /curl/
24
+
25
+ cookie, serialno, type = parse(s)
26
+
27
+ @s =<<EOF
28
+ require 'alexa_remotectl'
29
+
30
+ cookie = '#{cookie}'
31
+ device = {serialno: '#{serialno}', type: '#{type}'}
32
+ alexa = AlexaRemoteCtl.new(cookie: cookie, device: device)
33
+ alexa.pause
34
+ #alexa.play
35
+ EOF
36
+
37
+ end
38
+
39
+ def to_s()
40
+ Clipboard.copy @s
41
+ puts 'copied to clipboard'
42
+
43
+ @s
44
+ end
45
+
46
+ private
47
+
48
+ def parse(s)
49
+
50
+ serialno = s[/deviceSerialNumber=(\w+)/,1]
51
+ type = s[/deviceType=(\w+)/,1]
52
+ cookie = s[/Cookie: ([^']+)/,1]
53
+
54
+ [cookie, serialno, type]
55
+
56
+ end
57
+ end
11
58
 
12
59
  class AlexaRemoteCtl
13
60
 
@@ -17,33 +64,100 @@ class AlexaRemoteCtl
17
64
 
18
65
  end
19
66
 
67
+ def info()
68
+ device_player()[:playerInfo]
69
+ end
70
+
71
+ def mute?()
72
+ info()[:volume][:muted]
73
+ end
74
+
75
+ alias muted? mute?
76
+
77
+ # skip to the next music track
78
+ def next
79
+ pp_cmd('Next')
80
+ end
81
+
20
82
  def pause
21
- device_cmd('Pause')
83
+ pp_cmd('Pause')
22
84
  end
23
85
 
24
86
  def play
25
- device_cmd('Play')
87
+ pp_cmd('Play')
88
+ end
89
+
90
+ def playing?()
91
+ info()[:state] == 'PLAYING'
92
+ end
93
+
94
+ # Artist name
95
+ #
96
+ def text1()
97
+ info()[:infoText][:subText1]
98
+ end
99
+
100
+ # music station
101
+ #
102
+ def text2()
103
+ info()[:infoText][:subText2]
104
+ end
105
+
106
+ # music track title
107
+ #
108
+ def title()
109
+ info()[:infoText][:title]
110
+ end
111
+
112
+ def vol()
113
+ info()[:volume][:volume]
114
+ end
115
+
116
+ def vol=(n)
117
+
118
+ return unless n.between? 0, 40
119
+
120
+ body = '{"type":"VolumeLevelCommand","volumeLevel":' + n.to_s \
121
+ + ',"contentFocusClientId":null}'
122
+ device_cmd(body)
26
123
  end
27
124
 
28
125
  private
29
126
 
30
- def device_cmd(cmd)
127
+ # play, pause, or next
128
+ #
129
+ def pp_cmd(s)
130
+ body = '{"type":"' + s + 'Command","contentFocusClientId":null}'
131
+ device_cmd body
132
+ end
133
+
134
+ def device_cmd(body)
31
135
 
32
136
  serialno = @device[:serialno]
33
137
  type = @device[:type]
34
138
 
35
139
  url = "https://#{@domain}/api/np/command?deviceSerialNumber=#{serialno}&deviceType=#{type}"
36
- uri = URI.parse(url)
37
- request = Net::HTTP::Post.new(uri)
38
- request.body = '{"type":"' + cmd + 'Command","contentFocusClientId":null}'
39
- request.content_type = "application/x-www-form-urlencoded; charset=UTF-8"
140
+ post_command url, body
141
+
142
+ end
143
+
144
+ def device_player()
145
+ serialno = @device[:serialno]
146
+ type = @device[:type]
147
+
148
+ url = "https://#{@domain}/api/np/player?deviceSerialNumber=#{serialno}&deviceType=#{type}"
149
+ r = post_request url
150
+ JSON.parse(r.body, symbolize_names: true)
151
+ end
152
+
153
+ def make_response(uri, request)
40
154
 
41
155
  request["Accept"] = "application/json, text/javascript, */*; q=0.01"
42
156
  request["Accept-Language"] = "en-GB,en-US;q=0.9,en;q=0.8"
43
157
  request["Connection"] = "keep-alive"
44
158
  request["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
45
159
  request["Cookie"] = @cookie
46
- request["Origin"] = "https://" + @domain
160
+
47
161
  request["Referer"] = "https://#{@domain}/spa/index.html"
48
162
  request["Sec-Fetch-Dest"] = "empty"
49
163
  request["Sec-Fetch-Mode"] = "cors"
@@ -64,8 +178,93 @@ class AlexaRemoteCtl
64
178
  http.request(request)
65
179
  end
66
180
 
181
+ end
182
+
183
+ def post_command(url, body='')
184
+ uri = URI.parse(url)
185
+ request = Net::HTTP::Post.new(uri)
186
+ request.body = body
187
+ request.content_type = "application/x-www-form-urlencoded; charset=UTF-8"
188
+ request["Origin"] = "https://" + @domain
189
+
190
+ response = make_response(uri, request)
191
+
67
192
  # response.code
68
193
  # response.body
194
+ end
195
+
196
+ def post_request(url)
197
+
198
+ uri = URI.parse(url)
199
+ request = Net::HTTP::Get.new(uri)
200
+ response = make_response(uri, request)
201
+
202
+ # response.code
203
+ # response.body
204
+
205
+ end
206
+
207
+ end
208
+
209
+ class AlexaDevices
210
+
211
+ # devices = [[{*serialno*, *type*}, label], ...]
212
+ # note: label can be any identifier you choose e.g. kitchen
213
+ #
214
+ def initialize(devicesx=[], devices: devicesx,
215
+ domain: 'alexa.amazon.co.uk', cookie: '')
216
+
217
+ @devices, @domain, @cookie = devices, domain, cookie
69
218
 
70
219
  end
220
+
221
+ def playing()
222
+
223
+ @devices.map do |device, label|
224
+ alexa = AlexaRemoteCtl.new(cookie: @cookie, device: device)
225
+ alexa.playing? ? [alexa, label] : nil
226
+ end.compact
227
+
228
+ end
229
+
230
+ def pause(id=nil)
231
+
232
+ a = playing()
233
+
234
+ if id then
235
+
236
+ alexa, _ = a.find {|_, label| label.to_sym == id.to_sym}
237
+ alexa.pause
238
+
239
+ else
240
+
241
+ a.each do |alexa, label|
242
+ puts 'Pausing @' + label.inspect
243
+ alexa.pause
244
+ end
245
+
246
+ end
247
+ end
248
+
249
+ def play(id=nil)
250
+
251
+ a = @devices
252
+
253
+ if id then
254
+
255
+ device, _ = a.find {|_, label| label.to_sym == id.to_sym}
256
+ alexa = AlexaRemoteCtl.new(cookie: @cookie, device: device)
257
+ alexa.play
258
+
259
+ else
260
+
261
+ a.each do |device, label|
262
+ puts 'Pausing @' + label.inspect
263
+ alexa = AlexaRemoteCtl.new(cookie: @cookie, device: device)
264
+ alexa.play
265
+ end
266
+
267
+ end
268
+ end
269
+
71
270
  end
data.tar.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- q#z�w��3��x��aB��D�������/������vHW筄H�.�`6�s���:� )Z��� ��VS,Cy��Kg�B����G��A?C <~#��M
2
- g����z��Kt��0���9Q���� ��I;���uO{������D}�Ԙ��U(��z$}H:%!���>]ҿ�Y����kp'��.�;�;�:MG1�O��Up�w�ޮ�5��,�B�{�jg�!�?��r�E��pbB����pO�>�~��Y�����4ԉI�Uѐ��U`�s8����+}ڨ�[�����,mVW�tf#�g-{�����r8&+��aA�4gX��Y���X�H���cm���OMV��50y됒A�ԉTk5��u]�<V
1
+ q�!O��,>�n���$�}���1t�?(��y���?��Ҥ��d]R
2
+ ���]�],�\]��v4#�K^²Ed�ϟ�LO��WT�ո{�|ݬrCRR� P���[�����,alxm�Ł�<�q���T���_
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.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -35,8 +35,28 @@ cert_chain:
35
35
  d/gEwBtUmduwWZNX2NOJehf8s1cnH9OBP7s1ziHjdkZCgkQm3QewRRcdfZeYwFi6
36
36
  4kVEcApgAgd+04ctE6uiRn5o
37
37
  -----END CERTIFICATE-----
38
- date: 2022-05-18 00:00:00.000000000 Z
39
- dependencies: []
38
+ date: 2022-05-22 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: clipboard
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.3'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 1.3.6
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '1.3'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 1.3.6
40
60
  description:
41
61
  email: digital.robertson@gmail.com
42
62
  executables: []
metadata.gz.sig CHANGED
@@ -1,5 +1,2 @@
1
- -4�[��R�
2
- \�]�^�h
3
- �9�O��P���� Y����B�R4�`�Љ�Br��פ0�Lڵ��-�=���Můf�H�'!`۫��� x���p����"�$��´�PJ����S�����^����F>���BM�b���ѩ�wy���au§�W�N��k���(���4�)�,�.��}I�����x�M�XI�� �����
4
- b�z�Y3n��]�uh
5
- &54]@^���r��N�t��"#^1��M��yHp\}����M���>�K�9Y��zT�jF��ʽ�4�
1
+ �tS��'-'9VN)�Y����>��4�����@o
2
+ 4�h��Wt�5�F� @�J��E"(�:E�wq 9��;����gC��A�{�p�%p�Ay{�{u�(�^������dǤ�+Q9j]*�Y�+Ts��=ٗ�h���ng<"�������� ���