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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/ruby-macrodroid.rb +16 -330
- data/lib/ruby-macrodroid/actions.rb +224 -39
- data/lib/ruby-macrodroid/base.rb +109 -15
- data/lib/ruby-macrodroid/constraints.rb +24 -4
- data/lib/ruby-macrodroid/macro.rb +501 -68
- data/lib/ruby-macrodroid/triggers.rb +46 -14
- metadata +10 -10
- 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: 341332647c11b1d70151aab4625ffefced825585c4814eed7d7aefaf7c96703e
|
4
|
+
data.tar.gz: ac8f26a27b1f9d394174f1d887e8af27a6c551dc55d4cffa89b8fb04f6b1927d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: debe33514bbcd6cbc508c6d6a3d647cd37861bc61168743ed15cb1f1d7cf142cd883fb6059b2b7ad901659314f1dadee8f7610dbc03074f79fc3b95c8abc2f27
|
7
|
+
data.tar.gz: 50e36ff27c737d50b0686610398feae034f21a4cfab3a15b0c6367e278305a5bdc4ed6f699c0a220f0794dcf89cd3a2ec5ae0bdaf25f0d18aa49309206c03659
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/ruby-macrodroid.rb
CHANGED
@@ -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
|
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
|
-
|
85
|
+
to_camelcase(value)
|
341
86
|
elsif value.is_a?(Array) and value.first.is_a? Hash
|
342
|
-
value.map {|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(/^
|
407
|
-
.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).
|
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
|
-
|
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(
|
53
|
-
"%s/%s: %s" % [@group, @type,
|
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(
|
147
|
+
def initialize(obj={}, macro=nil)
|
148
|
+
|
149
|
+
# puts 'obj: ' + obj[0].xml.inspect
|
144
150
|
|
145
|
-
h
|
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: {:
|
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
|
-
|
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?
|
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
|
-
|
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(
|
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(
|
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
|
-
'
|
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(
|
1409
|
+
def initialize(obj=nil)
|
1290
1410
|
|
1291
|
-
|
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: {:
|
1296
|
-
:
|
1297
|
-
:
|
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' + "\
|
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(
|
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?
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
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(
|
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,
|