ruby-macrodroid 0.8.9 → 0.9.1
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 +28 -758
- data/lib/ruby-macrodroid/actions.rb +142 -34
- data/lib/ruby-macrodroid/constraints.rb +1338 -0
- data/lib/ruby-macrodroid/macro.rb +630 -0
- data/lib/ruby-macrodroid/triggers.rb +42 -9
- metadata +12 -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: 37e8014bb2ccd71ffd2da90197a1dd1a89c7e8e6bbbfc7ed88e9cfbff07925a1
|
4
|
+
data.tar.gz: f2d4910bb6893249e33eb7c4326ea733188ecef67ec94f808cd25ef6c97760d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06015fe764a0450838ad49b6dbebba46afc32ec49673dbf4e1bce9b07e04aaea1850153cf2c0b1d56e740dd2cbcf4653f92878ee99680d7c3f2eaacf1fffb69e
|
7
|
+
data.tar.gz: df0c2950bcae690d137b294825c95579f8530fea24cabfe371809efff64343d4e9ffd71b5f2378c7938bc214dfc0e409892947ad03a86ef4438816fafa11000a
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/ruby-macrodroid.rb
CHANGED
@@ -7,12 +7,7 @@
|
|
7
7
|
# ## Nlp classes
|
8
8
|
#
|
9
9
|
# TriggersNlp ActionsNlp ConstraintsNlp
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# ## Macro class
|
13
|
-
#
|
14
|
-
# Macro
|
15
|
-
#
|
10
|
+
#
|
16
11
|
#
|
17
12
|
# ## Error class
|
18
13
|
#
|
@@ -31,11 +26,12 @@
|
|
31
26
|
#
|
32
27
|
|
33
28
|
|
29
|
+
|
34
30
|
require 'yaml'
|
35
31
|
require 'rowx'
|
36
32
|
require 'uuid'
|
37
|
-
require 'glw'
|
38
|
-
require 'geozone'
|
33
|
+
#require 'glw'
|
34
|
+
#require 'geozone'
|
39
35
|
require 'geocoder'
|
40
36
|
require 'subunit'
|
41
37
|
require 'rxfhelper'
|
@@ -48,248 +44,6 @@ device
|
|
48
44
|
airplane_mode is disabled
|
49
45
|
EOF
|
50
46
|
|
51
|
-
class TriggersNlp
|
52
|
-
include AppRoutes
|
53
|
-
|
54
|
-
def initialize()
|
55
|
-
|
56
|
-
super()
|
57
|
-
params = {}
|
58
|
-
triggers(params)
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
def triggers(params)
|
63
|
-
|
64
|
-
# e.g. at 7:30pm daily
|
65
|
-
get /^(?:at )?(\d+:\d+(?:[ap]m)?) daily/i do |time, days|
|
66
|
-
[TimerTrigger, {time: time,
|
67
|
-
days: %w(Mon Tue Wed Thu Fri Sat Sun).join(', ')}]
|
68
|
-
end
|
69
|
-
|
70
|
-
get /^(?:at )?(\d+:\d+(?:[ap]m)?) (?:on )?(.*)/i do |time, days|
|
71
|
-
[TimerTrigger, {time: time, days: days}]
|
72
|
-
end
|
73
|
-
|
74
|
-
# time.is? 'at 18:30pm on Mon or Tue'
|
75
|
-
get /^time.is\? ['"](?:at )?(\d+:\d+(?:[ap]m)?) (?:on )?(.*)['"]/i do |time, days|
|
76
|
-
[TimerTrigger, {time: time, days: days.gsub(' or ',', ')}]
|
77
|
-
end
|
78
|
-
|
79
|
-
get /^shake[ _]device\??$/i do
|
80
|
-
[ShakeDeviceTrigger, {}]
|
81
|
-
end
|
82
|
-
|
83
|
-
get /^Flip Device (.*)$/i do |motion|
|
84
|
-
facedown = motion =~ /Face Up (?:->|to) Face Down/i
|
85
|
-
[FlipDeviceTrigger, {face_down: facedown }]
|
86
|
-
end
|
87
|
-
|
88
|
-
get /^flip_device_down\?$/i do
|
89
|
-
[FlipDeviceTrigger, {face_down: true }]
|
90
|
-
end
|
91
|
-
|
92
|
-
get /^flip_device_up\?$/i do
|
93
|
-
[FlipDeviceTrigger, {face_down: false }]
|
94
|
-
end
|
95
|
-
|
96
|
-
get /^Failed Login Attempt$/i do
|
97
|
-
[FailedLoginTrigger, {}]
|
98
|
-
end
|
99
|
-
|
100
|
-
get /^failed_login?$/i do
|
101
|
-
[FailedLoginTrigger, {}]
|
102
|
-
end
|
103
|
-
|
104
|
-
get /^Geofence (Entry|Exit) \(([^\)]+)/i do |direction, name|
|
105
|
-
enter_area = direction.downcase.to_sym == :entry
|
106
|
-
[GeofenceTrigger, {name: name, enter_area: enter_area}]
|
107
|
-
end
|
108
|
-
|
109
|
-
get /^location (entered|exited) \(([^\)]+)/i do |direction, name|
|
110
|
-
enter_area = direction.downcase.to_sym == :entered
|
111
|
-
[GeofenceTrigger, {name: name, enter_area: enter_area}]
|
112
|
-
end
|
113
|
-
|
114
|
-
# eg. Proximity Sensor (Near)
|
115
|
-
#
|
116
|
-
get /^Proximity Sensor \(([^\)]+)\)/i do |distance|
|
117
|
-
|
118
|
-
[ProximityTrigger, {distance: distance}]
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
alias find_trigger run_route
|
126
|
-
|
127
|
-
def to_s(colour: false)
|
128
|
-
'TriggersNlp ' + @h.inspect
|
129
|
-
end
|
130
|
-
|
131
|
-
alias to_summary to_s
|
132
|
-
end
|
133
|
-
|
134
|
-
class ActionsNlp
|
135
|
-
include AppRoutes
|
136
|
-
|
137
|
-
def initialize()
|
138
|
-
|
139
|
-
super()
|
140
|
-
params = {}
|
141
|
-
actions(params)
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
def actions(params)
|
146
|
-
|
147
|
-
# e.g. message popup: hello world!
|
148
|
-
get /^message popup: (.*)/i do |msg|
|
149
|
-
[ToastAction, {msg: msg}]
|
150
|
-
end
|
151
|
-
|
152
|
-
# e.g. Popup Message 'hello world!'
|
153
|
-
get /^Popup[ _]Message ['"]([^'"]+)/i do |msg|
|
154
|
-
[ToastAction, {msg: msg}]
|
155
|
-
end
|
156
|
-
|
157
|
-
# e.g. Popup Message\n hello world!
|
158
|
-
get /^Popup Message\n\s+(.*)/im do |msg|
|
159
|
-
[ToastAction, {msg: msg}]
|
160
|
-
end
|
161
|
-
|
162
|
-
# e.g. Popup Message
|
163
|
-
get /^Popup Message$/i do
|
164
|
-
[ToastAction, {}]
|
165
|
-
end
|
166
|
-
|
167
|
-
# e.g. say current time
|
168
|
-
get /^say current[ _]time/i do
|
169
|
-
[SayTimeAction, {}]
|
170
|
-
end
|
171
|
-
|
172
|
-
get /^Torch :?(.*)/i do |onoffstate|
|
173
|
-
state = onoffstate.downcase == 'on' ? 0 : 1
|
174
|
-
[CameraFlashLightAction, {state: state}]
|
175
|
-
end
|
176
|
-
|
177
|
-
get /^Take Picture/i do
|
178
|
-
[TakePictureAction, {}]
|
179
|
-
end
|
180
|
-
|
181
|
-
get /^take_picture/i do
|
182
|
-
[TakePictureAction, {}]
|
183
|
-
end
|
184
|
-
|
185
|
-
# e.g. Display Notification: Hi there: This is the body of the message
|
186
|
-
get /^Display Notification: ([^:]+): [^$]+$/i do |subject, text|
|
187
|
-
[NotificationAction, {subject: subject, text: text}]
|
188
|
-
end
|
189
|
-
|
190
|
-
|
191
|
-
# e.g. Enable Wifi
|
192
|
-
get /^(Enable|Disable) Wifi$/i do |raw_state|
|
193
|
-
|
194
|
-
state = raw_state.downcase.to_sym == :enable ? 0 : 1
|
195
|
-
[SetWifiAction, {state: state}]
|
196
|
-
|
197
|
-
end
|
198
|
-
|
199
|
-
# e.g. Play: Altair
|
200
|
-
get /^Play: (.*)$/i do |name|
|
201
|
-
|
202
|
-
[PlaySoundAction, {file_path: name}]
|
203
|
-
|
204
|
-
end
|
205
|
-
|
206
|
-
# e.g. Launch Settings
|
207
|
-
get /^Launch (.*)$/i do |application|
|
208
|
-
|
209
|
-
h = {
|
210
|
-
application_name: application,
|
211
|
-
package_to_launch: 'com.android.' + application.downcase
|
212
|
-
}
|
213
|
-
[LaunchActivityAction, h]
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
|
-
# e.g. HTTP GET http://someurl.com/something
|
218
|
-
get /^HTTP GET ([^$]+)$/i do |url|
|
219
|
-
|
220
|
-
[OpenWebPageAction, url_to_open: url]
|
221
|
-
|
222
|
-
end
|
223
|
-
|
224
|
-
# e.g. webhook entered_kitchen
|
225
|
-
#
|
226
|
-
get /webhook|HTTP GET/i do
|
227
|
-
[OpenWebPageAction, {}]
|
228
|
-
end
|
229
|
-
|
230
|
-
#a: Keep Device Awake Screen On Until Disabled
|
231
|
-
#
|
232
|
-
get /Keep Device Awake Screen On Until Disabled/i do
|
233
|
-
[KeepAwakeAction, {enabled: true, permanent: true, screen_option: 0}]
|
234
|
-
end
|
235
|
-
|
236
|
-
|
237
|
-
#a: Keep Device Awake Screen On 1h 1m 1s
|
238
|
-
#
|
239
|
-
get /Keep Device Awake Screen On ([^$]+)/i do |duration|
|
240
|
-
|
241
|
-
a = duration.split.map(&:to_i)
|
242
|
-
secs = Subunit.new(units={minutes:60, hours:60, seconds: 60}, a).to_i
|
243
|
-
|
244
|
-
h = {
|
245
|
-
permanent: true, screen_option: 0, seconds_to_stay_awake_for: secs
|
246
|
-
}
|
247
|
-
[KeepAwakeAction, h]
|
248
|
-
end
|
249
|
-
|
250
|
-
#a: Disable Keep Awake
|
251
|
-
#
|
252
|
-
get /Disable Keep Awake/i do
|
253
|
-
[KeepAwakeAction, {enabled: false, screen_option: 0}]
|
254
|
-
end
|
255
|
-
|
256
|
-
#a: Disable Keep Awake
|
257
|
-
#
|
258
|
-
get /if (.*)/i do
|
259
|
-
[IfConditionAction, {}]
|
260
|
-
end
|
261
|
-
|
262
|
-
end
|
263
|
-
|
264
|
-
alias find_action run_route
|
265
|
-
|
266
|
-
|
267
|
-
end
|
268
|
-
|
269
|
-
class ConstraintsNlp
|
270
|
-
include AppRoutes
|
271
|
-
|
272
|
-
def initialize()
|
273
|
-
|
274
|
-
super()
|
275
|
-
params = {}
|
276
|
-
constraints(params)
|
277
|
-
|
278
|
-
end
|
279
|
-
|
280
|
-
def constraints(params)
|
281
|
-
|
282
|
-
get /^airplane mode (.*)/i do |state|
|
283
|
-
[AirplaneModeConstraint, {enabled: (state =~ /^enabled|on$/) == 0}]
|
284
|
-
end
|
285
|
-
|
286
|
-
end
|
287
|
-
|
288
|
-
alias find_constraint run_route
|
289
|
-
|
290
|
-
end
|
291
|
-
|
292
|
-
|
293
47
|
module Params
|
294
48
|
|
295
49
|
refine Hash do
|
@@ -345,518 +99,23 @@ end
|
|
345
99
|
|
346
100
|
|
347
101
|
|
348
|
-
class Macro
|
349
|
-
using ColouredText
|
350
|
-
using Params
|
351
|
-
|
352
|
-
attr_reader :local_variables, :triggers, :actions, :constraints,
|
353
|
-
:guid, :deviceid
|
354
|
-
attr_accessor :title, :description
|
355
|
-
|
356
|
-
def initialize(name=nil, geofences: nil, deviceid: nil, debug: false)
|
357
|
-
|
358
|
-
@title, @geofences, @deviceid, @debug = name, geofences, deviceid, debug
|
359
|
-
|
360
|
-
puts 'inside Macro#initialize' if @debug
|
361
|
-
|
362
|
-
@local_variables, @triggers, @actions, @constraints = [], [], [], []
|
363
|
-
@h = {}
|
364
|
-
|
365
|
-
end
|
366
|
-
|
367
|
-
def add(obj)
|
368
|
-
|
369
|
-
if obj.kind_of? Trigger then
|
370
|
-
|
371
|
-
puts 'trigger found' if @debug
|
372
|
-
@triggers << obj
|
373
|
-
|
374
|
-
elsif obj.kind_of? Action
|
375
|
-
|
376
|
-
puts 'action found' if @debug
|
377
|
-
@actions << obj
|
378
|
-
|
379
|
-
elsif obj.kind_of? Constraint
|
380
|
-
|
381
|
-
puts 'constraint found' if @debug
|
382
|
-
@constraints << obj
|
383
|
-
|
384
|
-
end
|
385
|
-
|
386
|
-
end
|
387
|
-
|
388
|
-
def to_h()
|
389
|
-
|
390
|
-
h = {
|
391
|
-
local_variables: @local_variables,
|
392
|
-
m_trigger_list: @triggers.map(&:to_h),
|
393
|
-
m_action_list: @actions.map(&:to_h),
|
394
|
-
m_category: @category,
|
395
|
-
m_constraint_list: @constraints.map(&:to_h),
|
396
|
-
m_description: '',
|
397
|
-
m_name: title(),
|
398
|
-
m_excludeLog: false,
|
399
|
-
m_GUID: guid(),
|
400
|
-
m_isOrCondition: false,
|
401
|
-
m_enabled: false,
|
402
|
-
m_descriptionOpen: false,
|
403
|
-
m_headingColor: 0
|
404
|
-
}
|
405
|
-
|
406
|
-
puts 'h: ' + h.inspect if @debug
|
407
|
-
|
408
|
-
@h.merge(h)
|
409
|
-
end
|
410
|
-
|
411
|
-
def import_h(h)
|
412
|
-
|
413
|
-
if @debug then
|
414
|
-
puts 'inside import_h'
|
415
|
-
puts 'h:' + h.inspect
|
416
|
-
end
|
417
|
-
|
418
|
-
@category = h[:category]
|
419
|
-
@title = h[:name]
|
420
|
-
@description = h[:description]
|
421
|
-
|
422
|
-
# fetch the local variables
|
423
|
-
if h[:local_variables].any? and h[:local_variables].first.any? then
|
424
|
-
|
425
|
-
@local_variables = h[:local_variables].map do |var|
|
426
|
-
|
427
|
-
val = case var[:type]
|
428
|
-
when 0 # boolean
|
429
|
-
var[:boolean_value]
|
430
|
-
when 1 # integer
|
431
|
-
var[:int_value]
|
432
|
-
when 2 # string
|
433
|
-
var[:string_value]
|
434
|
-
when 3 # decimal
|
435
|
-
var[:decimal_Value]
|
436
|
-
end
|
437
|
-
|
438
|
-
[var[:name], val]
|
439
|
-
|
440
|
-
end.to_h
|
441
|
-
end
|
442
|
-
|
443
|
-
# fetch the triggers
|
444
|
-
@triggers = h[:trigger_list].map do |trigger|
|
445
|
-
puts 'trigger: ' + trigger.inspect
|
446
|
-
#exit
|
447
|
-
object(trigger.to_snake_case)
|
448
|
-
|
449
|
-
end
|
450
|
-
|
451
|
-
@actions = h[:action_list].map do |action|
|
452
|
-
object(action.to_snake_case)
|
453
|
-
end
|
454
|
-
puts 'before fetch constraints' if @debug
|
455
|
-
# fetch the constraints
|
456
|
-
@constraints = h[:constraint_list].map do |constraint|
|
457
|
-
object(constraint.to_snake_case)
|
458
|
-
end
|
459
|
-
puts 'after fetch constraints' if @debug
|
460
|
-
@h = h
|
461
|
-
|
462
|
-
%i(local_variables m_trigger_list m_action_list m_constraint_list)\
|
463
|
-
.each {|x| @h[x] = [] }
|
464
|
-
puts 'after @h set' if @debug
|
465
|
-
@h
|
466
|
-
|
467
|
-
end
|
468
|
-
|
469
|
-
def import_xml(node)
|
470
|
-
|
471
|
-
if @debug then
|
472
|
-
puts 'inside Macro#import_xml'
|
473
|
-
puts 'node: ' + node.xml.inspect
|
474
|
-
end
|
475
|
-
|
476
|
-
if node.element('triggers') then
|
477
|
-
|
478
|
-
# level 2
|
479
|
-
|
480
|
-
@title = node.attributes[:name]
|
481
|
-
@category = node.attributes[:category]
|
482
|
-
@description = node.attributes[:description]
|
483
|
-
|
484
|
-
|
485
|
-
# get all the triggers
|
486
|
-
@triggers = node.xpath('triggers/*').map do |e|
|
487
|
-
|
488
|
-
puts 'e.name: ' + e.name.inspect if @debug
|
489
|
-
{timer: TimerTrigger}[e.name.to_sym].new(e.attributes.to_h)
|
490
|
-
|
491
|
-
end
|
492
|
-
|
493
|
-
# get all the actions
|
494
|
-
@actions = node.xpath('actions/*').map do |e|
|
495
|
-
|
496
|
-
if e.name == 'notification' then
|
497
|
-
|
498
|
-
case e.attributes[:type].to_sym
|
499
|
-
when :popup
|
500
|
-
e.attributes.delete :type
|
501
|
-
ToastAction.new e.attributes.to_h
|
502
|
-
end
|
503
|
-
|
504
|
-
end
|
505
|
-
|
506
|
-
end
|
507
|
-
|
508
|
-
# get all the constraints
|
509
|
-
@constraints = node.xpath('constraints/*').map do |e|
|
510
|
-
|
511
|
-
puts 'e.name: ' + e.name.inspect if @debug
|
512
|
-
{airplanemode: AirplaneModeConstraint}[e.name.to_sym].new(e.attributes.to_h)
|
513
|
-
|
514
|
-
end
|
515
|
-
|
516
|
-
else
|
517
|
-
|
518
|
-
# Level 1
|
519
|
-
|
520
|
-
puts 'import_xml: inside level 1' if @debug
|
521
|
-
|
522
|
-
@title = node.text('macro') || node.attributes[:name]
|
523
|
-
|
524
|
-
#@description = node.attributes[:description]
|
525
|
-
|
526
|
-
tp = TriggersNlp.new
|
527
|
-
|
528
|
-
@triggers = node.xpath('trigger').map do |e|
|
529
|
-
|
530
|
-
r = tp.find_trigger e.text
|
531
|
-
|
532
|
-
puts 'found trigger ' + r.inspect if @debug
|
533
|
-
|
534
|
-
if r then
|
535
|
-
if r[0] == GeofenceTrigger then
|
536
|
-
GeofenceTrigger.new(r[1], geofences: @geofences)
|
537
|
-
else
|
538
|
-
r[0].new(r[1])
|
539
|
-
end
|
540
|
-
end
|
541
|
-
|
542
|
-
end
|
543
|
-
|
544
|
-
ap = ActionsNlp.new
|
545
|
-
|
546
|
-
@actions = node.xpath('action').map do |e|
|
547
|
-
|
548
|
-
puts 'action e: ' + e.xml.inspect if @debug
|
549
|
-
puts 'e.text ' + e.text if @debug
|
550
|
-
|
551
|
-
inner_lines = e.xpath('item/description/text()')
|
552
|
-
|
553
|
-
action = if e.text.to_s.strip.empty? then
|
554
|
-
inner_lines.shift.strip
|
555
|
-
else
|
556
|
-
e.text.strip
|
557
|
-
end
|
558
|
-
|
559
|
-
r = ap.find_action action
|
560
|
-
puts 'found action ' + r.inspect if @debug
|
561
|
-
|
562
|
-
if r then
|
563
|
-
|
564
|
-
loose = inner_lines.shift
|
565
|
-
|
566
|
-
raw_attributes = if loose then
|
567
|
-
|
568
|
-
puts 'do something ' + loose.to_s if @debug
|
569
|
-
loose.to_s
|
570
|
-
|
571
|
-
else
|
572
|
-
|
573
|
-
a = e.xpath('item/*')
|
574
|
-
|
575
|
-
h = if a.any? then
|
576
|
-
a.map {|node| [node.name.to_sym, node.text.to_s]}.to_h
|
577
|
-
else
|
578
|
-
{}
|
579
|
-
end
|
580
|
-
|
581
|
-
r[1].merge(h)
|
582
|
-
|
583
|
-
end
|
584
|
-
r[0].new(raw_attributes)
|
585
|
-
end
|
586
|
-
|
587
|
-
end
|
588
|
-
|
589
|
-
cp = ConstraintsNlp.new
|
590
|
-
|
591
|
-
@constraints = node.xpath('constraint').map do |e|
|
592
|
-
|
593
|
-
r = cp.find_constraint e.text
|
594
|
-
puts 'found constraint ' + r.inspect if @debug
|
595
|
-
|
596
|
-
if r then
|
597
|
-
r[0].new(r[1])
|
598
|
-
end
|
599
|
-
|
600
|
-
end
|
601
|
-
|
602
|
-
end
|
603
|
-
|
604
|
-
self
|
605
|
-
|
606
|
-
end
|
607
|
-
|
608
|
-
def match?(triggerx, detail={time: $env[:time]}, model=nil )
|
609
|
-
|
610
|
-
if @triggers.any? {|x| x.type == triggerx and x.match?(detail, model) } then
|
611
|
-
|
612
|
-
if @debug then
|
613
|
-
puts 'checking constraints ...'
|
614
|
-
puts '@constraints: ' + @constraints.inspect
|
615
|
-
end
|
616
|
-
|
617
|
-
if @constraints.all? {|x| x.match?($env.merge(detail), model) } then
|
618
|
-
|
619
|
-
true
|
620
|
-
|
621
|
-
else
|
622
|
-
|
623
|
-
return false
|
624
|
-
|
625
|
-
end
|
626
|
-
|
627
|
-
end
|
628
|
-
|
629
|
-
end
|
630
|
-
|
631
|
-
# invokes the actions
|
632
|
-
#
|
633
|
-
def run()
|
634
|
-
@actions.map(&:invoke)
|
635
|
-
end
|
636
|
-
|
637
|
-
# prepares the environment in order for triggers to test fire successfully
|
638
|
-
# Used for testing
|
639
|
-
#
|
640
|
-
def set_env()
|
641
|
-
@triggers.each(&:set_env)
|
642
|
-
end
|
643
|
-
|
644
|
-
def to_pc()
|
645
|
-
|
646
|
-
heading = '# ' + @title
|
647
|
-
heading += '\n# ' + @description if @description
|
648
|
-
condition = @triggers.first.to_pc
|
649
|
-
actions = @actions.map(&:to_pc).join("\n")
|
650
|
-
|
651
|
-
<<EOF
|
652
|
-
#{heading}
|
653
|
-
|
654
|
-
if #{condition} then
|
655
|
-
#{actions}
|
656
|
-
end
|
657
|
-
EOF
|
658
|
-
end
|
659
|
-
|
660
|
-
def to_s(colour: false)
|
661
|
-
|
662
|
-
indent = 0 #@actions.map(&:to_s).join.lines.length > 0 ? 1 : 0
|
663
|
-
|
664
|
-
a = []
|
665
|
-
a << '# ' + @category + "\n" if @category
|
666
|
-
a << (colour ? "m".bg_cyan.gray.bold : 'm') + ': ' + @title
|
667
|
-
|
668
|
-
|
669
|
-
if @description and @description.length >= 1 then
|
670
|
-
a << (colour ? "d".bg_gray.gray.bold : 'd') + ': ' \
|
671
|
-
+ @description.gsub(/\n/,"\n ")
|
672
|
-
end
|
673
|
-
|
674
|
-
if @local_variables.length >= 1 then
|
675
|
-
|
676
|
-
vars = @local_variables.map do |k,v|
|
677
|
-
label = colour ? 'v'.bg_magenta : 'v'
|
678
|
-
label += ': '
|
679
|
-
label + "%s: %s" % [k,v]
|
680
|
-
end
|
681
|
-
|
682
|
-
a << vars.join("\n")
|
683
|
-
end
|
684
|
-
|
685
|
-
a << @triggers.map do |x|
|
686
|
-
s =-x.to_s(colour: colour)
|
687
|
-
|
688
|
-
s2 = if s.lines.length > 1 then
|
689
|
-
"\n" + s.lines.map {|x| x.prepend (' ' * (indent+1)) }.join
|
690
|
-
else
|
691
|
-
' ' + s
|
692
|
-
end
|
693
|
-
#s.lines > 1 ? "\n" + x : x
|
694
|
-
(colour ? "t".bg_red.gray.bold : 't') + ":" + s2
|
695
|
-
end.join("\n")
|
696
|
-
|
697
|
-
actions = @actions.map do |x|
|
698
|
-
|
699
|
-
|
700
|
-
s = x.to_s(colour: colour)
|
701
|
-
#puts 's: ' + s.inspect
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
r = if indent <= 0 then
|
706
|
-
|
707
|
-
lines = s.lines
|
708
|
-
|
709
|
-
if lines.length > 1 then
|
710
|
-
s = lines.map {|x| x.prepend (' ' * (indent+1)) }.join
|
711
|
-
end
|
712
|
-
|
713
|
-
s2 = s.lines.length > 1 ? "\n" + s : ' ' + s
|
714
|
-
|
715
|
-
if colour then
|
716
|
-
"a".bg_blue.gray.bold + ":" + s2
|
717
|
-
else
|
718
|
-
"a:" + s2
|
719
|
-
end
|
720
|
-
|
721
|
-
elsif indent > 0
|
722
|
-
|
723
|
-
if s =~ /^Else/ then
|
724
|
-
(' ' * (indent-1)) + "%s" % s
|
725
|
-
elsif s =~ /^End/
|
726
|
-
indent -= 1
|
727
|
-
(' ' * indent) + "%s" % s
|
728
|
-
else
|
729
|
-
s2 = s.lines[0] + s.lines[1..-1].map {|x| (' ' * indent) + x }.join
|
730
|
-
(' ' * indent) + "%s" % s2
|
731
|
-
end
|
732
|
-
|
733
|
-
end
|
734
|
-
|
735
|
-
if s =~ /^(?:If|DO \/ WHILE)/i then
|
736
|
-
|
737
|
-
if indent < 1 then
|
738
|
-
|
739
|
-
r = if colour then
|
740
|
-
"a".bg_blue.gray.bold + ":\n %s" % s
|
741
|
-
else
|
742
|
-
"a:\n %s" % s
|
743
|
-
end
|
744
|
-
|
745
|
-
indent += 1
|
746
|
-
else
|
747
|
-
r = (' ' * indent) + "%s" % s
|
748
|
-
end
|
749
|
-
|
750
|
-
indent += 1
|
751
|
-
end
|
752
|
-
|
753
|
-
r
|
754
|
-
|
755
|
-
end.join("\n")
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
a << actions
|
761
|
-
|
762
|
-
|
763
|
-
if @constraints.any? then
|
764
|
-
a << @constraints.map do |x|
|
765
|
-
(colour ? "c".bg_green.gray.bold : 'c') + ": %s" % x
|
766
|
-
end.join("\n")
|
767
|
-
end
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
a.join("\n") + "\n"
|
774
|
-
|
775
|
-
end
|
776
|
-
|
777
|
-
def to_summary(colour: false)
|
778
|
-
|
779
|
-
if colour then
|
780
|
-
|
781
|
-
a = [
|
782
|
-
'm'.bg_cyan.gray.bold + ': ' + @title,
|
783
|
-
't'.bg_red.gray.bold + ': ' + @triggers.map \
|
784
|
-
{|x| x.to_summary(colour: false)}.join(", "),
|
785
|
-
'a'.bg_blue.gray.bold + ': ' + @actions.map \
|
786
|
-
{|x| x.to_summary(colour: false)}.join(", ")
|
787
|
-
]
|
788
|
-
|
789
|
-
if @constraints.any? then
|
790
|
-
a << 'c'.bg_green.gray.bold + ': ' + @constraints.map \
|
791
|
-
{|x| x.to_summary(colour: false)}.join(", ")
|
792
|
-
end
|
793
|
-
|
794
|
-
else
|
795
|
-
|
796
|
-
a = [
|
797
|
-
'm: ' + @title,
|
798
|
-
't: ' + @triggers.map {|x| x.to_summary(colour: false)}.join(", "),
|
799
|
-
'a: ' + @actions.map {|x| x.to_summary(colour: false)}.join(", ")
|
800
|
-
]
|
801
|
-
|
802
|
-
if @constraints.any? then
|
803
|
-
a << 'c: ' + @constraints.map \
|
804
|
-
{|x| x.to_summary(colour: false)}.join(", ")
|
805
|
-
end
|
806
|
-
end
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
a.join("\n") + "\n"
|
811
|
-
|
812
|
-
end
|
813
|
-
|
814
|
-
private
|
815
|
-
|
816
|
-
def guid()
|
817
|
-
'-' + rand(1..9).to_s + 18.times.map { rand 9 }.join
|
818
|
-
end
|
819
|
-
|
820
|
-
def object(h={})
|
821
|
-
|
822
|
-
puts ('inside object h:' + h.inspect).debug if @debug
|
823
|
-
klass = Object.const_get h[:class_type]
|
824
|
-
puts klass.inspect.highlight if $debug
|
825
|
-
|
826
|
-
if klass == GeofenceTrigger then
|
827
|
-
puts 'GeofenceTrigger found'.highlight if $debug
|
828
|
-
GeofenceTrigger.new(h, geofences: @geofences)
|
829
|
-
else
|
830
|
-
puts 'before klass'
|
831
|
-
h2 = h.merge( macro: self)
|
832
|
-
puts 'h2: ' + h2.inspect
|
833
|
-
r = klass.new h2
|
834
|
-
puts 'r:' + r.inspect
|
835
|
-
r
|
836
|
-
|
837
|
-
end
|
838
|
-
|
839
|
-
end
|
840
|
-
|
841
|
-
end
|
842
|
-
|
843
|
-
|
844
102
|
class MacroDroidError < Exception
|
845
103
|
end
|
846
104
|
|
847
105
|
class MacroDroid
|
106
|
+
include RXFHelperModule
|
848
107
|
using ColouredText
|
849
108
|
using Params
|
850
109
|
|
851
110
|
attr_reader :macros, :geofences, :yaml
|
852
|
-
attr_accessor :deviceid
|
111
|
+
attr_accessor :deviceid, :remote_url
|
853
112
|
|
854
113
|
# note: The deviceid can only be found from an existing Webhook trigger,
|
855
114
|
# generated from MacroDroid itself.
|
856
115
|
|
857
|
-
def initialize(obj=nil, deviceid: nil, debug: false)
|
116
|
+
def initialize(obj=nil, deviceid: nil, remote_url: nil, debug: false)
|
858
117
|
|
859
|
-
@deviceid, @debug = deviceid, debug
|
118
|
+
@deviceid, @remote_url, @debug = deviceid, remote_url, debug
|
860
119
|
|
861
120
|
@geofences = {}
|
862
121
|
|
@@ -885,10 +144,16 @@ class MacroDroid
|
|
885
144
|
puts 'before RowX.new' if @debug
|
886
145
|
|
887
146
|
s2 = s.gsub(/^g:/,'geofence:').gsub(/^m:/,'macro:')\
|
888
|
-
.gsub(/^
|
889
|
-
.gsub(/^c:/,'constraint:').gsub(/^#.*/,'')
|
147
|
+
.gsub(/^v:/,'variable:').gsub(/^t:/,'trigger:')\
|
148
|
+
.gsub(/^a:/,'action:').gsub(/^c:/,'constraint:').gsub(/^#.*/,'')
|
149
|
+
|
150
|
+
a = s2.split(/(?=^macro:)/)
|
890
151
|
|
891
|
-
|
152
|
+
raw_geofences = a.shift if a.first =~ /^geofence/
|
153
|
+
raw_macros = a.join
|
154
|
+
#raw_macros, raw_geofences .reverse
|
155
|
+
|
156
|
+
puts 'raw_macros: ' + raw_macros.inspect if @debug
|
892
157
|
|
893
158
|
if raw_geofences then
|
894
159
|
|
@@ -901,6 +166,7 @@ class MacroDroid
|
|
901
166
|
end
|
902
167
|
|
903
168
|
xml = RowX.new(raw_macros).to_xml
|
169
|
+
puts 'xml: ' + xml if @debug
|
904
170
|
import_rowxml(xml)
|
905
171
|
|
906
172
|
elsif s =~ /^# /
|
@@ -954,14 +220,16 @@ class MacroDroid
|
|
954
220
|
|
955
221
|
}
|
956
222
|
end
|
223
|
+
|
224
|
+
def export(filepath)
|
225
|
+
FileX.write filepath, to_json
|
226
|
+
end
|
957
227
|
|
958
|
-
def
|
228
|
+
def to_json()
|
959
229
|
|
960
230
|
to_h.to_json
|
961
231
|
|
962
232
|
end
|
963
|
-
|
964
|
-
alias to_json export_json
|
965
233
|
|
966
234
|
|
967
235
|
def to_h()
|
@@ -1063,7 +331,7 @@ class MacroDroid
|
|
1063
331
|
# puts '@geofences: ' + @geofences.inspect if @debug
|
1064
332
|
|
1065
333
|
m = Macro.new(geofences: @geofences.map(&:last), deviceid: @deviceid,
|
1066
|
-
debug: @debug )
|
334
|
+
remote_url: @remote_url, debug: @debug )
|
1067
335
|
m.import_h(macro)
|
1068
336
|
m
|
1069
337
|
|
@@ -1085,7 +353,7 @@ class MacroDroid
|
|
1085
353
|
@macros = doc.root.xpath('item').map do |node|
|
1086
354
|
puts ('geofences: ' + geofences.inspect).highlight if @debug
|
1087
355
|
Macro.new(geofences: geofences.map(&:last), deviceid: @deviceid,
|
1088
|
-
debug: @debug).import_xml(node)
|
356
|
+
remote_url: @remote_url, debug: @debug).import_xml(node)
|
1089
357
|
|
1090
358
|
end
|
1091
359
|
|
@@ -1107,7 +375,7 @@ class MacroDroid
|
|
1107
375
|
end
|
1108
376
|
|
1109
377
|
@macros = doc.root.xpath('macro').map do |node|
|
1110
|
-
|
378
|
+
puts 'node: ' + node.inspect if @debug
|
1111
379
|
Macro.new(geofences: @geofences.map(&:last), deviceid: @deviceid,
|
1112
380
|
debug: @debug).import_xml(node)
|
1113
381
|
|
@@ -1308,7 +576,9 @@ class DroidSim
|
|
1308
576
|
|
1309
577
|
end
|
1310
578
|
|
579
|
+
|
1311
580
|
require 'ruby-macrodroid/base'
|
1312
581
|
require 'ruby-macrodroid/triggers'
|
1313
582
|
require 'ruby-macrodroid/actions'
|
1314
583
|
require 'ruby-macrodroid/constraints'
|
584
|
+
require 'ruby-macrodroid/macro'
|