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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12fa9c7d9f642140ed62656a4c3444e5c739ad2be06af2883e23e48766cd742f
4
- data.tar.gz: 6f70e2124afbcf43bd15295dfea8aaf9a0a8d6704de819acb34481082d8c905f
3
+ metadata.gz: 37e8014bb2ccd71ffd2da90197a1dd1a89c7e8e6bbbfc7ed88e9cfbff07925a1
4
+ data.tar.gz: f2d4910bb6893249e33eb7c4326ea733188ecef67ec94f808cd25ef6c97760d0
5
5
  SHA512:
6
- metadata.gz: a00b28e20a41ffbdead956eb07ad4e7fe412aa2ceb773017a709c97a4fd1307672b78405581a8e54d855d1f9cb53fe598638bc542facccde886b127e9e150d17
7
- data.tar.gz: ddcdc9689a2f202477018ab710772c834caad0e392c6d7135c0f65beb8e85dbf0144fc793e7b11db404531a1cbaf69876b2b21f7598b6baf1361ba794f7bc809
6
+ metadata.gz: 06015fe764a0450838ad49b6dbebba46afc32ec49673dbf4e1bce9b07e04aaea1850153cf2c0b1d56e740dd2cbcf4653f92878ee99680d7c3f2eaacf1fffb69e
7
+ data.tar.gz: df0c2950bcae690d137b294825c95579f8530fea24cabfe371809efff64343d4e9ffd71b5f2378c7938bc214dfc0e409892947ad03a86ef4438816fafa11000a
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -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(/^t:/,'trigger:').gsub(/^a:/,'action:')\
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
- raw_macros, raw_geofences = s2.split(/(?=^macro:)/,2).reverse
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 export_json()
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'