ruby-macrodroid 0.8.12 → 0.9.4

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: 35ba502f49880d0b2036510866095ff532a03311c4b503099305b943ed5dd77f
4
- data.tar.gz: c604614f382e0bdf812ca7426fc74cd5339e16b821e272b3d31c85663a5f34fe
3
+ metadata.gz: 341332647c11b1d70151aab4625ffefced825585c4814eed7d7aefaf7c96703e
4
+ data.tar.gz: ac8f26a27b1f9d394174f1d887e8af27a6c551dc55d4cffa89b8fb04f6b1927d
5
5
  SHA512:
6
- metadata.gz: c36b8205504f1e76b467fe13e3e752213a0bff61e1312f507ce30ecc79904070e3004e5f82efb3e3dae9e0c22edfe5e5c7f19c421d87119ede851ab103f5d64e
7
- data.tar.gz: ab08df04436246ea37ade91f8a3509749923c1e017fb33163b591cc72f78410f3a4dcf78715669217897032362ed0a17935d4eb8858133d766a2bb712465232e
6
+ metadata.gz: debe33514bbcd6cbc508c6d6a3d647cd37861bc61168743ed15cb1f1d7cf142cd883fb6059b2b7ad901659314f1dadee8f7610dbc03074f79fc3b95c8abc2f27
7
+ data.tar.gz: 50e36ff27c737d50b0686610398feae034f21a4cfab3a15b0c6367e278305a5bdc4ed6f699c0a220f0794dcf89cd3a2ec5ae0bdaf25f0d18aa49309206c03659
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -38,269 +38,14 @@ require 'rxfhelper'
38
38
  require 'chronic_cron'
39
39
 
40
40
 
41
+ # PASTE_START
42
+
41
43
  MODEL =<<EOF
42
44
  device
43
45
  connectivity
44
46
  airplane_mode is disabled
45
47
  EOF
46
48
 
47
- class TriggersNlp
48
- include AppRoutes
49
-
50
- def initialize(macro=nil)
51
-
52
- super()
53
- params = {macro: macro}
54
- triggers(params)
55
-
56
- end
57
-
58
- def triggers(params)
59
-
60
- # e.g. at 7:30pm daily
61
- get /^(?:at )?(\d+:\d+(?:[ap]m)?) daily/i do |time, days|
62
- [TimerTrigger, {time: time,
63
- days: %w(Mon Tue Wed Thu Fri Sat Sun).join(', ')}]
64
- end
65
-
66
- get /^(?:at )?(\d+:\d+(?:[ap]m)?) (?:on )?(.*)/i do |time, days|
67
- [TimerTrigger, {time: time, days: days}]
68
- end
69
-
70
- # time.is? 'at 18:30pm on Mon or Tue'
71
- get /^time.is\? ['"](?:at )?(\d+:\d+(?:[ap]m)?) (?:on )?(.*)['"]/i do |time, days|
72
- [TimerTrigger, {time: time, days: days.gsub(' or ',', ')}]
73
- end
74
-
75
- get /^shake[ _]device\??$/i do
76
- [ShakeDeviceTrigger, {}]
77
- end
78
-
79
- get /^Flip Device (.*)$/i do |motion|
80
- facedown = motion =~ /Face Up (?:->|to) Face Down/i
81
- [FlipDeviceTrigger, {face_down: facedown }]
82
- end
83
-
84
- get /^flip_device_down\?$/i do
85
- [FlipDeviceTrigger, {face_down: true }]
86
- end
87
-
88
- get /^flip_device_up\?$/i do
89
- [FlipDeviceTrigger, {face_down: false }]
90
- end
91
-
92
- get /^Failed Login Attempt$/i do
93
- [FailedLoginTrigger, {}]
94
- end
95
-
96
- get /^failed_login?$/i do
97
- [FailedLoginTrigger, {}]
98
- end
99
-
100
- get /^Geofence (Entry|Exit) \(([^\)]+)/i do |direction, name|
101
- enter_area = direction.downcase.to_sym == :entry
102
- [GeofenceTrigger, {name: name, enter_area: enter_area}]
103
- end
104
-
105
- get /^location (entered|exited) \(([^\)]+)/i do |direction, name|
106
- enter_area = direction.downcase.to_sym == :entered
107
- [GeofenceTrigger, {name: name, enter_area: enter_area}]
108
- end
109
-
110
- # eg. Proximity Sensor (Near)
111
- #
112
- get /^Proximity Sensor \(([^\)]+)\)/i do |distance|
113
-
114
- [ProximityTrigger, {distance: distance}]
115
- end
116
-
117
- get /^WebHook \(Url\)/i do
118
- [WebHookTrigger, params]
119
- end
120
-
121
- get /^WebHook/i do
122
- [WebHookTrigger, params]
123
- end
124
-
125
- get /^wh/i do
126
- [WebHookTrigger, params]
127
- end
128
-
129
-
130
- end
131
-
132
- alias find_trigger run_route
133
-
134
- def to_s(colour: false)
135
- 'TriggersNlp ' + @h.inspect
136
- end
137
-
138
- alias to_summary to_s
139
- end
140
-
141
- class ActionsNlp
142
- include AppRoutes
143
-
144
- def initialize()
145
-
146
- super()
147
- params = {}
148
- actions(params)
149
-
150
- end
151
-
152
- def actions(params)
153
-
154
- # e.g. message popup: hello world!
155
- get /^message popup: (.*)/i do |msg|
156
- [ToastAction, {msg: msg}]
157
- end
158
-
159
- # e.g. Popup Message 'hello world!'
160
- get /^Popup[ _]Message ['"]([^'"]+)/i do |msg|
161
- [ToastAction, {msg: msg}]
162
- end
163
-
164
- # e.g. Popup Message\n hello world!
165
- get /^Popup Message\n\s+(.*)/im do |msg|
166
- [ToastAction, {msg: msg}]
167
- end
168
-
169
- # e.g. Popup Message
170
- get /^Popup Message$/i do
171
- [ToastAction, {}]
172
- end
173
-
174
- # e.g. say current time
175
- get /^say current[ _]time/i do
176
- [SayTimeAction, {}]
177
- end
178
-
179
- get /^Torch :?(.*)/i do |onoffstate|
180
- state = %w(on off toggle).index onoffstate.downcase
181
- [CameraFlashLightAction, {state: state}]
182
- end
183
-
184
- get /^Take Picture/i do
185
- [TakePictureAction, {}]
186
- end
187
-
188
- get /^take_picture/i do
189
- [TakePictureAction, {}]
190
- end
191
-
192
- # e.g. Display Notification: Hi there: This is the body of the message
193
- get /^Display Notification: ([^:]+): [^$]+$/i do |subject, text|
194
- [NotificationAction, {subject: subject, text: text}]
195
- end
196
-
197
-
198
- # e.g. Enable Wifi
199
- get /^(Enable|Disable) Wifi$/i do |raw_state|
200
-
201
- state = raw_state.downcase.to_sym == :enable ? 0 : 1
202
- [SetWifiAction, {state: state}]
203
-
204
- end
205
-
206
- # e.g. Play: Altair
207
- get /^Play: (.*)$/i do |name|
208
-
209
- [PlaySoundAction, {file_path: name}]
210
-
211
- end
212
-
213
- # e.g. Launch Settings
214
- get /^Launch (.*)$/i do |application|
215
-
216
- h = {
217
- application_name: application,
218
- package_to_launch: 'com.android.' + application.downcase
219
- }
220
- [LaunchActivityAction, h]
221
-
222
- end
223
-
224
- # e.g. HTTP GET http://someurl.com/something
225
- get /^HTTP GET ([^$]+)$/i do |url|
226
-
227
- [OpenWebPageAction, url_to_open: url]
228
-
229
- end
230
-
231
- # e.g. webhook entered_kitchen
232
- #
233
- get /webhook|HTTP GET/i do
234
- [OpenWebPageAction, {}]
235
- end
236
-
237
- #a: Keep Device Awake Screen On Until Disabled
238
- #
239
- get /Keep Device Awake Screen On Until Disabled/i do
240
- [KeepAwakeAction, {enabled: true, permanent: true, screen_option: 0}]
241
- end
242
-
243
-
244
- #a: Keep Device Awake Screen On 1h 1m 1s
245
- #
246
- get /Keep Device Awake Screen On ([^$]+)/i do |duration|
247
-
248
- a = duration.split.map(&:to_i)
249
- secs = Subunit.new(units={minutes:60, hours:60, seconds: 60}, a).to_i
250
-
251
- h = {
252
- permanent: true, screen_option: 0, seconds_to_stay_awake_for: secs
253
- }
254
- [KeepAwakeAction, h]
255
- end
256
-
257
- #a: Disable Keep Awake
258
- #
259
- get /Disable Keep Awake/i do
260
- [KeepAwakeAction, {enabled: false, screen_option: 0}]
261
- end
262
-
263
- #e.g a: if Airplane mode enabled
264
- #
265
- get /if (.*)/i do
266
- [IfConditionAction, {}]
267
- end
268
-
269
- get /End If/i do
270
- [EndIfAction, {}]
271
- end
272
-
273
- end
274
-
275
- alias find_action run_route
276
-
277
-
278
- end
279
-
280
- class ConstraintsNlp
281
- include AppRoutes
282
-
283
- def initialize()
284
-
285
- super()
286
- params = {}
287
- constraints(params)
288
-
289
- end
290
-
291
- def constraints(params)
292
-
293
- get /^airplane mode (.*)/i do |state|
294
- [AirplaneModeConstraint, {enabled: (state =~ /^enabled|on$/i) == 0}]
295
- end
296
-
297
- end
298
-
299
- alias find_constraint run_route
300
-
301
- end
302
-
303
-
304
49
  module Params
305
50
 
306
51
  refine Hash do
@@ -330,16 +75,16 @@ module Params
330
75
  end
331
76
 
332
77
  # turns keys from snake_case to CamelCase
333
- def to_camel_case(h=self)
78
+ def to_camelcase(h=self)
334
79
 
335
80
  h.inject({}) do |r,x|
336
81
 
337
82
  key, value = x
338
83
 
339
84
  val = if value.is_a?(Hash) then
340
- to_camel_case(value)
85
+ to_camelcase(value)
341
86
  elsif value.is_a?(Array) and value.first.is_a? Hash
342
- value.map {|row| to_camel_case(row)}
87
+ value.map {|row| to_camelcase(row)}
343
88
  else
344
89
  value
345
90
  end
@@ -356,8 +101,6 @@ end
356
101
 
357
102
 
358
103
 
359
-
360
-
361
104
  class MacroDroidError < Exception
362
105
  end
363
106
 
@@ -367,14 +110,14 @@ class MacroDroid
367
110
  using Params
368
111
 
369
112
  attr_reader :macros, :geofences, :yaml
370
- attr_accessor :deviceid
113
+ attr_accessor :deviceid, :remote_url
371
114
 
372
115
  # note: The deviceid can only be found from an existing Webhook trigger,
373
116
  # generated from MacroDroid itself.
374
117
 
375
- def initialize(obj=nil, deviceid: nil, debug: false)
118
+ def initialize(obj=nil, deviceid: nil, remote_url: nil, debug: false)
376
119
 
377
- @deviceid, @debug = deviceid, debug
120
+ @deviceid, @remote_url, @debug = deviceid, remote_url, debug
378
121
 
379
122
  @geofences = {}
380
123
 
@@ -403,8 +146,9 @@ class MacroDroid
403
146
  puts 'before RowX.new' if @debug
404
147
 
405
148
  s2 = s.gsub(/^g:/,'geofence:').gsub(/^m:/,'macro:')\
406
- .gsub(/^v:/,'variable:').gsub(/^t:/,'trigger:')\
407
- .gsub(/^a:/,'action:').gsub(/^c:/,'constraint:').gsub(/^#.*/,'')
149
+ .gsub(/^d:/,'description:').gsub(/^v:/,'variable:')\
150
+ .gsub(/^t:/,'trigger:').gsub(/^a:/,'action:')\
151
+ .gsub(/^c:/,'constraint:').gsub(/^#.*/,'')
408
152
 
409
153
  a = s2.split(/(?=^macro:)/)
410
154
 
@@ -424,7 +168,7 @@ class MacroDroid
424
168
 
425
169
  end
426
170
 
427
- xml = RowX.new(raw_macros).to_xml
171
+ xml = RowX.new(raw_macros, allow_lonely_keyfield: true).to_xml
428
172
  puts 'xml: ' + xml if @debug
429
173
  import_rowxml(xml)
430
174
 
@@ -499,7 +243,7 @@ class MacroDroid
499
243
  },
500
244
  macro_list: @macros.map(&:to_h)
501
245
  }
502
- @h.merge(h).to_camel_case
246
+ @h.merge(h).to_camelcase
503
247
 
504
248
  end
505
249
 
@@ -590,7 +334,7 @@ class MacroDroid
590
334
  # puts '@geofences: ' + @geofences.inspect if @debug
591
335
 
592
336
  m = Macro.new(geofences: @geofences.map(&:last), deviceid: @deviceid,
593
- debug: @debug )
337
+ remote_url: @remote_url, debug: @debug )
594
338
  m.import_h(macro)
595
339
  m
596
340
 
@@ -612,7 +356,7 @@ class MacroDroid
612
356
  @macros = doc.root.xpath('item').map do |node|
613
357
  puts ('geofences: ' + geofences.inspect).highlight if @debug
614
358
  Macro.new(geofences: geofences.map(&:last), deviceid: @deviceid,
615
- debug: @debug).import_xml(node)
359
+ remote_url: @remote_url, debug: @debug).import_xml(node)
616
360
 
617
361
  end
618
362
 
@@ -835,65 +579,7 @@ class DroidSim
835
579
 
836
580
  end
837
581
 
838
- RD_MACROS =<<EOF
839
- m: Torch
840
- t: webhook
841
- a: Torch toggle
842
- EOF
843
-
844
- module RemoteDroid
845
-
846
- class Service
847
- def initialize(callback)
848
- @callback = callback
849
- end
850
- end
851
-
852
- class Bluetooth
853
- def enable()
854
- end
855
- end
856
-
857
- class Torch < Service
858
-
859
- def toggle()
860
- @callback.call :torch
861
- end
862
-
863
- end
864
-
865
- class Control
866
-
867
- def initialize(deviceid: nil)
868
- @deviceid = deviceid
869
- @torch = Torch.new(self)
870
- end
871
-
872
- def bluetooth()
873
- @bluetooth
874
- end
875
-
876
- def call(command)
877
- url = "https://trigger.macrodroid.com/%s/%s" % [@deviceid, command]
878
- puts 'url: ' + url.inspect
879
- s = open(url).read
880
- end
881
-
882
- def torch()
883
- @torch
884
- end
885
-
886
- def write(s)
887
-
888
- MacroDroid.new(RD_MACROS, deviceid: @deviceid).export s
889
-
890
- end
891
-
892
- alias export write
893
-
894
- end
895
-
896
- end
582
+ # PASTE_END
897
583
 
898
584
  require 'ruby-macrodroid/base'
899
585
  require 'ruby-macrodroid/triggers'
@@ -34,6 +34,7 @@
34
34
 
35
35
  class Action < MacroObject
36
36
  using Params
37
+ include ObjectX
37
38
 
38
39
  attr_reader :constraints
39
40
 
@@ -49,8 +50,8 @@ class Action < MacroObject
49
50
 
50
51
  end
51
52
 
52
- def invoke(s='')
53
- "%s/%s: %s" % [@group, @type, s]
53
+ def invoke(h={})
54
+ "%s/%s: %s" % [@group, @type, h.to_json]
54
55
  end
55
56
 
56
57
 
@@ -136,26 +137,95 @@ class LaunchShortcutAction < ApplicationAction
136
137
 
137
138
  end
138
139
 
140
+ class OpenWebPageActionError < Exception
141
+ end
142
+
139
143
  # Category: Applications
140
144
  #
141
145
  class OpenWebPageAction < ApplicationAction
142
146
 
143
- def initialize(h={})
147
+ def initialize(obj={}, macro=nil)
148
+
149
+ # puts 'obj: ' + obj[0].xml.inspect
144
150
 
145
- h[:url_to_open] = h[:url] if h[:url]
151
+ h = if obj.is_a? Hash then
152
+
153
+ obj
154
+
155
+ elsif obj.is_a? Array
156
+
157
+ puts 'obj: ' + obj.inspect if $debug
158
+ e, macro = obj
159
+
160
+ a = e.xpath('item/*')
161
+
162
+ h2 = if a.any? then
163
+ a.map {|node| [node.name.to_sym, node.text.to_s]}.to_h
164
+ else
165
+ txt = e.text('item/description')
166
+ {url: (txt || e.text)}
167
+ end
168
+
169
+ h2.merge(macro: macro)
170
+
171
+ end
172
+
173
+ puts 'h:' + h.inspect if $debug
174
+
175
+ #h[:url_to_open] = h[:url] if h[:url] and h[:url].length > 1
146
176
 
147
177
  options = {
148
- variable_to_save_response: {:m_stringValue=>"", :m_name=>"", :m_decimalValue=>0.0, :isLocal=>true, :m_booleanValue=>false, :excludeFromLog=>false, :m_intValue=>0, :m_type=>2},
178
+ variable_to_save_response: {:string_value=>"", :name=>"coords",
179
+ decimal_value: 0.0, isLocal: true, m_boolean_value: false,
180
+ excludeFromLog: false, int_value: 0, type: 2},
149
181
  url_to_open: '',
150
182
  http_get: true,
151
183
  disable_url_encode: false,
152
184
  block_next_action: false
153
185
  }
186
+
187
+ return super(options.merge h) if h[:url_to_open]
188
+
189
+ if h[:macro].remote_url.nil? and (h[:url].nil? or h[:url].empty?) then
190
+ raise OpenWebPageActionError, 'remote_url not found'
191
+ end
192
+
193
+ url = if h[:url] and h[:url].length > 1 then
194
+
195
+ h[:url]
154
196
 
155
- super(options.merge filter(options,h))
197
+ elsif h2 and h[:macro].remote_url and h[:identifier]
198
+
199
+ "%s/%s" % [h[:macro].remote_url.sub(/\/$/,''), h[:identifier]]
200
+
201
+ elsif (h[:identifier].nil? or h[:identifier].empty?)
202
+
203
+ h[:url_to_open] = h[:macro].remote_url.sub(/\/$/,'') + '/' +
204
+ h[:macro].title.downcase.gsub(/ +/,'-')
205
+
206
+ end
207
+
208
+ if h2 then
209
+
210
+ h2.delete :identifier
211
+ h2.delete :url
212
+
213
+ if h2.any? then
214
+ url += '?' + \
215
+ URI.escape(h2.map {|key,value| "%s=%s" % [key, value]}.join('&'))
216
+ end
217
+
218
+ end
219
+
220
+ h[:url_to_open] = url
221
+ super(options.merge h)
156
222
 
157
223
  end
158
224
 
225
+ def invoke()
226
+ super(url: @h[:url_to_open])
227
+ end
228
+
159
229
  def to_s(colour: false, indent: 0)
160
230
  @s = "HTTP GET\nurl: " + @h[:url_to_open]
161
231
  super()
@@ -324,6 +394,7 @@ class IfConditionAction < Action
324
394
  a: true,
325
395
  constraint_list: []
326
396
  }
397
+ puts 'obj: ' + obj.inspect #if $debug
327
398
 
328
399
  if obj.is_a? Hash then
329
400
 
@@ -332,13 +403,19 @@ class IfConditionAction < Action
332
403
  h2 = options.merge(filter(options,h).merge(macro: macro))
333
404
  super(h2)
334
405
 
335
- elsif obj.is_a? Rexle::Element
336
- super()
337
- raw_txt = obj.text('item/description') || obj.text.to_s
338
- puts 'raw_txt: ' + raw_txt.inspect if $debug
406
+ elsif obj.is_a? Array
339
407
 
340
- clause = raw_txt[/^if (.*)/i,1]
408
+ e, macro = obj
409
+ super()
410
+ puts 'e.xml: ' + e.xml
411
+ puts 'e.text: ' + e.text.to_s.strip
412
+ raw_txt = e.text.to_s.strip[/^if [^$]+/i] || e.text('item/description')
413
+ puts 'raw_txt: ' + raw_txt.inspect #if $debug
414
+
415
+ clause = raw_txt[/^If (.*)/i,1]
416
+ puts 'clause: ' + clause.inspect
341
417
  conditions = clause.split(/\s+\b(?:AND|OR)\b\s+/i)
418
+ puts 'conditions: ' + conditions.inspect
342
419
 
343
420
  cp = ConstraintsNlp.new
344
421
 
@@ -351,6 +428,19 @@ class IfConditionAction < Action
351
428
 
352
429
  end
353
430
  puts '@constraints: ' + @constraints.inspect if $debug
431
+
432
+ # find any nested actions
433
+ item = e.element('item')
434
+
435
+ if item then
436
+
437
+ ap = ActionsNlp.new
438
+ obj2 = action_to_object(ap, item, item, macro)
439
+ puts 'obj2: ' + obj2.inspect
440
+ #macro.add obj2
441
+
442
+ end
443
+
354
444
  {}
355
445
  else
356
446
  # get the constraints
@@ -368,7 +458,7 @@ class IfConditionAction < Action
368
458
  def to_s(colour: false, indent: 0)
369
459
 
370
460
  h = @h.clone
371
- h.delete :macro
461
+ #h.delete :macro
372
462
  @s = 'If '
373
463
  operator = @h[:is_or_condition] ? 'OR' : 'AND'
374
464
  constraints = @constraints.map \
@@ -380,7 +470,8 @@ class IfConditionAction < Action
380
470
  out << s + constraints
381
471
  out.join("\n")
382
472
 
383
- end
473
+ end
474
+
384
475
  end
385
476
 
386
477
  class ElseAction < Action
@@ -448,6 +539,8 @@ class EndIfAction < Action
448
539
  obj
449
540
  elsif obj.is_a? Rexle::Element
450
541
  {}
542
+ else
543
+ {}
451
544
  end
452
545
 
453
546
 
@@ -455,7 +548,7 @@ class EndIfAction < Action
455
548
  constraint_list: []
456
549
  }
457
550
 
458
- super(options.merge h)
551
+ super()
459
552
 
460
553
  end
461
554
 
@@ -700,9 +793,10 @@ class SayTimeAction < DateTimeAction
700
793
  end
701
794
 
702
795
  def invoke()
703
- time = ($env and $env[:time]) ? $env[:time] : Time.now
796
+ #time = ($env and $env[:time]) ? $env[:time] : Time.now
797
+ time = Time.now
704
798
  tformat = @h['12_hour'] ? "%-I:%M%P" : "%H:%M"
705
- super(time.strftime(tformat))
799
+ super(txt: time.strftime(tformat))
706
800
  end
707
801
 
708
802
  def to_pc()
@@ -791,10 +885,18 @@ end
791
885
  #
792
886
  class SpeakTextAction < DeviceAction
793
887
 
794
- def initialize(h={})
795
-
888
+ def initialize(obj=nil)
889
+
890
+ h = if obj.is_a? Hash then
891
+ obj
892
+ elsif obj.is_a? Array
893
+ e, macro = obj
894
+ txt = e.text('item/description')
895
+ {text: (txt || e.text)}
896
+ end
897
+
796
898
  options = {
797
- text_to_say: '',
899
+ text_to_say: h[:text] || '',
798
900
  queue: false,
799
901
  read_numbers_individually: false,
800
902
  specify_audio_stream: false,
@@ -808,8 +910,13 @@ class SpeakTextAction < DeviceAction
808
910
 
809
911
  end
810
912
 
913
+ def invoke()
914
+ super(text: @h[:text_to_say])
915
+ end
916
+
811
917
  def to_s(colour: false, indent: 0)
812
- "Speak Text (%s)" % @h[:text_to_say]
918
+ @s = "Speak Text (%s)" % @h[:text_to_say]
919
+ super()
813
920
  end
814
921
 
815
922
  end
@@ -961,6 +1068,9 @@ class CameraFlashLightAction < DeviceSettingsAction
961
1068
  super(options.merge h)
962
1069
 
963
1070
  end
1071
+ def invoke()
1072
+ super(state: @h[:state])
1073
+ end
964
1074
 
965
1075
  def to_pc()
966
1076
  ['torch :on', 'torch :off', 'torch :toggle'][@h[:state]]
@@ -977,7 +1087,17 @@ end
977
1087
  class VibrateAction < DeviceSettingsAction
978
1088
 
979
1089
  def initialize(h={})
980
-
1090
+
1091
+ pattern = [
1092
+ 'Blip', 'Short Buzz', 'Long Buzz', 'Rapid', 'Slow', 'Increasing',
1093
+ 'Constant', 'Decreasing', 'Final Fantasy', 'Game Over', 'Star Wars',
1094
+ 'Mini Blip', 'Micro Blip'
1095
+ ]
1096
+
1097
+ if h[:pattern] then
1098
+ h[:vibrate_pattern] = pattern.map(&:downcase).index h[:pattern]
1099
+ end
1100
+
981
1101
  options = {
982
1102
  vibrate_pattern: 1
983
1103
  }
@@ -1265,7 +1385,7 @@ class ForceLocationUpdateAction < LocationAction
1265
1385
  end
1266
1386
 
1267
1387
  def to_s(colour: false, indent: 0)
1268
- 'ForceLocationUpdateAction ' + @h.inspect
1388
+ 'Force Location Update' #+ @h.inspect
1269
1389
  end
1270
1390
 
1271
1391
  alias to_summary to_s
@@ -1286,26 +1406,34 @@ end
1286
1406
  #
1287
1407
  class ShareLocationAction < LocationAction
1288
1408
 
1289
- def initialize(h={})
1409
+ def initialize(obj=nil)
1290
1410
 
1291
- super()
1411
+ h = if obj.is_a? Hash then
1412
+ obj
1413
+ elsif obj.is_a? Array
1414
+ e, macro = obj
1415
+ {variable: macro.set_var(e.text('item/description').to_s)}
1416
+
1417
+ end
1418
+
1419
+ #super()
1292
1420
 
1293
1421
  options = {
1294
1422
  email: '',
1295
- variable: {:m_stringValue=>"", :m_name=>"",
1296
- :m_decimalValue=>0.0, :isLocal=>true, :m_booleanValue=>false,
1297
- :excludeFromLog=>false, :m_intValue=>0, :m_type=>2},
1423
+ variable: {:string_value=>"", :name=>"",
1424
+ :decimal_value=>0.0, :is_local=>true, :boolean_value=>false,
1425
+ :exclude_from_log=>false, :int_value=>0, :type=>2},
1298
1426
  sim_id: 0,
1299
1427
  output_channel: 5,
1300
1428
  old_variable_format: true
1301
1429
  }
1302
-
1430
+ #options[:variable].merge! h
1303
1431
  super(options.merge h)
1304
1432
 
1305
1433
  end
1306
1434
 
1307
1435
  def to_s(colour: false, indent: 0)
1308
- @s = 'Share Location' + "\nGPS" # + @h.inspect
1436
+ @s = 'Share Location' + "\n" + @h[:variable][:name] # + @h.inspect
1309
1437
  super()
1310
1438
  end
1311
1439
 
@@ -1500,7 +1628,15 @@ end
1500
1628
  #
1501
1629
  class SetVariableAction < Action
1502
1630
 
1503
- def initialize(h={})
1631
+ def initialize(obj=nil)
1632
+
1633
+ h = if obj.is_a? Hash then
1634
+ obj
1635
+ elsif obj.is_a? Array
1636
+ e, macro = obj
1637
+ node = e.element('item/*')
1638
+ macro.set_var node.name, node.value.to_s
1639
+ end
1504
1640
 
1505
1641
  options = {
1506
1642
  :user_prompt=>true,
@@ -1508,9 +1644,21 @@ class SetVariableAction < Action
1508
1644
  :user_prompt_show_cancel=>true,
1509
1645
  :user_prompt_stop_after_cancel=>true,
1510
1646
  :user_prompt_title=>"Word reverse",
1511
- :name => 'word'
1647
+ :name => 'word',
1648
+ :false_label=>"False", :int_expression=>false, :int_random=>false,
1649
+ :int_random_max=>0, :int_random_min=>0, :int_value_decrement=>false,
1650
+ :int_value_increment=>false, :new_boolean_value=>false,
1651
+ :new_double_value=>0.0, :new_int_value=>0,
1652
+ :new_string_value=>"[battery]", :true_label=>"True",
1653
+ :user_prompt=>false, :user_prompt_show_cancel=>true,
1654
+ :user_prompt_stop_after_cancel=>true,
1655
+ :variable=>{
1656
+ :exclude_from_log=>false, :is_local=>true,
1657
+ :boolean_value=>false, :decimal_value=>0.0,
1658
+ :int_value=>0, :name=>"foo", :string_value=>"52", :type=>2
1659
+ }
1512
1660
  }
1513
- super(h)
1661
+ super(options.merge h)
1514
1662
 
1515
1663
  end
1516
1664
 
@@ -1971,11 +2119,10 @@ class ToastAction < NotificationsAction
1971
2119
 
1972
2120
  h = if obj.is_a? Hash then
1973
2121
  obj
1974
- elsif obj.is_a? Rexle::Element
1975
- txt = obj.text('item/description')
1976
- {msg: (txt || obj.text)}
1977
- else
1978
- {msg: obj}
2122
+ elsif obj.is_a? Array
2123
+ e, macro = obj
2124
+ txt = e.text('item/description')
2125
+ {msg: (txt || e.text)}
1979
2126
  end
1980
2127
 
1981
2128
  if h[:msg] then
@@ -1999,7 +2146,7 @@ class ToastAction < NotificationsAction
1999
2146
  end
2000
2147
 
2001
2148
  def invoke()
2002
- super(@h[:message_text])
2149
+ super(msg: @h[:message_text])
2003
2150
  end
2004
2151
 
2005
2152
  def to_pc()
@@ -2265,8 +2412,46 @@ end
2265
2412
  # disable keep awake => enabled: false
2266
2413
  #
2267
2414
  class KeepAwakeAction < ScreenAction
2415
+ using ColouredText
2268
2416
 
2269
- def initialize(h={})
2417
+ def initialize(obj=nil)
2418
+
2419
+
2420
+ h = if obj.is_a? Hash then
2421
+
2422
+ obj
2423
+
2424
+ elsif obj.is_a? Array
2425
+
2426
+ puts 'obj: ' + obj.inspect if $debug
2427
+ e, macro = obj
2428
+
2429
+ a = e.xpath('item/*')
2430
+
2431
+ txt = e.text('item/description')
2432
+
2433
+ h2 = if txt then
2434
+
2435
+ raw_duration = (txt || e.text).to_s
2436
+ puts 'raw_duration: ' + raw_duration.inspect
2437
+ duration = raw_duration[/Screen On - ([^$]+)/i]
2438
+ {duration: duration}
2439
+
2440
+ elsif a.any? then
2441
+ a.map {|node| [node.name.to_sym, node.text.to_s]}.to_h
2442
+ end
2443
+
2444
+ h2.merge(macro: macro)
2445
+
2446
+ end
2447
+
2448
+ puts ('h: ' + h.inspect).debug #if $debug
2449
+
2450
+ if h[:duration] then
2451
+
2452
+ h[:seconds_to_stay_awake_for] = Subunit.hms_to_seconds(h[:duration])
2453
+
2454
+ end
2270
2455
 
2271
2456
  options = {
2272
2457
  enabled: true,