ruby-macrodroid 0.7.8 → 0.8.2
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 +96 -4924
- data/lib/ruby-macrodroid/actions.rb +2056 -0
- data/lib/ruby-macrodroid/base.rb +95 -0
- data/lib/ruby-macrodroid/triggers.rb +1558 -0
- metadata +19 -16
- metadata.gz.sig +0 -0
@@ -0,0 +1,2056 @@
|
|
1
|
+
# file: ruby-macrodroid/actions.rb
|
2
|
+
|
3
|
+
# This file contains the following classes:
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# ## Action classes
|
7
|
+
#
|
8
|
+
# Action LocationAction ShareLocationAction ApplicationAction
|
9
|
+
# LaunchActivityAction KillBackgroundAppAction OpenWebPageAction CameraAction
|
10
|
+
# UploadPhotoAction TakePictureAction ConnectivityAction SetWifiAction
|
11
|
+
# SetBluetoothAction SetBluetoothAction SendIntentAction DateTimeAction
|
12
|
+
# SetAlarmClockAction StopWatchAction SayTimeAction DeviceAction
|
13
|
+
# AndroidShortcutsAction ClipboardAction PressBackAction SpeakTextAction
|
14
|
+
# UIInteractionAction VoiceSearchAction DeviceSettingsAction
|
15
|
+
# ExpandCollapseStatusBarAction LaunchHomeScreenAction CameraFlashLightAction
|
16
|
+
# VibrateAction SetAutoRotateAction DayDreamAction SetKeyboardAction
|
17
|
+
# SetKeyguardAction CarModeAction ChangeKeyboardAction SetWallpaperAction
|
18
|
+
# FileAction OpenFileAction LocationAction ForceLocationUpdateAction
|
19
|
+
# ShareLocationAction SetLocationUpdateRateAction LoggingAction
|
20
|
+
# AddCalendarEntryAction LogAction ClearLogAction MediaAction
|
21
|
+
# RecordMicrophoneAction PlaySoundAction MessagingAction SendEmailAction
|
22
|
+
# SendSMSAction UDPCommandAction NotificationsAction ClearNotificationsAction
|
23
|
+
# MessageDialogAction AllowLEDNotificationLightAction
|
24
|
+
# SetNotificationSoundAction SetNotificationSoundAction
|
25
|
+
# SetNotificationSoundAction NotificationAction ToastAction PhoneAction
|
26
|
+
# AnswerCallAction ClearCallLogAction OpenCallLogAction RejectCallAction
|
27
|
+
# MakeCallAction SetRingtoneAction ScreenAction SetBrightnessAction
|
28
|
+
# ForceScreenRotationAction ScreenOnAction DimScreenAction KeepAwakeAction
|
29
|
+
# SetScreenTimeoutAction VolumeAction SilentModeVibrateOffAction
|
30
|
+
# SetVibrateAction VolumeIncrementDecrementAction SpeakerPhoneAction
|
31
|
+
# SetVolumeAction
|
32
|
+
#
|
33
|
+
|
34
|
+
|
35
|
+
class Action < MacroObject
|
36
|
+
using Params
|
37
|
+
|
38
|
+
attr_reader :constraints
|
39
|
+
|
40
|
+
def initialize(h={})
|
41
|
+
|
42
|
+
macro = h[:macro]
|
43
|
+
h.delete :macro
|
44
|
+
super(h)
|
45
|
+
|
46
|
+
# fetch the constraints
|
47
|
+
@constraints = @h[:constraint_list].map do |constraint|
|
48
|
+
object(constraint.to_snake_case.merge(macro: macro))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def invoke(s='')
|
53
|
+
"%s/%s: %s" % [@group, @type, s]
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s(colour: false)
|
57
|
+
|
58
|
+
h = @h.clone
|
59
|
+
h.delete :macro
|
60
|
+
@s ||= "#<%s %s>" % [self.class, h.inspect]
|
61
|
+
operator = @h[:is_or_condition] ? 'OR' : 'AND'
|
62
|
+
constraints = @constraints.map \
|
63
|
+
{|x| x.to_summary(colour: colour)}.join(" %s " % operator)
|
64
|
+
|
65
|
+
@s + constraints
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
class LocationAction < Action
|
73
|
+
|
74
|
+
def initialize(h={})
|
75
|
+
super(h)
|
76
|
+
@group = 'location'
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# Category: Location
|
82
|
+
#
|
83
|
+
class ShareLocationAction < LocationAction
|
84
|
+
|
85
|
+
def initialize(h={})
|
86
|
+
|
87
|
+
super()
|
88
|
+
|
89
|
+
options = {
|
90
|
+
email: '',
|
91
|
+
variable: {:m_stringValue=>"", :m_name=>"",
|
92
|
+
:m_decimalValue=>0.0, :isLocal=>true, :m_booleanValue=>false,
|
93
|
+
:excludeFromLog=>false, :m_intValue=>0, :m_type=>2},
|
94
|
+
sim_id: 0,
|
95
|
+
output_channel: 5,
|
96
|
+
old_variable_format: true
|
97
|
+
}
|
98
|
+
|
99
|
+
super(options.merge h)
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_s(colour: false)
|
104
|
+
'ShareLocationAction ' + @h.inspect
|
105
|
+
end
|
106
|
+
|
107
|
+
alias to_summary to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
class ApplicationAction < Action
|
112
|
+
|
113
|
+
def initialize(h={})
|
114
|
+
super(h)
|
115
|
+
@group = 'application'
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
# Category: Applications
|
121
|
+
#
|
122
|
+
class LaunchActivityAction < ApplicationAction
|
123
|
+
|
124
|
+
def initialize(h={})
|
125
|
+
|
126
|
+
options = {
|
127
|
+
application_name: 'Chrome',
|
128
|
+
package_to_launch: 'com.android.chrome',
|
129
|
+
exclude_from_recents: false,
|
130
|
+
start_new: false
|
131
|
+
}
|
132
|
+
|
133
|
+
super(options.merge h)
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_s(colour: false)
|
138
|
+
'Launch ' + @h[:application_name]
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
# Category: Applications
|
144
|
+
#
|
145
|
+
class KillBackgroundAppAction < ApplicationAction
|
146
|
+
|
147
|
+
def initialize(h={})
|
148
|
+
|
149
|
+
options = {
|
150
|
+
application_name_list: [""],
|
151
|
+
package_name_list: [""]
|
152
|
+
}
|
153
|
+
|
154
|
+
super(options.merge h)
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
def to_s(colour: false)
|
159
|
+
'KillBackgroundAppAction ' + @h.inspect
|
160
|
+
end
|
161
|
+
|
162
|
+
alias to_summary to_s
|
163
|
+
end
|
164
|
+
|
165
|
+
# Category: Applications
|
166
|
+
#
|
167
|
+
class LaunchShortcutAction < ApplicationAction
|
168
|
+
|
169
|
+
def initialize(h={})
|
170
|
+
|
171
|
+
options = {
|
172
|
+
:app_name=>"Amazon Alexa", :intent_encoded=>"", :name=>"Ask Alexa"
|
173
|
+
}
|
174
|
+
|
175
|
+
super(options.merge h)
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_s(colour: false)
|
180
|
+
@s = "Launch Shortcut: " + @h[:app_name] + "\n " + @h[:name]
|
181
|
+
super()
|
182
|
+
end
|
183
|
+
|
184
|
+
alias to_summary to_s
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
# Category: Applications
|
189
|
+
#
|
190
|
+
class OpenWebPageAction < ApplicationAction
|
191
|
+
|
192
|
+
def initialize(h={})
|
193
|
+
|
194
|
+
h[:url_to_open] = h[:url] if h[:url]
|
195
|
+
|
196
|
+
options = {
|
197
|
+
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},
|
198
|
+
url_to_open: '',
|
199
|
+
http_get: true,
|
200
|
+
disable_url_encode: false,
|
201
|
+
block_next_action: false
|
202
|
+
}
|
203
|
+
|
204
|
+
super(options.merge filter(options,h))
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
def to_s(colour: false)
|
209
|
+
"HTTP GET\n url: " + @h[:url_to_open]
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
class CameraAction < Action
|
216
|
+
|
217
|
+
def initialize(h={})
|
218
|
+
super(h)
|
219
|
+
@group = 'camera'
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
# Category: Camera/Photo
|
225
|
+
#
|
226
|
+
class UploadPhotoAction < CameraAction
|
227
|
+
|
228
|
+
def initialize(h={})
|
229
|
+
|
230
|
+
options = {
|
231
|
+
option: 'Via Intent',
|
232
|
+
use_smtp_email: false
|
233
|
+
}
|
234
|
+
|
235
|
+
super(options.merge h)
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
def to_s(colour: false)
|
240
|
+
'UploadPhotoAction ' + @h.inspect
|
241
|
+
end
|
242
|
+
|
243
|
+
alias to_summary to_s
|
244
|
+
end
|
245
|
+
|
246
|
+
# Category: Camera/Photo
|
247
|
+
#
|
248
|
+
class TakePictureAction < CameraAction
|
249
|
+
|
250
|
+
def initialize(h={})
|
251
|
+
|
252
|
+
options = {
|
253
|
+
new_path: '/storage/sdcard1/DCIM/Camera',
|
254
|
+
path: '/storage/sdcard1/DCIM/Camera',
|
255
|
+
show_icon: true,
|
256
|
+
use_front_camera: true,
|
257
|
+
flash_option: 0
|
258
|
+
}
|
259
|
+
|
260
|
+
super(options.merge h)
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
def to_pc()
|
265
|
+
camera = @h[:use_front_camera] ? :front : :back
|
266
|
+
'take_photo :' + camera.to_s
|
267
|
+
end
|
268
|
+
|
269
|
+
def to_s(colour: false)
|
270
|
+
'Take Picture'
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
class IfConditionAction < Action
|
276
|
+
|
277
|
+
def initialize(h={})
|
278
|
+
|
279
|
+
options = {
|
280
|
+
a: true,
|
281
|
+
constraint_list: ''
|
282
|
+
}
|
283
|
+
|
284
|
+
macro = h[:macro]
|
285
|
+
h2 = options.merge(filter(options,h).merge(macro: macro))
|
286
|
+
|
287
|
+
super(h2)
|
288
|
+
|
289
|
+
@label = 'If '
|
290
|
+
|
291
|
+
end
|
292
|
+
|
293
|
+
def to_s(colour: false)
|
294
|
+
|
295
|
+
@s = "If " #+ @constraints.map(&:to_s).join(" %s " % operator)
|
296
|
+
super(colour: colour)
|
297
|
+
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
class ElseAction < Action
|
302
|
+
|
303
|
+
def initialize(h={})
|
304
|
+
|
305
|
+
options = {
|
306
|
+
constraint_list: ''
|
307
|
+
}
|
308
|
+
|
309
|
+
super(options.merge h)
|
310
|
+
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
def to_s(colour: false)
|
315
|
+
'Else'
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
319
|
+
|
320
|
+
class ElseIfConditionAction < IfConditionAction
|
321
|
+
|
322
|
+
def initialize(h={})
|
323
|
+
|
324
|
+
options = {
|
325
|
+
constraint_list: ''
|
326
|
+
}
|
327
|
+
|
328
|
+
super(options.merge h)
|
329
|
+
@label = 'ElseIf '
|
330
|
+
|
331
|
+
end
|
332
|
+
|
333
|
+
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
class EndIfAction < Action
|
338
|
+
|
339
|
+
def initialize(h={})
|
340
|
+
|
341
|
+
options = {
|
342
|
+
constraint_list: ''
|
343
|
+
}
|
344
|
+
|
345
|
+
super(options.merge h)
|
346
|
+
|
347
|
+
end
|
348
|
+
|
349
|
+
def to_s(colour: false)
|
350
|
+
'End If'
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
|
355
|
+
class ConnectivityAction < Action
|
356
|
+
|
357
|
+
def initialize(h={})
|
358
|
+
super(h)
|
359
|
+
@group = 'connectivity'
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|
363
|
+
|
364
|
+
# Category: Connectivity
|
365
|
+
#
|
366
|
+
class SetAirplaneModeAction < ConnectivityAction
|
367
|
+
|
368
|
+
def initialize(h={})
|
369
|
+
|
370
|
+
options = {
|
371
|
+
device_name: '',
|
372
|
+
state: 1
|
373
|
+
}
|
374
|
+
|
375
|
+
super(options.merge h)
|
376
|
+
|
377
|
+
end
|
378
|
+
|
379
|
+
def to_s(colour: false)
|
380
|
+
|
381
|
+
state = ['On', 'Off', 'Toggle'][@h[:state]]
|
382
|
+
@s = 'Airplane Mode ' + state + "\n"
|
383
|
+
super(colour: colour)
|
384
|
+
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
388
|
+
|
389
|
+
# Category: Connectivity
|
390
|
+
#
|
391
|
+
class SetWifiAction < ConnectivityAction
|
392
|
+
|
393
|
+
def initialize(h={})
|
394
|
+
|
395
|
+
options = {
|
396
|
+
ssid: '[Select Wifi]',
|
397
|
+
network_id: 0,
|
398
|
+
state: 0
|
399
|
+
}
|
400
|
+
|
401
|
+
super(options.merge h)
|
402
|
+
|
403
|
+
end
|
404
|
+
|
405
|
+
def to_s(colour: false)
|
406
|
+
action = @h[:state] == 0 ? 'Enable' : 'Disable'
|
407
|
+
action + ' Wifi'
|
408
|
+
end
|
409
|
+
|
410
|
+
end
|
411
|
+
|
412
|
+
# Category: Connectivity
|
413
|
+
#
|
414
|
+
class SetBluetoothAction < ConnectivityAction
|
415
|
+
|
416
|
+
def initialize(h={})
|
417
|
+
|
418
|
+
options = {
|
419
|
+
device_name: '',
|
420
|
+
state: 0
|
421
|
+
}
|
422
|
+
|
423
|
+
super(options.merge h)
|
424
|
+
|
425
|
+
end
|
426
|
+
|
427
|
+
def to_s(colour: false)
|
428
|
+
'SetBluetoothAction ' + @h.inspect
|
429
|
+
end
|
430
|
+
|
431
|
+
alias to_summary to_s
|
432
|
+
end
|
433
|
+
|
434
|
+
# Category: Connectivity
|
435
|
+
#
|
436
|
+
class SetBluetoothAction < ConnectivityAction
|
437
|
+
|
438
|
+
def initialize(h={})
|
439
|
+
|
440
|
+
options = {
|
441
|
+
device_name: '',
|
442
|
+
state: 1
|
443
|
+
}
|
444
|
+
|
445
|
+
super(options.merge h)
|
446
|
+
|
447
|
+
end
|
448
|
+
|
449
|
+
def to_s(colour: false)
|
450
|
+
'SetBluetoothAction ' + @h.inspect
|
451
|
+
end
|
452
|
+
|
453
|
+
alias to_summary to_s
|
454
|
+
end
|
455
|
+
|
456
|
+
class SetHotspotAction < ConnectivityAction
|
457
|
+
|
458
|
+
def initialize(h={})
|
459
|
+
|
460
|
+
options = {
|
461
|
+
device_name: "", state: 0, turn_wifi_on: true, use_legacy_mechanism: false, mechanism: 0
|
462
|
+
|
463
|
+
}
|
464
|
+
|
465
|
+
super(options.merge h)
|
466
|
+
|
467
|
+
end
|
468
|
+
|
469
|
+
def to_s(colour: false)
|
470
|
+
action = @h[:turn_wifi_on] ? 'Enable' : 'Disable'
|
471
|
+
action + ' HotSpot'
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
# Category: Connectivity
|
476
|
+
#
|
477
|
+
class SendIntentAction < ConnectivityAction
|
478
|
+
|
479
|
+
def initialize(h={})
|
480
|
+
|
481
|
+
options = {
|
482
|
+
action: '',
|
483
|
+
class_name: '',
|
484
|
+
data: '',
|
485
|
+
extra1_name: '',
|
486
|
+
extra1_value: '',
|
487
|
+
extra2_name: '',
|
488
|
+
extra2_value: '',
|
489
|
+
extra3_name: '',
|
490
|
+
extra3_value: '',
|
491
|
+
extra4_name: '',
|
492
|
+
extra4_value: '',
|
493
|
+
package_name: '',
|
494
|
+
target: 'Activity'
|
495
|
+
}
|
496
|
+
|
497
|
+
super(options.merge h)
|
498
|
+
|
499
|
+
end
|
500
|
+
|
501
|
+
def to_s(colour: false)
|
502
|
+
'Send Intent ' + "\n " + @h[:action]
|
503
|
+
end
|
504
|
+
|
505
|
+
alias to_summary to_s
|
506
|
+
end
|
507
|
+
|
508
|
+
|
509
|
+
class DateTimeAction < Action
|
510
|
+
|
511
|
+
def initialize(h={})
|
512
|
+
super(h)
|
513
|
+
@group = 'datetime'
|
514
|
+
end
|
515
|
+
|
516
|
+
end
|
517
|
+
|
518
|
+
# Category: Date/Time
|
519
|
+
#
|
520
|
+
class SetAlarmClockAction < DateTimeAction
|
521
|
+
|
522
|
+
def initialize(h={})
|
523
|
+
|
524
|
+
options = {
|
525
|
+
days_of_week: [false, false, false, false, false, false, false],
|
526
|
+
label: 'wakeup mum',
|
527
|
+
delay_in_minutes: 1,
|
528
|
+
hour: 8,
|
529
|
+
delay_in_hours: 0,
|
530
|
+
minute: 15,
|
531
|
+
one_off: true,
|
532
|
+
option: 0,
|
533
|
+
relative: true,
|
534
|
+
day_option: 0
|
535
|
+
}
|
536
|
+
|
537
|
+
super(options.merge h)
|
538
|
+
|
539
|
+
end
|
540
|
+
|
541
|
+
def to_s(colour: false)
|
542
|
+
'SetAlarmClockAction ' + @h.inspect
|
543
|
+
end
|
544
|
+
|
545
|
+
alias to_summary to_s
|
546
|
+
end
|
547
|
+
|
548
|
+
# Category: Date/Time
|
549
|
+
#
|
550
|
+
class StopWatchAction < DateTimeAction
|
551
|
+
|
552
|
+
def initialize(h={})
|
553
|
+
|
554
|
+
options = {
|
555
|
+
stopwatch_name: 'timer1',
|
556
|
+
option: 0
|
557
|
+
}
|
558
|
+
|
559
|
+
super(options.merge h)
|
560
|
+
|
561
|
+
end
|
562
|
+
|
563
|
+
def to_s(colour: false)
|
564
|
+
'StopWatchAction ' + @h.inspect
|
565
|
+
end
|
566
|
+
|
567
|
+
alias to_summary to_s
|
568
|
+
end
|
569
|
+
|
570
|
+
# Category: Date/Time
|
571
|
+
#
|
572
|
+
class SayTimeAction < DateTimeAction
|
573
|
+
|
574
|
+
def initialize(h={})
|
575
|
+
|
576
|
+
options = {
|
577
|
+
:'12_hour' => true
|
578
|
+
}
|
579
|
+
|
580
|
+
super(options.merge h)
|
581
|
+
|
582
|
+
end
|
583
|
+
|
584
|
+
def invoke()
|
585
|
+
time = ($env and $env[:time]) ? $env[:time] : Time.now
|
586
|
+
tformat = @h['12_hour'] ? "%-I:%M%P" : "%H:%M"
|
587
|
+
super(time.strftime(tformat))
|
588
|
+
end
|
589
|
+
|
590
|
+
def to_pc()
|
591
|
+
'say current_time()'
|
592
|
+
end
|
593
|
+
|
594
|
+
def to_s(colour: false)
|
595
|
+
'Say Current Time'
|
596
|
+
end
|
597
|
+
|
598
|
+
end
|
599
|
+
|
600
|
+
|
601
|
+
class DeviceAction < Action
|
602
|
+
|
603
|
+
def initialize(h={})
|
604
|
+
super(h)
|
605
|
+
@group = 'device'
|
606
|
+
end
|
607
|
+
|
608
|
+
end
|
609
|
+
|
610
|
+
# Category: Device Actions
|
611
|
+
#
|
612
|
+
class AndroidShortcutsAction < DeviceAction
|
613
|
+
|
614
|
+
def initialize(h={})
|
615
|
+
|
616
|
+
options = {
|
617
|
+
option: 1
|
618
|
+
}
|
619
|
+
|
620
|
+
super(options.merge h)
|
621
|
+
|
622
|
+
end
|
623
|
+
|
624
|
+
def to_s(colour: false)
|
625
|
+
'AndroidShortcutsAction ' + @h.inspect
|
626
|
+
end
|
627
|
+
|
628
|
+
alias to_summary to_s
|
629
|
+
end
|
630
|
+
|
631
|
+
# Category: Device Actions
|
632
|
+
#
|
633
|
+
class ClipboardAction < DeviceAction
|
634
|
+
|
635
|
+
def initialize(h={})
|
636
|
+
|
637
|
+
options = {
|
638
|
+
clipboard_text: ''
|
639
|
+
}
|
640
|
+
|
641
|
+
super(options.merge h)
|
642
|
+
|
643
|
+
end
|
644
|
+
|
645
|
+
def to_s(colour: false)
|
646
|
+
'ClipboardAction ' + @h.inspect
|
647
|
+
end
|
648
|
+
|
649
|
+
alias to_summary to_s
|
650
|
+
end
|
651
|
+
|
652
|
+
# Category: Device Actions
|
653
|
+
#
|
654
|
+
class PressBackAction < DeviceAction
|
655
|
+
|
656
|
+
def initialize(h={})
|
657
|
+
|
658
|
+
options = {
|
659
|
+
}
|
660
|
+
|
661
|
+
super(options.merge h)
|
662
|
+
|
663
|
+
end
|
664
|
+
|
665
|
+
def to_s(colour: false)
|
666
|
+
'PressBackAction ' + @h.inspect
|
667
|
+
end
|
668
|
+
|
669
|
+
alias to_summary to_s
|
670
|
+
end
|
671
|
+
|
672
|
+
# Category: Device Actions
|
673
|
+
#
|
674
|
+
class SpeakTextAction < DeviceAction
|
675
|
+
|
676
|
+
def initialize(h={})
|
677
|
+
|
678
|
+
options = {
|
679
|
+
text_to_say: '',
|
680
|
+
queue: false,
|
681
|
+
read_numbers_individually: false,
|
682
|
+
specify_audio_stream: false,
|
683
|
+
speed: 0.99,
|
684
|
+
pitch: 0.99,
|
685
|
+
wait_to_finish: false,
|
686
|
+
audio_stream: 0
|
687
|
+
}
|
688
|
+
|
689
|
+
super(options.merge h)
|
690
|
+
|
691
|
+
end
|
692
|
+
|
693
|
+
def to_s(colour: false)
|
694
|
+
"Speak Text (%s)" % @h[:text_to_say]
|
695
|
+
end
|
696
|
+
|
697
|
+
end
|
698
|
+
|
699
|
+
# Category: Device Actions
|
700
|
+
#
|
701
|
+
class UIInteractionAction < DeviceAction
|
702
|
+
|
703
|
+
def initialize(h={})
|
704
|
+
|
705
|
+
options = {
|
706
|
+
ui_interaction_configuration: {:type=>"Copy"},
|
707
|
+
action: 2
|
708
|
+
}
|
709
|
+
|
710
|
+
super(options.merge h)
|
711
|
+
|
712
|
+
end
|
713
|
+
|
714
|
+
def to_s(colour: false)
|
715
|
+
'UIInteractionAction ' + @h.inspect
|
716
|
+
end
|
717
|
+
|
718
|
+
alias to_summary to_s
|
719
|
+
end
|
720
|
+
|
721
|
+
# Category: Device Actions
|
722
|
+
#
|
723
|
+
class VoiceSearchAction < DeviceAction
|
724
|
+
|
725
|
+
def initialize(h={})
|
726
|
+
|
727
|
+
options = {
|
728
|
+
}
|
729
|
+
|
730
|
+
super(options.merge h)
|
731
|
+
|
732
|
+
end
|
733
|
+
|
734
|
+
def to_s(colour: false)
|
735
|
+
'VoiceSearchAction ' + @h.inspect
|
736
|
+
end
|
737
|
+
|
738
|
+
alias to_summary to_s
|
739
|
+
end
|
740
|
+
|
741
|
+
|
742
|
+
class DeviceSettingsAction < Action
|
743
|
+
|
744
|
+
def initialize(h={})
|
745
|
+
super(h)
|
746
|
+
@group = 'devicesettings'
|
747
|
+
end
|
748
|
+
|
749
|
+
end
|
750
|
+
|
751
|
+
# Category: Device Settings
|
752
|
+
#
|
753
|
+
class ExpandCollapseStatusBarAction < DeviceSettingsAction
|
754
|
+
|
755
|
+
def initialize(h={})
|
756
|
+
|
757
|
+
options = {
|
758
|
+
option: 0
|
759
|
+
}
|
760
|
+
|
761
|
+
super(options.merge h)
|
762
|
+
|
763
|
+
end
|
764
|
+
|
765
|
+
def to_s(colour: false)
|
766
|
+
'ExpandCollapseStatusBarAction ' + @h.inspect
|
767
|
+
end
|
768
|
+
|
769
|
+
alias to_summary to_s
|
770
|
+
end
|
771
|
+
|
772
|
+
# Category: Device Settings
|
773
|
+
#
|
774
|
+
class LaunchHomeScreenAction < DeviceSettingsAction
|
775
|
+
|
776
|
+
def initialize(h={})
|
777
|
+
|
778
|
+
options = {
|
779
|
+
}
|
780
|
+
|
781
|
+
super(options.merge h)
|
782
|
+
|
783
|
+
end
|
784
|
+
|
785
|
+
def to_s(colour: false)
|
786
|
+
'LaunchHomeScreenAction ' + @h.inspect
|
787
|
+
end
|
788
|
+
|
789
|
+
alias to_summary to_s
|
790
|
+
end
|
791
|
+
|
792
|
+
# Category: Device Settings
|
793
|
+
#
|
794
|
+
class CameraFlashLightAction < DeviceSettingsAction
|
795
|
+
|
796
|
+
def initialize(h={})
|
797
|
+
|
798
|
+
options = {
|
799
|
+
launch_foreground: false,
|
800
|
+
state: 0
|
801
|
+
}
|
802
|
+
|
803
|
+
super(options.merge h)
|
804
|
+
|
805
|
+
end
|
806
|
+
|
807
|
+
def to_pc()
|
808
|
+
['torch :on', 'torch :off', 'torch :toggle'][@h[:state]]
|
809
|
+
end
|
810
|
+
|
811
|
+
def to_s(colour: false)
|
812
|
+
['Torch On', 'Torch Off', 'Torch Toggle'][@h[:state]]
|
813
|
+
end
|
814
|
+
|
815
|
+
end
|
816
|
+
|
817
|
+
# Category: Device Settings
|
818
|
+
#
|
819
|
+
class VibrateAction < DeviceSettingsAction
|
820
|
+
|
821
|
+
def initialize(h={})
|
822
|
+
|
823
|
+
options = {
|
824
|
+
vibrate_pattern: 1
|
825
|
+
}
|
826
|
+
|
827
|
+
super(options.merge h)
|
828
|
+
|
829
|
+
end
|
830
|
+
|
831
|
+
def to_s(colour: false)
|
832
|
+
|
833
|
+
pattern = [
|
834
|
+
'Blip', 'Short Buzz', 'Long Buzz', 'Rapid', 'Slow', 'Increasing',
|
835
|
+
'Constant', 'Decreasing', 'Final Fantasy', 'Game Over', 'Star Wars',
|
836
|
+
'Mini Blip', 'Micro Blip'
|
837
|
+
]
|
838
|
+
|
839
|
+
'Vibrate ' + "(%s)" % pattern[@h[:vibrate_pattern].to_i]
|
840
|
+
end
|
841
|
+
|
842
|
+
end
|
843
|
+
|
844
|
+
# Category: Device Settings
|
845
|
+
#
|
846
|
+
class SetAutoRotateAction < DeviceSettingsAction
|
847
|
+
|
848
|
+
def initialize(h={})
|
849
|
+
|
850
|
+
options = {
|
851
|
+
state: 0
|
852
|
+
}
|
853
|
+
|
854
|
+
super(options.merge h)
|
855
|
+
|
856
|
+
end
|
857
|
+
|
858
|
+
def to_s(colour: false)
|
859
|
+
'SetAutoRotateAction ' + @h.inspect
|
860
|
+
end
|
861
|
+
|
862
|
+
alias to_summary to_s
|
863
|
+
end
|
864
|
+
|
865
|
+
# Category: Device Settings
|
866
|
+
#
|
867
|
+
class DayDreamAction < DeviceSettingsAction
|
868
|
+
|
869
|
+
def initialize(h={})
|
870
|
+
|
871
|
+
options = {
|
872
|
+
}
|
873
|
+
|
874
|
+
super(options.merge h)
|
875
|
+
|
876
|
+
end
|
877
|
+
|
878
|
+
def to_s(colour: false)
|
879
|
+
'DayDreamAction ' + @h.inspect
|
880
|
+
end
|
881
|
+
|
882
|
+
alias to_summary to_s
|
883
|
+
end
|
884
|
+
|
885
|
+
# Category: Device Settings
|
886
|
+
#
|
887
|
+
class SetKeyboardAction < DeviceSettingsAction
|
888
|
+
|
889
|
+
def initialize(h={})
|
890
|
+
|
891
|
+
options = {
|
892
|
+
}
|
893
|
+
|
894
|
+
super(options.merge h)
|
895
|
+
|
896
|
+
end
|
897
|
+
|
898
|
+
def to_s(colour: false)
|
899
|
+
'SetKeyboardAction ' + @h.inspect
|
900
|
+
end
|
901
|
+
|
902
|
+
alias to_summary to_s
|
903
|
+
end
|
904
|
+
|
905
|
+
# Category: Device Settings
|
906
|
+
#
|
907
|
+
class SetKeyguardAction < DeviceSettingsAction
|
908
|
+
|
909
|
+
def initialize(h={})
|
910
|
+
|
911
|
+
options = {
|
912
|
+
keyguard_on: true
|
913
|
+
}
|
914
|
+
|
915
|
+
super(options.merge h)
|
916
|
+
|
917
|
+
end
|
918
|
+
|
919
|
+
def to_s(colour: false)
|
920
|
+
'SetKeyguardAction ' + @h.inspect
|
921
|
+
end
|
922
|
+
|
923
|
+
alias to_summary to_s
|
924
|
+
end
|
925
|
+
|
926
|
+
# Category: Device Settings
|
927
|
+
#
|
928
|
+
class CarModeAction < DeviceSettingsAction
|
929
|
+
|
930
|
+
def initialize(h={})
|
931
|
+
|
932
|
+
options = {
|
933
|
+
option: 0
|
934
|
+
}
|
935
|
+
|
936
|
+
super(options.merge h)
|
937
|
+
|
938
|
+
end
|
939
|
+
|
940
|
+
def to_s(colour: false)
|
941
|
+
'CarModeAction ' + @h.inspect
|
942
|
+
end
|
943
|
+
|
944
|
+
alias to_summary to_s
|
945
|
+
end
|
946
|
+
|
947
|
+
# Category: Device Settings
|
948
|
+
#
|
949
|
+
class ChangeKeyboardAction < DeviceSettingsAction
|
950
|
+
|
951
|
+
def initialize(h={})
|
952
|
+
|
953
|
+
options = {
|
954
|
+
keyboard_id: 'com.android.inputmethod.latin/.LatinIME',
|
955
|
+
keyboard_name: 'Android Keyboard (AOSP)'
|
956
|
+
}
|
957
|
+
|
958
|
+
super(options.merge h)
|
959
|
+
|
960
|
+
end
|
961
|
+
|
962
|
+
def to_s(colour: false)
|
963
|
+
'ChangeKeyboardAction ' + @h.inspect
|
964
|
+
end
|
965
|
+
|
966
|
+
alias to_summary to_s
|
967
|
+
end
|
968
|
+
|
969
|
+
# Category: Device Settings
|
970
|
+
#
|
971
|
+
class SetWallpaperAction < DeviceSettingsAction
|
972
|
+
|
973
|
+
def initialize(h={})
|
974
|
+
|
975
|
+
options = {
|
976
|
+
image_name: '6051449505275476553',
|
977
|
+
s_screen_options: ["Home Screen", "Lock Screen", "Home + Lock Screen"],
|
978
|
+
s_options: ["Image", "Live Wallpaper (Preview Screen)"],
|
979
|
+
wallpaper_uri_string: 'content://media/external/images/media/928',
|
980
|
+
screen_option: 0,
|
981
|
+
option: 0
|
982
|
+
}
|
983
|
+
|
984
|
+
super(options.merge h)
|
985
|
+
|
986
|
+
end
|
987
|
+
|
988
|
+
def to_s(colour: false)
|
989
|
+
'SetWallpaperAction ' + @h.inspect
|
990
|
+
end
|
991
|
+
|
992
|
+
alias to_summary to_s
|
993
|
+
end
|
994
|
+
|
995
|
+
class FileAction < Action
|
996
|
+
|
997
|
+
def initialize(h={})
|
998
|
+
super(h)
|
999
|
+
@group = 'file'
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
# Category: Files
|
1005
|
+
#
|
1006
|
+
class OpenFileAction < FileAction
|
1007
|
+
|
1008
|
+
def initialize(h={})
|
1009
|
+
|
1010
|
+
options = {
|
1011
|
+
app_name: '',
|
1012
|
+
class_name: '',
|
1013
|
+
package_name: '',
|
1014
|
+
file_path: ''
|
1015
|
+
}
|
1016
|
+
|
1017
|
+
super(options.merge h)
|
1018
|
+
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
def to_s(colour: false)
|
1022
|
+
'OpenFileAction ' + @h.inspect
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
alias to_summary to_s
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
|
1029
|
+
class LocationAction < Action
|
1030
|
+
|
1031
|
+
def initialize(h={})
|
1032
|
+
super(h)
|
1033
|
+
@group = 'location'
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
# Category: Location
|
1039
|
+
#
|
1040
|
+
class ForceLocationUpdateAction < LocationAction
|
1041
|
+
|
1042
|
+
def initialize(h={})
|
1043
|
+
|
1044
|
+
options = {
|
1045
|
+
}
|
1046
|
+
|
1047
|
+
super(options.merge h)
|
1048
|
+
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
def to_s(colour: false)
|
1052
|
+
'ForceLocationUpdateAction ' + @h.inspect
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
alias to_summary to_s
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
# Category: Location
|
1059
|
+
#
|
1060
|
+
class ShareLocationAction < LocationAction
|
1061
|
+
|
1062
|
+
def initialize(h={})
|
1063
|
+
|
1064
|
+
options = {
|
1065
|
+
email: '',
|
1066
|
+
variable: {:m_stringValue=>"", :m_name=>"", :m_decimalValue=>0.0, :isLocal=>true, :m_booleanValue=>false, :excludeFromLog=>false, :m_intValue=>0, :m_type=>2},
|
1067
|
+
sim_id: 0,
|
1068
|
+
output_channel: 5,
|
1069
|
+
old_variable_format: true
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
super(options.merge h)
|
1073
|
+
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
def to_s(colour: false)
|
1077
|
+
'ShareLocationAction ' + @h.inspect
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
alias to_summary to_s
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
# Category: Location
|
1084
|
+
#
|
1085
|
+
class SetLocationUpdateRateAction < LocationAction
|
1086
|
+
|
1087
|
+
def initialize(h={})
|
1088
|
+
|
1089
|
+
options = {
|
1090
|
+
update_rate: 0,
|
1091
|
+
update_rate_seconds: 600
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
super(options.merge h)
|
1095
|
+
|
1096
|
+
end
|
1097
|
+
|
1098
|
+
def to_s(colour: false)
|
1099
|
+
'SetLocationUpdateRateAction ' + @h.inspect
|
1100
|
+
end
|
1101
|
+
|
1102
|
+
alias to_summary to_s
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
class LoggingAction < Action
|
1106
|
+
|
1107
|
+
def initialize(h={})
|
1108
|
+
super(h)
|
1109
|
+
@group = 'logging'
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
# Category: Logging
|
1115
|
+
#
|
1116
|
+
class AddCalendarEntryAction < LoggingAction
|
1117
|
+
|
1118
|
+
def initialize(h={})
|
1119
|
+
|
1120
|
+
options = {
|
1121
|
+
title: '',
|
1122
|
+
duration_value: '0',
|
1123
|
+
calendar_id: '3',
|
1124
|
+
detail: '',
|
1125
|
+
availability: 0,
|
1126
|
+
fixed_days: 16,
|
1127
|
+
fixed_hour: 0,
|
1128
|
+
fixed_minute: 0,
|
1129
|
+
fixed_months: 8,
|
1130
|
+
fixed_time: true,
|
1131
|
+
relative_days: 0,
|
1132
|
+
relative_hours: 0,
|
1133
|
+
relative_minutes: 0,
|
1134
|
+
all_day_event: true
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
super(options.merge h)
|
1138
|
+
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
def to_s(colour: false)
|
1142
|
+
'AddCalendarEntryAction ' + @h.inspect
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
alias to_summary to_s
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
# Category: Logging
|
1149
|
+
#
|
1150
|
+
class LogAction < LoggingAction
|
1151
|
+
|
1152
|
+
def initialize(h={})
|
1153
|
+
|
1154
|
+
options = {
|
1155
|
+
log_text: '',
|
1156
|
+
log_date_and_time: true
|
1157
|
+
}
|
1158
|
+
|
1159
|
+
super(options.merge h)
|
1160
|
+
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
def to_s(colour: false)
|
1164
|
+
'LogAction ' + @h.inspect
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
alias to_summary to_s
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
# Category: Logging
|
1171
|
+
#
|
1172
|
+
class ClearLogAction < LoggingAction
|
1173
|
+
|
1174
|
+
def initialize(h={})
|
1175
|
+
|
1176
|
+
options = {
|
1177
|
+
user_log: true
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
super(options.merge h)
|
1181
|
+
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
def to_s(colour: false)
|
1185
|
+
'ClearLogAction ' + @h.inspect
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
alias to_summary to_s
|
1189
|
+
end
|
1190
|
+
|
1191
|
+
# MacroDroid Specific
|
1192
|
+
#
|
1193
|
+
class ExportMacrosAction < Action
|
1194
|
+
|
1195
|
+
def initialize(h={})
|
1196
|
+
|
1197
|
+
options = {
|
1198
|
+
file_path: "", path_uri: ""
|
1199
|
+
}
|
1200
|
+
super(h)
|
1201
|
+
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
def to_s(colour: false)
|
1205
|
+
|
1206
|
+
'Export macros'
|
1207
|
+
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
alias to_summary to_s
|
1211
|
+
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
class PauseAction < Action
|
1215
|
+
|
1216
|
+
def initialize(h={})
|
1217
|
+
|
1218
|
+
options = {
|
1219
|
+
delay_in_milli_seconds: 0, delay_in_seconds: 1, use_alarm: false
|
1220
|
+
}
|
1221
|
+
super(h)
|
1222
|
+
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
def to_s(colour: false)
|
1226
|
+
|
1227
|
+
su = Subunit.new(units={minutes:60, hours:60},
|
1228
|
+
seconds: @h[:delay_in_seconds])
|
1229
|
+
|
1230
|
+
ms = @h[:delay_in_milli_seconds]
|
1231
|
+
|
1232
|
+
duration = if su.to_h.has_key?(:minutes) or (ms < 1) then
|
1233
|
+
su.strfunit("%X")
|
1234
|
+
else
|
1235
|
+
"%s %s ms" % [su.strfunit("%X"), ms]
|
1236
|
+
end
|
1237
|
+
|
1238
|
+
"Wait " + duration
|
1239
|
+
end
|
1240
|
+
|
1241
|
+
end
|
1242
|
+
|
1243
|
+
class MediaAction < Action
|
1244
|
+
|
1245
|
+
def initialize(h={})
|
1246
|
+
super(h)
|
1247
|
+
@group = 'media'
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
end
|
1251
|
+
|
1252
|
+
# Category: Media
|
1253
|
+
#
|
1254
|
+
class RecordMicrophoneAction < MediaAction
|
1255
|
+
|
1256
|
+
def initialize(h={})
|
1257
|
+
|
1258
|
+
options = {
|
1259
|
+
path: '/storage/emulated/0/MacroDroid/Recordings',
|
1260
|
+
record_time_string: 'Cancel Recording',
|
1261
|
+
recording_format: 0,
|
1262
|
+
seconds_to_record_for: -2
|
1263
|
+
}
|
1264
|
+
|
1265
|
+
super(options.merge h)
|
1266
|
+
|
1267
|
+
end
|
1268
|
+
|
1269
|
+
def to_s(colour: false)
|
1270
|
+
'RecordMicrophoneAction ' + @h.inspect
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
alias to_summary to_s
|
1274
|
+
end
|
1275
|
+
|
1276
|
+
# Category: Media
|
1277
|
+
#
|
1278
|
+
class PlaySoundAction < MediaAction
|
1279
|
+
|
1280
|
+
def initialize(h={})
|
1281
|
+
|
1282
|
+
options = {
|
1283
|
+
selected_index: 0,
|
1284
|
+
file_path: ''
|
1285
|
+
}
|
1286
|
+
|
1287
|
+
super(options.merge h)
|
1288
|
+
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
def to_s(colour: false)
|
1292
|
+
'Play: ' + @h[:file_path]
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
end
|
1296
|
+
|
1297
|
+
|
1298
|
+
class MessagingAction < Action
|
1299
|
+
|
1300
|
+
def initialize(h={})
|
1301
|
+
super(h)
|
1302
|
+
@group = 'messaging'
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
end
|
1306
|
+
|
1307
|
+
# Category: Messaging
|
1308
|
+
#
|
1309
|
+
class SendEmailAction < MessagingAction
|
1310
|
+
|
1311
|
+
def initialize(h={})
|
1312
|
+
|
1313
|
+
options = {
|
1314
|
+
subject: '',
|
1315
|
+
body: '',
|
1316
|
+
email_address: '',
|
1317
|
+
from_email_address: '',
|
1318
|
+
attach_user_log: false,
|
1319
|
+
attach_log: false,
|
1320
|
+
send_option: 0
|
1321
|
+
}
|
1322
|
+
|
1323
|
+
super(options.merge h)
|
1324
|
+
|
1325
|
+
end
|
1326
|
+
|
1327
|
+
def to_s(colour: false)
|
1328
|
+
'SendEmailAction ' + @h.inspect
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
alias to_summary to_s
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
# Category: Messaging
|
1335
|
+
#
|
1336
|
+
class SendSMSAction < MessagingAction
|
1337
|
+
|
1338
|
+
def initialize(h={})
|
1339
|
+
|
1340
|
+
options = {
|
1341
|
+
number: '',
|
1342
|
+
contact: {:m_id=>"Hardwired_Number", :m_lookupKey=>"Hardwired_Number", :m_name=>"[Select Number]"},
|
1343
|
+
message_content: '',
|
1344
|
+
add_to_message_log: false,
|
1345
|
+
pre_populate: false,
|
1346
|
+
sim_id: 0
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
super(options.merge h)
|
1350
|
+
|
1351
|
+
end
|
1352
|
+
|
1353
|
+
def to_s(colour: false)
|
1354
|
+
'SendSMSAction ' + @h.inspect
|
1355
|
+
end
|
1356
|
+
|
1357
|
+
alias to_summary to_s
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
# Category: Messaging
|
1361
|
+
#
|
1362
|
+
class UDPCommandAction < MessagingAction
|
1363
|
+
|
1364
|
+
def initialize(h={})
|
1365
|
+
|
1366
|
+
options = {
|
1367
|
+
destination: '',
|
1368
|
+
message: '',
|
1369
|
+
port: 1024
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
super(options.merge h)
|
1373
|
+
|
1374
|
+
end
|
1375
|
+
|
1376
|
+
def to_s(colour: false)
|
1377
|
+
'UDPCommandAction ' + @h.inspect
|
1378
|
+
end
|
1379
|
+
|
1380
|
+
alias to_summary to_s
|
1381
|
+
end
|
1382
|
+
|
1383
|
+
|
1384
|
+
class NotificationsAction < Action
|
1385
|
+
|
1386
|
+
def initialize(h={})
|
1387
|
+
super(h)
|
1388
|
+
@group = 'notifications'
|
1389
|
+
end
|
1390
|
+
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
# Category: Notifications
|
1394
|
+
#
|
1395
|
+
class ClearNotificationsAction < NotificationsAction
|
1396
|
+
|
1397
|
+
def initialize(h={})
|
1398
|
+
|
1399
|
+
options = {
|
1400
|
+
package_name_list: [],
|
1401
|
+
match_text: '',
|
1402
|
+
application_name_list: [],
|
1403
|
+
clear_persistent: false,
|
1404
|
+
excludes: false,
|
1405
|
+
match_option: 0,
|
1406
|
+
age_in_seconds: 0,
|
1407
|
+
option: 0,
|
1408
|
+
enable_regex: false
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
super(options.merge h)
|
1412
|
+
|
1413
|
+
end
|
1414
|
+
|
1415
|
+
def to_s(colour: false)
|
1416
|
+
'ClearNotificationsAction ' + @h.inspect
|
1417
|
+
end
|
1418
|
+
|
1419
|
+
alias to_summary to_s
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
# Category: Notifications
|
1423
|
+
#
|
1424
|
+
class MessageDialogAction < NotificationsAction
|
1425
|
+
|
1426
|
+
def initialize(h={})
|
1427
|
+
|
1428
|
+
options = {
|
1429
|
+
secondary_class_type: 'MessageDialogAction',
|
1430
|
+
ringtone_name: 'Default',
|
1431
|
+
notification_text: '',
|
1432
|
+
notification_subject: '',
|
1433
|
+
macro_guid_to_run: -0,
|
1434
|
+
notification_channel_type: 0,
|
1435
|
+
image_resource_id: 0,
|
1436
|
+
overwrite_existing: false,
|
1437
|
+
priority: 0,
|
1438
|
+
ringtone_index: 0,
|
1439
|
+
icon_bg_color: -1762269,
|
1440
|
+
run_macro_when_pressed: false
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
super(options.merge h)
|
1444
|
+
|
1445
|
+
end
|
1446
|
+
|
1447
|
+
def to_s(colour: false)
|
1448
|
+
'Display Dialog' + "\n Battery at: [battery]"
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
end
|
1452
|
+
|
1453
|
+
# Category: Notifications
|
1454
|
+
#
|
1455
|
+
class AllowLEDNotificationLightAction < NotificationsAction
|
1456
|
+
|
1457
|
+
def initialize(h={})
|
1458
|
+
|
1459
|
+
options = {
|
1460
|
+
enabled: true
|
1461
|
+
}
|
1462
|
+
|
1463
|
+
super(options.merge h)
|
1464
|
+
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
def to_s(colour: false)
|
1468
|
+
'AllowLEDNotificationLightAction ' + @h.inspect
|
1469
|
+
end
|
1470
|
+
|
1471
|
+
alias to_summary to_s
|
1472
|
+
end
|
1473
|
+
|
1474
|
+
# Category: Notifications
|
1475
|
+
#
|
1476
|
+
class SetNotificationSoundAction < NotificationsAction
|
1477
|
+
|
1478
|
+
def initialize(h={})
|
1479
|
+
|
1480
|
+
options = {
|
1481
|
+
ringtone_uri: 'content://media/internal/audio/media/27'
|
1482
|
+
}
|
1483
|
+
|
1484
|
+
super(options.merge h)
|
1485
|
+
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
def to_s(colour: false)
|
1489
|
+
'SetNotificationSoundAction ' + @h.inspect
|
1490
|
+
end
|
1491
|
+
|
1492
|
+
alias to_summary to_s
|
1493
|
+
end
|
1494
|
+
|
1495
|
+
# Category: Notifications
|
1496
|
+
#
|
1497
|
+
class SetNotificationSoundAction < NotificationsAction
|
1498
|
+
|
1499
|
+
def initialize(h={})
|
1500
|
+
|
1501
|
+
options = {
|
1502
|
+
ringtone_uri: 'content://media/internal/audio/media/51'
|
1503
|
+
}
|
1504
|
+
|
1505
|
+
super(options.merge h)
|
1506
|
+
|
1507
|
+
end
|
1508
|
+
|
1509
|
+
def to_s(colour: false)
|
1510
|
+
'SetNotificationSoundAction ' + @h.inspect
|
1511
|
+
end
|
1512
|
+
|
1513
|
+
alias to_summary to_s
|
1514
|
+
end
|
1515
|
+
|
1516
|
+
# Category: Notifications
|
1517
|
+
#
|
1518
|
+
class SetNotificationSoundAction < NotificationsAction
|
1519
|
+
|
1520
|
+
def initialize(h={})
|
1521
|
+
|
1522
|
+
options = {
|
1523
|
+
ringtone_name: 'None'
|
1524
|
+
}
|
1525
|
+
|
1526
|
+
super(options.merge h)
|
1527
|
+
|
1528
|
+
end
|
1529
|
+
|
1530
|
+
def to_s(colour: false)
|
1531
|
+
'SetNotificationSoundAction ' + @h.inspect
|
1532
|
+
end
|
1533
|
+
|
1534
|
+
alias to_summary to_s
|
1535
|
+
end
|
1536
|
+
|
1537
|
+
# Category: Notifications
|
1538
|
+
#
|
1539
|
+
class NotificationAction < NotificationsAction
|
1540
|
+
|
1541
|
+
def initialize(h={})
|
1542
|
+
|
1543
|
+
h[:notification_subject] = h[:subject] if h[:subject]
|
1544
|
+
h[:notification_text] = h[:text] if h[:text]
|
1545
|
+
|
1546
|
+
options = {
|
1547
|
+
ringtone_name: 'Default',
|
1548
|
+
notification_text: '',
|
1549
|
+
notification_subject: '',
|
1550
|
+
macro_guid_to_run: 0,
|
1551
|
+
notification_channel_type: 0,
|
1552
|
+
image_resource_id: 0,
|
1553
|
+
overwrite_existing: false,
|
1554
|
+
priority: 0,
|
1555
|
+
ringtone_index: 0,
|
1556
|
+
icon_bg_color: -1762269,
|
1557
|
+
run_macro_when_pressed: false
|
1558
|
+
}
|
1559
|
+
|
1560
|
+
super(options.merge filter(options, h))
|
1561
|
+
|
1562
|
+
end
|
1563
|
+
|
1564
|
+
def to_s(colour: false)
|
1565
|
+
"Display Notification\n " + \
|
1566
|
+
"%s: %s" % [@h[:notification_subject], @h[:notification_text]]
|
1567
|
+
end
|
1568
|
+
|
1569
|
+
end
|
1570
|
+
|
1571
|
+
# Category: Notifications
|
1572
|
+
#
|
1573
|
+
class ToastAction < NotificationsAction
|
1574
|
+
|
1575
|
+
def initialize(h={})
|
1576
|
+
|
1577
|
+
if h[:msg] then
|
1578
|
+
h[:message_text] = h[:msg]
|
1579
|
+
h.delete :msg
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
options = {
|
1583
|
+
message_text: '',
|
1584
|
+
image_resource_name: 'launcher_no_border',
|
1585
|
+
image_package_name: 'com.arlosoft.macrodroid',
|
1586
|
+
image_name: 'launcher_no_border',
|
1587
|
+
duration: 0,
|
1588
|
+
display_icon: true,
|
1589
|
+
background_color: -12434878,
|
1590
|
+
position: 0
|
1591
|
+
}
|
1592
|
+
|
1593
|
+
super(options.merge h)
|
1594
|
+
|
1595
|
+
end
|
1596
|
+
|
1597
|
+
def invoke()
|
1598
|
+
super(@h[:message_text])
|
1599
|
+
end
|
1600
|
+
|
1601
|
+
def to_pc()
|
1602
|
+
"popup_message '%s'" % @h[:message_text]
|
1603
|
+
end
|
1604
|
+
|
1605
|
+
def to_s(colour: false)
|
1606
|
+
"Popup Message\n %s" % @h[:message_text]
|
1607
|
+
end
|
1608
|
+
|
1609
|
+
end
|
1610
|
+
|
1611
|
+
|
1612
|
+
class PhoneAction < Action
|
1613
|
+
|
1614
|
+
def initialize(h={})
|
1615
|
+
super(h)
|
1616
|
+
@group = 'phone'
|
1617
|
+
end
|
1618
|
+
|
1619
|
+
end
|
1620
|
+
|
1621
|
+
# Category: Phone
|
1622
|
+
#
|
1623
|
+
class AnswerCallAction < PhoneAction
|
1624
|
+
|
1625
|
+
def initialize(h={})
|
1626
|
+
|
1627
|
+
options = {
|
1628
|
+
selected_index: 0
|
1629
|
+
}
|
1630
|
+
|
1631
|
+
super(options.merge h)
|
1632
|
+
|
1633
|
+
end
|
1634
|
+
|
1635
|
+
def to_s(colour: false)
|
1636
|
+
@s = 'Answer Call' + "\n "
|
1637
|
+
super()
|
1638
|
+
end
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
# Category: Phone
|
1642
|
+
#
|
1643
|
+
class ClearCallLogAction < PhoneAction
|
1644
|
+
|
1645
|
+
def initialize(h={})
|
1646
|
+
|
1647
|
+
options = {
|
1648
|
+
non_contact: false,
|
1649
|
+
specific_contact: false,
|
1650
|
+
type: 0
|
1651
|
+
}
|
1652
|
+
|
1653
|
+
super(options.merge h)
|
1654
|
+
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
def to_s(colour: false)
|
1658
|
+
'ClearCallLogAction ' + @h.inspect
|
1659
|
+
end
|
1660
|
+
|
1661
|
+
alias to_summary to_s
|
1662
|
+
end
|
1663
|
+
|
1664
|
+
# Category: Phone
|
1665
|
+
#
|
1666
|
+
class OpenCallLogAction < PhoneAction
|
1667
|
+
|
1668
|
+
def initialize(h={})
|
1669
|
+
|
1670
|
+
options = {
|
1671
|
+
}
|
1672
|
+
|
1673
|
+
super(options.merge h)
|
1674
|
+
|
1675
|
+
end
|
1676
|
+
|
1677
|
+
def to_s(colour: false)
|
1678
|
+
'OpenCallLogAction ' + @h.inspect
|
1679
|
+
end
|
1680
|
+
|
1681
|
+
alias to_summary to_s
|
1682
|
+
end
|
1683
|
+
|
1684
|
+
# Category: Phone
|
1685
|
+
#
|
1686
|
+
class RejectCallAction < PhoneAction
|
1687
|
+
|
1688
|
+
def initialize(h={})
|
1689
|
+
|
1690
|
+
options = {
|
1691
|
+
}
|
1692
|
+
|
1693
|
+
super(options.merge h)
|
1694
|
+
|
1695
|
+
end
|
1696
|
+
|
1697
|
+
def to_s(colour: false)
|
1698
|
+
@s = 'Call Reject' + "\n "
|
1699
|
+
super()
|
1700
|
+
end
|
1701
|
+
|
1702
|
+
end
|
1703
|
+
|
1704
|
+
# Category: Phone
|
1705
|
+
#
|
1706
|
+
class MakeCallAction < PhoneAction
|
1707
|
+
|
1708
|
+
def initialize(h={})
|
1709
|
+
|
1710
|
+
options = {
|
1711
|
+
contact: {:m_id=>"Hardwired_Number", :m_lookupKey=>"Hardwired_Number", :m_name=>"[Select Number]"},
|
1712
|
+
number: ''
|
1713
|
+
}
|
1714
|
+
|
1715
|
+
super(options.merge h)
|
1716
|
+
|
1717
|
+
end
|
1718
|
+
|
1719
|
+
def to_s(colour: false)
|
1720
|
+
'MakeCallAction ' + @h.inspect
|
1721
|
+
end
|
1722
|
+
|
1723
|
+
alias to_summary to_s
|
1724
|
+
end
|
1725
|
+
|
1726
|
+
|
1727
|
+
# Category: Phone
|
1728
|
+
#
|
1729
|
+
class SetRingtoneAction < PhoneAction
|
1730
|
+
|
1731
|
+
def initialize(h={})
|
1732
|
+
|
1733
|
+
options = {
|
1734
|
+
ringtone_uri: 'content://media/internal/audio/media/174'
|
1735
|
+
}
|
1736
|
+
|
1737
|
+
super(options.merge h)
|
1738
|
+
|
1739
|
+
end
|
1740
|
+
|
1741
|
+
def to_s(colour: false)
|
1742
|
+
'SetRingtoneAction ' + @h.inspect
|
1743
|
+
end
|
1744
|
+
|
1745
|
+
alias to_summary to_s
|
1746
|
+
end
|
1747
|
+
|
1748
|
+
class ScreenAction < Action
|
1749
|
+
|
1750
|
+
def initialize(h={})
|
1751
|
+
super(h)
|
1752
|
+
@group = 'screen'
|
1753
|
+
end
|
1754
|
+
|
1755
|
+
end
|
1756
|
+
|
1757
|
+
# Category: Screen
|
1758
|
+
#
|
1759
|
+
class SetBrightnessAction < ScreenAction
|
1760
|
+
|
1761
|
+
def initialize(h={})
|
1762
|
+
|
1763
|
+
options = {
|
1764
|
+
brightness_percent: 81,
|
1765
|
+
force_pie_mode: false,
|
1766
|
+
brightness: 0
|
1767
|
+
}
|
1768
|
+
|
1769
|
+
super(options.merge h)
|
1770
|
+
|
1771
|
+
end
|
1772
|
+
|
1773
|
+
def to_s(colour: false)
|
1774
|
+
'SetBrightnessAction ' + @h.inspect
|
1775
|
+
end
|
1776
|
+
|
1777
|
+
alias to_summary to_s
|
1778
|
+
end
|
1779
|
+
|
1780
|
+
# Category: Screen
|
1781
|
+
#
|
1782
|
+
class ForceScreenRotationAction < ScreenAction
|
1783
|
+
|
1784
|
+
def initialize(h={})
|
1785
|
+
|
1786
|
+
options = {
|
1787
|
+
option: 0
|
1788
|
+
}
|
1789
|
+
|
1790
|
+
super(options.merge h)
|
1791
|
+
|
1792
|
+
end
|
1793
|
+
|
1794
|
+
def to_s(colour: false)
|
1795
|
+
'ForceScreenRotationAction ' + @h.inspect
|
1796
|
+
end
|
1797
|
+
|
1798
|
+
alias to_summary to_s
|
1799
|
+
end
|
1800
|
+
|
1801
|
+
# Category: Screen
|
1802
|
+
#
|
1803
|
+
class ScreenOnAction < ScreenAction
|
1804
|
+
|
1805
|
+
def initialize(h={})
|
1806
|
+
|
1807
|
+
options = {
|
1808
|
+
pie_lock_screen: false,
|
1809
|
+
screen_off: true,
|
1810
|
+
screen_off_no_lock: false,
|
1811
|
+
screen_on_alternative: false
|
1812
|
+
}
|
1813
|
+
|
1814
|
+
super(options.merge h)
|
1815
|
+
|
1816
|
+
end
|
1817
|
+
|
1818
|
+
def to_s(colour: false)
|
1819
|
+
|
1820
|
+
state = @h[:screen_off] ? 'Off' : 'On'
|
1821
|
+
state += ' ' + 'No Lock (root only)' if @h[:screen_off_no_lock]
|
1822
|
+
#state += ' ' + '(Alternative)' if @h[:screen_on_alternative]
|
1823
|
+
|
1824
|
+
'Screen ' + state
|
1825
|
+
|
1826
|
+
end
|
1827
|
+
|
1828
|
+
alias to_summary to_s
|
1829
|
+
end
|
1830
|
+
|
1831
|
+
# Category: Screen
|
1832
|
+
#
|
1833
|
+
class DimScreenAction < ScreenAction
|
1834
|
+
|
1835
|
+
def initialize(h={})
|
1836
|
+
|
1837
|
+
options = {
|
1838
|
+
percent: 50,
|
1839
|
+
dim_screen_on: true
|
1840
|
+
}
|
1841
|
+
|
1842
|
+
super(options.merge h)
|
1843
|
+
|
1844
|
+
end
|
1845
|
+
|
1846
|
+
def to_s(colour: false)
|
1847
|
+
'DimScreenAction ' + @h.inspect
|
1848
|
+
end
|
1849
|
+
|
1850
|
+
alias to_summary to_s
|
1851
|
+
end
|
1852
|
+
|
1853
|
+
# Category: Screen
|
1854
|
+
#
|
1855
|
+
# options:
|
1856
|
+
# keep awake, screen on => enabled: true
|
1857
|
+
# disable keep awake => enabled: false
|
1858
|
+
#
|
1859
|
+
class KeepAwakeAction < ScreenAction
|
1860
|
+
|
1861
|
+
def initialize(h={})
|
1862
|
+
|
1863
|
+
options = {
|
1864
|
+
enabled: true,
|
1865
|
+
permanent: true,
|
1866
|
+
screen_option: 0,
|
1867
|
+
seconds_to_stay_awake_for: 0
|
1868
|
+
}
|
1869
|
+
|
1870
|
+
super(options.merge h)
|
1871
|
+
|
1872
|
+
end
|
1873
|
+
|
1874
|
+
def to_s(colour: false)
|
1875
|
+
|
1876
|
+
screen = @h[:screen_option] == 0 ? 'Screen On' : 'Screen Off'
|
1877
|
+
|
1878
|
+
if @h[:enabled] then
|
1879
|
+
|
1880
|
+
whenx = if @h[:seconds_to_stay_awake_for] == 0 then
|
1881
|
+
|
1882
|
+
'Until Disabled'
|
1883
|
+
|
1884
|
+
else
|
1885
|
+
scnds = @h[:seconds_to_stay_awake_for]
|
1886
|
+
Subunit.new(units={minutes:60, hours:60}, seconds: scnds).strfunit("%x")
|
1887
|
+
end
|
1888
|
+
|
1889
|
+
"Keep Device Awake\n " + screen + ' - ' + whenx
|
1890
|
+
|
1891
|
+
else
|
1892
|
+
'Disable Keep Awake'
|
1893
|
+
end
|
1894
|
+
|
1895
|
+
|
1896
|
+
end
|
1897
|
+
end
|
1898
|
+
|
1899
|
+
# Category: Screen
|
1900
|
+
#
|
1901
|
+
class SetScreenTimeoutAction < ScreenAction
|
1902
|
+
|
1903
|
+
def initialize(h={})
|
1904
|
+
|
1905
|
+
options = {
|
1906
|
+
timeout_delay_string: '1 Minute',
|
1907
|
+
timeout_delay: 60,
|
1908
|
+
custom_value_delay: 0
|
1909
|
+
}
|
1910
|
+
|
1911
|
+
super(options.merge h)
|
1912
|
+
|
1913
|
+
end
|
1914
|
+
|
1915
|
+
def to_s(colour: false)
|
1916
|
+
'SetScreenTimeoutAction ' + @h.inspect
|
1917
|
+
end
|
1918
|
+
|
1919
|
+
alias to_summary to_s
|
1920
|
+
end
|
1921
|
+
|
1922
|
+
|
1923
|
+
class VolumeAction < Action
|
1924
|
+
|
1925
|
+
def initialize(h={})
|
1926
|
+
super(h)
|
1927
|
+
@group = 'volume'
|
1928
|
+
end
|
1929
|
+
|
1930
|
+
end
|
1931
|
+
|
1932
|
+
# Category: Volume
|
1933
|
+
#
|
1934
|
+
class SilentModeVibrateOffAction < VolumeAction
|
1935
|
+
|
1936
|
+
def initialize(h={})
|
1937
|
+
|
1938
|
+
options = {
|
1939
|
+
option: 1
|
1940
|
+
}
|
1941
|
+
|
1942
|
+
super(options.merge h)
|
1943
|
+
|
1944
|
+
end
|
1945
|
+
|
1946
|
+
def to_s(colour: false)
|
1947
|
+
'SilentModeVibrateOffAction ' + @h.inspect
|
1948
|
+
end
|
1949
|
+
|
1950
|
+
alias to_summary to_s
|
1951
|
+
end
|
1952
|
+
|
1953
|
+
# Category: Volume
|
1954
|
+
#
|
1955
|
+
class SetVibrateAction < VolumeAction
|
1956
|
+
|
1957
|
+
def initialize(h={})
|
1958
|
+
|
1959
|
+
options = {
|
1960
|
+
option: 'Silent (Vibrate On)',
|
1961
|
+
option_int: -1
|
1962
|
+
}
|
1963
|
+
|
1964
|
+
super(options.merge h)
|
1965
|
+
|
1966
|
+
end
|
1967
|
+
|
1968
|
+
def to_s(colour: false)
|
1969
|
+
|
1970
|
+
a = [
|
1971
|
+
'Silent (Vibrate On)',
|
1972
|
+
'Normal (Vibrate Off)',
|
1973
|
+
'Vibrate when ringing On',
|
1974
|
+
'Vibrate when ringing Off',
|
1975
|
+
'Vibrate when ringing Toggle'
|
1976
|
+
]
|
1977
|
+
|
1978
|
+
status = a[@h[:option_int]]
|
1979
|
+
@s = 'Vibrate Enable/Disable ' + "\n " + status + "\n "
|
1980
|
+
super()
|
1981
|
+
|
1982
|
+
end
|
1983
|
+
|
1984
|
+
def to_summary(colour: false)
|
1985
|
+
|
1986
|
+
@s = 'Vibrate Enable/Disable'
|
1987
|
+
|
1988
|
+
end
|
1989
|
+
end
|
1990
|
+
|
1991
|
+
# Category: Volume
|
1992
|
+
#
|
1993
|
+
class VolumeIncrementDecrementAction < VolumeAction
|
1994
|
+
|
1995
|
+
def initialize(h={})
|
1996
|
+
|
1997
|
+
options = {
|
1998
|
+
volume_up: true
|
1999
|
+
}
|
2000
|
+
|
2001
|
+
super(options.merge h)
|
2002
|
+
|
2003
|
+
end
|
2004
|
+
|
2005
|
+
def to_s(colour: false)
|
2006
|
+
'VolumeIncrementDecrementAction ' + @h.inspect
|
2007
|
+
end
|
2008
|
+
|
2009
|
+
alias to_summary to_s
|
2010
|
+
end
|
2011
|
+
|
2012
|
+
# Category: Volume
|
2013
|
+
#
|
2014
|
+
class SpeakerPhoneAction < VolumeAction
|
2015
|
+
|
2016
|
+
def initialize(h={})
|
2017
|
+
|
2018
|
+
options = {
|
2019
|
+
secondary_class_type: 'SpeakerPhoneAction',
|
2020
|
+
state: 0
|
2021
|
+
}
|
2022
|
+
|
2023
|
+
super(options.merge h)
|
2024
|
+
|
2025
|
+
end
|
2026
|
+
|
2027
|
+
def to_s(colour: false)
|
2028
|
+
'SpeakerPhoneAction ' + @h.inspect
|
2029
|
+
end
|
2030
|
+
|
2031
|
+
alias to_summary to_s
|
2032
|
+
end
|
2033
|
+
|
2034
|
+
# Category: Volume
|
2035
|
+
#
|
2036
|
+
class SetVolumeAction < VolumeAction
|
2037
|
+
|
2038
|
+
def initialize(h={})
|
2039
|
+
|
2040
|
+
options = {
|
2041
|
+
variables: [nil, nil, nil, nil, nil, nil, nil],
|
2042
|
+
stream_index_array: [false, false, false, false, false, false, true],
|
2043
|
+
stream_volume_array: [0, 0, 0, 0, 0, 0, 66],
|
2044
|
+
force_vibrate_off: false,
|
2045
|
+
volume: -1
|
2046
|
+
}
|
2047
|
+
|
2048
|
+
super(options.merge h)
|
2049
|
+
|
2050
|
+
end
|
2051
|
+
|
2052
|
+
def to_s(colour: false)
|
2053
|
+
volume = @h[:stream_index_array].zip(@h[:stream_volume_array]).to_h[true]
|
2054
|
+
'Volume Change ' + "Notification = %s%%" % volume
|
2055
|
+
end
|
2056
|
+
end
|