ruby-macrodroid 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c73d4f6bcddec53817e6ae7c59224759e58dd490ab53b2cab91728ceb98961f7
4
- data.tar.gz: 37887f1b46a2158d5101b2c51ae444016dcf34606df34f8e6f58aed05482efb9
3
+ metadata.gz: 8b105d3fc8c1fe8e43ad4ea6b8b9018a26e376949c94c1623a11540ba8d5850c
4
+ data.tar.gz: 22b28e9b200b82fe6c048a0781845c032502c9b24e8ff566e455b8f2193d97f1
5
5
  SHA512:
6
- metadata.gz: 6bb6b3059e62aa4ce7924207a6fe545bc5b588d4ea4eab315361be595c47f343602a617dc7c2fdbc4701b44456dfcd18b255dc0fccfd904f7b56b5455f6f67a4
7
- data.tar.gz: 2b7f77a7b582a0a8d7beda8ba09d10973e06a4844d114398a5bf534e755e66914cede0023693605abe0100f882befe7598271d70aaa5747bde9dac39c04d03d3
6
+ metadata.gz: c09be84265a4961e278e378c346a6152924848f3cf2a347aa3c52c2b87dab6711092c07be1dbb3820576e5779e73818c96b34958c1e2044edf29b24a973c5e35
7
+ data.tar.gz: 333fc854bc4ce0ff61b1921a971835a1f4d1f75d65ae8608de0990c710f5060ecc7bfedb0468baba7f575ca73b3df96e9036d93a64339ba0e08a73d9c9612ecc
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -3,6 +3,7 @@
3
3
  # file: ruby-macrodroid.rb
4
4
 
5
5
  require 'uuid'
6
+ require 'yaml'
6
7
  require 'rxfhelper'
7
8
  require 'chronic_cron'
8
9
 
@@ -30,7 +31,37 @@ class TriggersNlp
30
31
  [TimerTrigger, {time: time, days: days}]
31
32
  end
32
33
 
34
+ # time.is? 'at 18:30pm on Mon or Tue'
35
+ get /^time.is\? ['"](?:at )?(\d+:\d+(?:[ap]m)?) (?:on )?(.*)['"]/i do |time, days|
36
+ [TimerTrigger, {time: time, days: days.gsub(' or ',', ')}]
37
+ end
38
+
39
+ get /^shake[ _]device\??$/i do
40
+ [ShakeDeviceTrigger, {}]
41
+ end
42
+
43
+ get /^Flip Device (.*)$/i do |motion|
44
+ facedown = motion =~ /Face Up (?:->|to) Face Down/i
45
+ [FlipDeviceTrigger, {face_down: facedown }]
46
+ end
47
+
48
+ get /^flip_device_down\?$/i do
49
+ [FlipDeviceTrigger, {face_down: true }]
50
+ end
33
51
 
52
+ get /^flip_device_up\?$/i do
53
+ [FlipDeviceTrigger, {face_down: false }]
54
+ end
55
+
56
+ get /^Failed Login Attempt$/i do
57
+ [FailedLoginTrigger, {}]
58
+ end
59
+
60
+ get /^failed_login?$/i do
61
+ [FailedLoginTrigger, {}]
62
+ end
63
+
64
+
34
65
  end
35
66
 
36
67
  alias find_trigger run_route
@@ -54,9 +85,26 @@ class ActionsNlp
54
85
  [ToastAction, {msg: msg}]
55
86
  end
56
87
 
57
- get /^Popup Message ['"][^'"]+/i do |msg|
88
+ get /^Popup[ _]Message ['"]([^'"]+)/i do |msg|
58
89
  [ToastAction, {msg: msg}]
59
90
  end
91
+
92
+ get /^say current[ _]time/i do
93
+ [SayTimeAction, {}]
94
+ end
95
+
96
+ get /^Torch :?(.*)/i do |onoffstate|
97
+ state = onoffstate.downcase == 'on' ? 0 : 1
98
+ [CameraFlashLightAction, {state: state}]
99
+ end
100
+
101
+ get /^Take Picture/i do
102
+ [TakePictureAction, {}]
103
+ end
104
+
105
+ get /^take_picture/i do
106
+ [TakePictureAction, {}]
107
+ end
60
108
 
61
109
  end
62
110
 
@@ -145,7 +193,7 @@ class Macro
145
193
  using Params
146
194
 
147
195
  attr_reader :local_variables, :triggers, :actions, :constraints, :guid
148
- attr_accessor :title
196
+ attr_accessor :title, :description
149
197
 
150
198
  def initialize(name=nil, debug: false)
151
199
 
@@ -209,6 +257,7 @@ class Macro
209
257
  end
210
258
 
211
259
  @title = h[:name]
260
+ @description = h[:description]
212
261
 
213
262
  # fetch the local variables
214
263
  @local_variables = h['local_variables']
@@ -246,6 +295,7 @@ class Macro
246
295
  end
247
296
 
248
297
  @title = node.attributes[:name]
298
+ @description = node.attributes[:description]
249
299
 
250
300
  if node.element('triggers') then
251
301
 
@@ -357,15 +407,33 @@ class Macro
357
407
 
358
408
  def run()
359
409
  @actions.map(&:invoke)
360
- end
410
+ end
411
+
412
+ def to_pc()
413
+
414
+ heading = '# ' + @title + "\n"
415
+ heading += '# ' + @description if @description
416
+ condition = @triggers.first.to_pc
417
+ actions = @actions.map(&:to_pc).join("\n")
418
+
419
+ <<EOF
420
+ #{heading}
421
+
422
+ if #{condition} then
423
+ #{actions}
424
+ end
425
+ EOF
426
+ end
361
427
 
362
428
  def to_s()
363
- [
429
+ a = [
364
430
  'm: ' + @title,
365
431
  @triggers.map {|x| "t: %s" % x}.join("\n"),
366
432
  @actions.map {|x| "a: %s" % x}.join("\n"),
367
433
  @constraints.map {|x| "a: %s" % x}.join("\n")
368
- ].join("\n")
434
+ ]
435
+ a.insert(1, 'd: ' + @description) if @description
436
+ a.join("\n")
369
437
  end
370
438
 
371
439
  private
@@ -384,6 +452,9 @@ class Macro
384
452
  end
385
453
 
386
454
 
455
+ class MacroDroidError < Exception
456
+ end
457
+
387
458
  class MacroDroid
388
459
  using ColouredText
389
460
  using Params
@@ -396,16 +467,33 @@ class MacroDroid
396
467
 
397
468
  if obj then
398
469
 
399
- s, _ = RXFHelper.read(obj)
470
+ raw_s, _ = RXFHelper.read(obj)
471
+
472
+ s = raw_s.strip
400
473
 
401
474
  if s[0] == '{' then
475
+
402
476
  import_json(s)
477
+
403
478
  elsif s[0] == '<'
479
+
404
480
  import_xml(s)
405
481
  @h = build_h
482
+
406
483
  else
407
- import_xml(text_to_xml(s))
484
+
485
+ xml = if s =~ /^m: / then
486
+ text_to_xml(s)
487
+ elsif s =~ /^# /
488
+ pc_to_xml(s)
489
+ else
490
+ raise MacroDroidError, 'invalid input'
491
+ end
492
+ import_xml(xml)
408
493
  @h = build_h
494
+
495
+
496
+
409
497
  end
410
498
 
411
499
  else
@@ -459,7 +547,10 @@ class MacroDroid
459
547
 
460
548
  def import_json(s)
461
549
 
462
- @h = JSON.parse(s, symbolize_names: true).to_snake_case
550
+ h = JSON.parse(s, symbolize_names: true)
551
+ puts 'json_to_yaml: ' + h.to_yaml if @debug
552
+
553
+ @h = h.to_snake_case
463
554
  puts ('@h: ' + @h.inspect).debug if @debug
464
555
 
465
556
  @macros = @h[:macro_list].map do |macro|
@@ -477,20 +568,48 @@ class MacroDroid
477
568
 
478
569
  def import_xml(raws)
479
570
 
571
+ puts 'raws: ' + raws.inspect if @debug
480
572
  s = RXFHelper.read(raws).first
481
573
  puts 's: ' + s.inspect if @debug
482
574
  doc = Rexle.new(s)
483
- puts 'after doc' if @debug
575
+
576
+ if @debug then
577
+ puts 'doc: ' + doc.root.xml
578
+ end
579
+
580
+ debug = @debug
484
581
 
485
582
  @macros = doc.root.xpath('macro').map do |node|
486
583
 
487
- macro = Macro.new @title, debug: @debug
584
+ macro = Macro.new @title, debug: debug
488
585
  macro.import_xml(node)
489
586
  macro
490
587
 
491
588
  end
492
589
  end
493
590
 
591
+ def pc_to_xml(s)
592
+
593
+ macros = s.strip.split(/(?=#)/).map do |raw_macro|
594
+
595
+ a = raw_macro.lines
596
+ name = a.shift[/(?<=# ).*/]
597
+ description = a.shift[/(?<=# ).*/] if a[0][/^# /]
598
+ body = a.join.strip
599
+
600
+ a2 = body.lines
601
+ # get the trigger
602
+ trigger = [:trigger, {}, a2[0][/^if (.*) then/,1]]
603
+ action = [:action, {}, a2[1].strip]
604
+ [:macro, {name: name, description: description}, trigger, action, []]
605
+
606
+ end
607
+
608
+ doc = Rexle.new([:macros, {}, '', *macros])
609
+ doc.root.xml pretty: true
610
+
611
+ end
612
+
494
613
  def text_to_xml(s)
495
614
 
496
615
  a = s.split(/.*(?=^m:)/); a.shift
@@ -523,9 +642,15 @@ class MacroDroid
523
642
  @h.merge(macro_list: @macros.map(&:to_h)).to_camel_case
524
643
 
525
644
  end
645
+
646
+ # returns pseudocode
647
+ #
648
+ def to_pc()
649
+ @macros.map(&:to_pc).join("\n\n")
650
+ end
526
651
 
527
652
  def to_s()
528
- @macros.map(&:to_s).join("\n\n")
653
+ @macros.map(&:to_s).join("\n")
529
654
  end
530
655
 
531
656
  end
@@ -1103,6 +1228,10 @@ class TimerTrigger < Trigger
1103
1228
 
1104
1229
  end
1105
1230
 
1231
+ def to_pc()
1232
+ "time.is? '%s'" % self.to_s.gsub(',', ' or')
1233
+ end
1234
+
1106
1235
  def to_s()
1107
1236
 
1108
1237
  dow = @h[:days_of_week]
@@ -1185,6 +1314,15 @@ class RegularIntervalTrigger < Trigger
1185
1314
 
1186
1315
  end
1187
1316
 
1317
+ class DeviceEventsTrigger < Trigger
1318
+
1319
+ def initialize(h={})
1320
+ super(h)
1321
+ @group = 'device_events'
1322
+ end
1323
+
1324
+ end
1325
+
1188
1326
  # Category: Device Events
1189
1327
  #
1190
1328
  # Airplane Mode Changed
@@ -1196,7 +1334,7 @@ end
1196
1334
  # shorthand example:
1197
1335
  # airplanemode: enabled
1198
1336
  #
1199
- class AirplaneModeTrigger < Trigger
1337
+ class AirplaneModeTrigger < DeviceEventsTrigger
1200
1338
 
1201
1339
  def initialize(h={})
1202
1340
 
@@ -1212,7 +1350,7 @@ end
1212
1350
 
1213
1351
  # Category: Device Events
1214
1352
  #
1215
- class AutoSyncChangeTrigger < Trigger
1353
+ class AutoSyncChangeTrigger < DeviceEventsTrigger
1216
1354
 
1217
1355
  def initialize(h={})
1218
1356
 
@@ -1228,7 +1366,7 @@ end
1228
1366
 
1229
1367
  # Category: Device Events
1230
1368
  #
1231
- class DayDreamTrigger < Trigger
1369
+ class DayDreamTrigger < DeviceEventsTrigger
1232
1370
 
1233
1371
  def initialize(h={})
1234
1372
 
@@ -1244,7 +1382,7 @@ end
1244
1382
 
1245
1383
  # Category: Device Events
1246
1384
  #
1247
- class DockTrigger < Trigger
1385
+ class DockTrigger < DeviceEventsTrigger
1248
1386
 
1249
1387
  def initialize(h={})
1250
1388
 
@@ -1260,7 +1398,30 @@ end
1260
1398
 
1261
1399
  # Category: Device Events
1262
1400
  #
1263
- class GPSEnabledTrigger < Trigger
1401
+ class FailedLoginTrigger < DeviceEventsTrigger
1402
+
1403
+ def initialize(h={})
1404
+
1405
+ options = {
1406
+ num_failures: 1
1407
+ }
1408
+
1409
+ super(options.merge h)
1410
+
1411
+ end
1412
+
1413
+ def to_pc()
1414
+ 'failed_login?'
1415
+ end
1416
+
1417
+ def to_s()
1418
+ 'Failed Login Attempt'
1419
+ end
1420
+ end
1421
+
1422
+ # Category: Device Events
1423
+ #
1424
+ class GPSEnabledTrigger < DeviceEventsTrigger
1264
1425
 
1265
1426
  def initialize(h={})
1266
1427
 
@@ -1276,7 +1437,7 @@ end
1276
1437
 
1277
1438
  # Category: Device Events
1278
1439
  #
1279
- class MusicPlayingTrigger < Trigger
1440
+ class MusicPlayingTrigger < DeviceEventsTrigger
1280
1441
 
1281
1442
  def initialize(h={})
1282
1443
 
@@ -1293,7 +1454,7 @@ end
1293
1454
 
1294
1455
  # Category: Device Events
1295
1456
  #
1296
- class DeviceUnlockedTrigger < Trigger
1457
+ class DeviceUnlockedTrigger < DeviceEventsTrigger
1297
1458
 
1298
1459
  def initialize(h={})
1299
1460
 
@@ -1308,7 +1469,7 @@ end
1308
1469
 
1309
1470
  # Category: Device Events
1310
1471
  #
1311
- class AutoRotateChangeTrigger < Trigger
1472
+ class AutoRotateChangeTrigger < DeviceEventsTrigger
1312
1473
 
1313
1474
  def initialize(h={})
1314
1475
 
@@ -1324,7 +1485,7 @@ end
1324
1485
 
1325
1486
  # Category: Device Events
1326
1487
  #
1327
- class ClipboardChangeTrigger < Trigger
1488
+ class ClipboardChangeTrigger < DeviceEventsTrigger
1328
1489
 
1329
1490
  def initialize(h={})
1330
1491
 
@@ -1341,7 +1502,7 @@ end
1341
1502
 
1342
1503
  # Category: Device Events
1343
1504
  #
1344
- class BootTrigger < Trigger
1505
+ class BootTrigger < DeviceEventsTrigger
1345
1506
 
1346
1507
  def initialize(h={})
1347
1508
 
@@ -1356,7 +1517,7 @@ end
1356
1517
 
1357
1518
  # Category: Device Events
1358
1519
  #
1359
- class IntentReceivedTrigger < Trigger
1520
+ class IntentReceivedTrigger < DeviceEventsTrigger
1360
1521
 
1361
1522
  def initialize(h={})
1362
1523
 
@@ -1376,7 +1537,7 @@ end
1376
1537
 
1377
1538
  # Category: Device Events
1378
1539
  #
1379
- class NotificationTrigger < Trigger
1540
+ class NotificationTrigger < DeviceEventsTrigger
1380
1541
 
1381
1542
  def initialize(h={})
1382
1543
 
@@ -1402,7 +1563,7 @@ end
1402
1563
 
1403
1564
  # Category: Device Events
1404
1565
  #
1405
- class ScreenOnOffTrigger < Trigger
1566
+ class ScreenOnOffTrigger < DeviceEventsTrigger
1406
1567
 
1407
1568
  def initialize(h={})
1408
1569
 
@@ -1418,7 +1579,7 @@ end
1418
1579
 
1419
1580
  # Category: Device Events
1420
1581
  #
1421
- class SilentModeTrigger < Trigger
1582
+ class SilentModeTrigger < DeviceEventsTrigger
1422
1583
 
1423
1584
  def initialize(h={})
1424
1585
 
@@ -1494,9 +1655,19 @@ class SunriseSunsetTrigger < Trigger
1494
1655
 
1495
1656
  end
1496
1657
 
1658
+
1659
+ class SensorsTrigger < Trigger
1660
+
1661
+ def initialize(h={})
1662
+ super(h)
1663
+ @group = 'sensors'
1664
+ end
1665
+
1666
+ end
1667
+
1497
1668
  # Category: Sensors
1498
1669
  #
1499
- class ActivityRecognitionTrigger < Trigger
1670
+ class ActivityRecognitionTrigger < SensorsTrigger
1500
1671
 
1501
1672
  def initialize(h={})
1502
1673
 
@@ -1513,7 +1684,7 @@ end
1513
1684
 
1514
1685
  # Category: Sensors
1515
1686
  #
1516
- class ProximityTrigger < Trigger
1687
+ class ProximityTrigger < SensorsTrigger
1517
1688
 
1518
1689
  def initialize(h={})
1519
1690
 
@@ -1530,7 +1701,7 @@ end
1530
1701
 
1531
1702
  # Category: Sensors
1532
1703
  #
1533
- class ShakeDeviceTrigger < Trigger
1704
+ class ShakeDeviceTrigger < SensorsTrigger
1534
1705
 
1535
1706
  def initialize(h={})
1536
1707
 
@@ -1540,12 +1711,25 @@ class ShakeDeviceTrigger < Trigger
1540
1711
  super(options.merge h)
1541
1712
 
1542
1713
  end
1714
+
1715
+ def to_pc()
1716
+ 'shake_device?'
1717
+ end
1718
+
1719
+ def to_s()
1720
+ 'Shake Device'
1721
+ end
1543
1722
 
1544
1723
  end
1545
1724
 
1546
1725
  # Category: Sensors
1547
1726
  #
1548
- class FlipDeviceTrigger < Trigger
1727
+ # options:
1728
+ # Face Up -> Face Down
1729
+ # Face Down -> Face Up
1730
+ # Any -> Face Down
1731
+ #
1732
+ class FlipDeviceTrigger < SensorsTrigger
1549
1733
 
1550
1734
  def initialize(h={})
1551
1735
 
@@ -1557,13 +1741,23 @@ class FlipDeviceTrigger < Trigger
1557
1741
 
1558
1742
  super(options.merge h)
1559
1743
 
1744
+ end
1745
+
1746
+ def to_pc()
1747
+ @h[:face_down] ? 'flip_device_down?' : 'flip_device_up?'
1560
1748
  end
1749
+
1750
+ def to_s()
1751
+
1752
+ action = @h[:face_down] ? 'Face Up -> Face Down' : 'Face Down -> Face Up'
1753
+ 'Flip Device ' + action
1754
+ end
1561
1755
 
1562
1756
  end
1563
1757
 
1564
1758
  # Category: Sensors
1565
1759
  #
1566
- class OrientationTrigger < Trigger
1760
+ class OrientationTrigger < SensorsTrigger
1567
1761
 
1568
1762
  def initialize(h={})
1569
1763
 
@@ -1829,6 +2023,15 @@ class TakePictureAction < CameraAction
1829
2023
  super(options.merge h)
1830
2024
 
1831
2025
  end
2026
+
2027
+ def to_pc()
2028
+ camera = @h[:use_front_camera] ? :front : :back
2029
+ 'take_photo :' + camera.to_s
2030
+ end
2031
+
2032
+ def to_s()
2033
+ 'Take Picture'
2034
+ end
1832
2035
 
1833
2036
  end
1834
2037
 
@@ -1987,6 +2190,20 @@ class SayTimeAction < DateTimeAction
1987
2190
  super(options.merge h)
1988
2191
 
1989
2192
  end
2193
+
2194
+ def invoke()
2195
+ time = ($env and $env[:time]) ? $env[:time] : Time.now
2196
+ tformat = @h['12_hour'] ? "%-I:%M%P" : "%H:%M"
2197
+ super(time.strftime(tformat))
2198
+ end
2199
+
2200
+ def to_pc()
2201
+ 'say current_time()'
2202
+ end
2203
+
2204
+ def to_s()
2205
+ 'Say Current Time'
2206
+ end
1990
2207
 
1991
2208
  end
1992
2209
 
@@ -2158,6 +2375,14 @@ class CameraFlashLightAction < DeviceSettingsAction
2158
2375
 
2159
2376
  end
2160
2377
 
2378
+ def to_pc()
2379
+ 'torch :on'
2380
+ end
2381
+
2382
+ def to_s()
2383
+ 'Torch On'
2384
+ end
2385
+
2161
2386
  end
2162
2387
 
2163
2388
  # Category: Device Settings
@@ -2750,6 +2975,10 @@ class ToastAction < NotificationsAction
2750
2975
  super(@h[:message_text])
2751
2976
  end
2752
2977
 
2978
+ def to_pc()
2979
+ "popup_message '%s'" % @h[:message_text]
2980
+ end
2981
+
2753
2982
  def to_s()
2754
2983
  "Popup Message '%s'" % @h[:message_text]
2755
2984
  end
@@ -3489,6 +3718,18 @@ class AirplaneModeConstraint < Constraint
3489
3718
  end
3490
3719
 
3491
3720
  end
3721
+
3722
+ def to_pc()
3723
+ status = @h[:enabled] ? 'enabled?' : 'disabled?'
3724
+ 'airplane_mode.' + status
3725
+ end
3726
+
3727
+ def to_s()
3728
+
3729
+ status = @h[:enabled] ? 'Enabled' : 'Disabled'
3730
+ 'Airplane Mode ' + status
3731
+
3732
+ end
3492
3733
 
3493
3734
  end
3494
3735
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-macrodroid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
metadata.gz.sig CHANGED
Binary file