jw-automator 1.0.2 → 3.0.0

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.
package/automator.js DELETED
@@ -1,694 +0,0 @@
1
- /*
2
- ver 1.0.2 19-11-13
3
- -fixed DST-Standard time changeover bug
4
- ver 1.0.1 19-07-18
5
- -bug-fixes, 1.0.0 was actually non-functional...
6
- ver 1.0.0 19-06-27
7
- */
8
-
9
- 'use strict';
10
-
11
- var fs = require('fs'); //for saving state
12
-
13
- /**
14
- * Creates an automator
15
- *
16
- * @param {object} [options] - startup options
17
- * @param {Boolean} [options.save] - Should the automator save it's state
18
- * @param {string} [options.saveFile] - alternate path/file for save
19
- */
20
- function automator(options) {
21
- if (typeof options === 'undefined') { options = {}; }
22
- var _self = this;
23
-
24
- var _actions = []; //The actions to be automated
25
- var _functions = {}; //the functions that the automator can run
26
- var _saveFile = '.actions.json'; //default save path
27
- var _saveState = true;
28
- var _lastTickTime = Date.now(); //this works with action.unBuffered to prevent actions from being missed
29
- var _newTickTime = Date.now();
30
-
31
- if (options.saveFile) { _saveFile = options.saveFile; }
32
- if (!options.save) { _saveState = false; }
33
-
34
- //The timer always runs but it may be muted, i.e. will execute no actions, they
35
- //will however have their counters updated as if they were being run and will be
36
- //removed if their end dates pass
37
- //can be set directly by the client
38
- this.mute = false;
39
-
40
- //holds the timer reference
41
- //var _autoTimer = null;
42
-
43
- /******************* Custom Emitter Code **************************************************/
44
- //this is for potential browser compatibility
45
- var _events = {};
46
- this.on = function(event, callback) {
47
- //attaches a callback function to an event
48
- _events[event] = callback;
49
- };
50
- function emit(event, payload) {
51
- if (typeof _events[event] === 'function') { //the client has registered the event
52
- _events[event](payload); //run the event function provided
53
- }
54
- }
55
- /*******************************************************************************************/
56
-
57
- function debug(msg) {
58
- emit('debug', msg);
59
- }
60
-
61
- function startUp() {
62
- //first load the actions from file.
63
- //we're going to do this in sync mode because we want to guarantee that the file is loaded
64
- //before we start the automator and possibly accept a new action that is then overwritten
65
- //by the save file.
66
- if (_saveState) {
67
- try {
68
- _actions = JSON.parse(fs.readFileSync(_saveFile, 'utf8'));
69
- debug('Loaded save file');
70
- } catch (err) {
71
- debug('Save file does not exist yet.');
72
- }
73
- }
74
-
75
- // we want the tick to run exactly on the second, so calculate a wait period before starting
76
- var wait = 1000 - new Date(Date.now()).getMilliseconds();
77
- debug('Waiting ' + wait + ' milliseconds...');
78
- setTimeout(function() {
79
- emit('ready');
80
- tick();
81
- }, wait);
82
- }
83
-
84
- function tick() {
85
- _lastTickTime = _newTickTime;
86
- _newTickTime = Date.now();
87
- //run all the actions with:
88
- // -Date.now() set as the tick time with the milliseconds set to 0
89
- // -the opposite of this.mute set as the execute flag, so execute if this.mute = false
90
- // -run the callback with the list of actions run during this tick passed back
91
-
92
- _actions = executeAllActions(_actions, clearMilliSeconds(Date.now()), !_self.mute, function(actionsUpdated, actionsRun) {
93
- if (actionsUpdated) {
94
- emit('update'); //tell the client that the action list has updated
95
- if (_saveState) { saveActions(_actions); }
96
- }
97
- if (actionsRun.length > 0) {
98
- emit('action', actionsRun); //emit to any listening clients the list of actions run
99
- }
100
- });
101
-
102
- var wait = 1000-new Date(Date.now()).getMilliseconds();
103
- setTimeout(function() {
104
- tick();
105
- },wait);
106
- }
107
-
108
- function saveActions(actions) {
109
- //saves the actions object to a file
110
- fs.writeFile(_saveFile, JSON.stringify(actions), function(err) {
111
- if(err) { emit('error', 'Error saving actions: ' + err); }
112
- });
113
- }
114
-
115
- function clearMilliSeconds(date) {
116
- //returns a date object with the milliseconds set to 0
117
- date = new Date(date); //force a date object
118
- date.setMilliseconds(0); //clear the milliseconds
119
- return date;
120
- }
121
-
122
- function dateToMilliseconds(date) {
123
- //converts dates and date strings to milliseconds
124
- //more robust then Date.parse()
125
- return(Date.parse(new Date(date).toString()));
126
- }
127
-
128
- function checkActionLimit(action) {
129
- var removeAction = false;
130
- if (action.repeat) {
131
- //limit will be FALSE if it doesn't exist and also check if the limit is 0 (=no limit)
132
- if (action.repeat.limit && action.repeat.limit > 0) {
133
- if (action.repeat.count >= action.repeat.limit) {
134
- removeAction = true;
135
- }
136
- }
137
- }
138
-
139
- return removeAction;
140
- }
141
-
142
- function checkActionEndDate(action, now) {
143
- var removeAction = false;
144
- if (action.repeat) {
145
- if (action.repeat.endDate) { //endDate will be FALSE if it doesn't exist
146
- if (dateToMilliseconds(action.repeat.endDate < dateToMilliseconds(now))) {
147
- removeAction = true;
148
- }
149
- }
150
- }
151
-
152
- return removeAction;
153
- }
154
-
155
- function executeAllActions(actions, now, shouldExecute, callback) {
156
- //debug('execute actions...');
157
- //debug(JSON.stringify(actions));
158
-
159
- if (typeof shouldExecute === 'undefined') { shouldExecute = false; }
160
-
161
- //actions: the actions object to work with
162
- //now: the time of the tick (may be a virtual or test time)
163
- //shouldExecute: should the action actually run or just update
164
- //callback: function to execute when we complete
165
-
166
- var actionsUpdated = false; //to emit only when something changed
167
- var actionsRun = []; //a list of all the actions run this tick
168
- var actionInfo = {}; //the object saved in the actionRun array
169
- var dateOld = false; //test var for updating passed actions to the next tick in the future
170
-
171
- //MAIN LOOP:
172
- //we're going to iterate down so we can remove elements without messing up the iteration
173
- for (var i = actions.length; i--;) {
174
- //sanitize date (and force .date into a date object)
175
- actions[i].date = clearMilliSeconds(actions[i].date);
176
-
177
- //it's possible that we have failed to run actions that were proscribed, so what
178
- //we're going to do is virtually run this action until it's next run time is now
179
- //or in the future. This is important for actions that were intended to run for
180
- //a certain amount of executions starting at a particular time. Say every hour
181
- //for 4 hours starting at noon. If the automator is started at 3:00 it should only
182
- //run the action twice.
183
- //check if the date is in the past
184
- //pre-set the dateOld test for the while loop
185
- dateOld = dateToMilliseconds(actions[i].date) < dateToMilliseconds(now); //true if in the past
186
- while (dateOld) {
187
- //debug('date is in the past: ' + actions[i].date);
188
- //while the next action date is still in the past, increment it until it isn't
189
- //the action count will increase as if the action was run, but the action will not execute
190
- actionsUpdated = true; //something has changed, in this case the date of at least one action.
191
-
192
- //the false flag will keep the action from running, but will update it's timing
193
- //update the action, but don't run it's command, do increment its counter
194
- var run = false;
195
- //go ahead and run the action if it was missed and unBuffered = false
196
- if (actions[i].date > _lastTickTime && !actions[i].unBuffered) {
197
- run = true;
198
- } else {
199
-
200
- }
201
- actions[i] = executeAction(actions[i], run, true);
202
- dateOld = dateToMilliseconds(actions[i].date) < dateToMilliseconds(now); //check again
203
- }
204
- //the current action date is now in the future (or now, now being the time passed to the function)
205
- //check if the action's date is this tick
206
- if (dateToMilliseconds(actions[i].date) === dateToMilliseconds(now)) {
207
- //run the action command and increment the counter
208
- actions[i] = executeAction(actions[i], shouldExecute, true);
209
- actionsUpdated = true; //something has changed, in this case an action has run and it's date has updated
210
- //create a new actionInfo obj and add it to the list of actions that have run
211
- actionInfo = {
212
- id: actions[i].id,
213
- name: actions[i].name,
214
- date: now
215
- };
216
- actionsRun.push(actionInfo);
217
- }
218
-
219
- //now we will test if the actions are old/past limits, if either are true, remove it
220
- //also remove if repeat is set to false
221
- //pass the provided tick time as the "current" date in case the time is simulated
222
- if (checkActionLimit(actions[i]) || checkActionEndDate(actions[i], now) || !actions[i].repeat) {
223
- debug('>>>> Removed action: ' + actions[i].name + ' - ' + actions[i].id);
224
- debug(">>>> Limit: " + checkActionLimit(actions[i]));
225
- debug(">>>> Date: " + checkActionEndDate(actions[i], now));
226
- debug('>>>> Type: ' + typeof actions[i].repeat);
227
- actions.splice(i,1); //remove the offending action
228
- actionsUpdated = true; //something has changed, in this case the action list
229
-
230
- }
231
- } //END MAIN LOOP
232
-
233
- if (typeof callback === 'function') {
234
- callback(actionsUpdated, actionsRun); //callback with the list of actions run this tick
235
- }
236
-
237
- return actions; //return the updated actions object
238
- }
239
-
240
-
241
- function executeAction(action, execute, increment) {
242
- if (typeof execute === 'undefined') { execute = false; }
243
- if (typeof increment === 'undefined') { increment = true; }
244
-
245
- if (action.repeat) { //if the action has a repeat object
246
- //update the count, even if the action isn't set to run
247
- //set this to false if you are manually executing the action and don't want
248
- //this time to count against the total runs
249
- if (increment) {
250
- action.repeat.count++;
251
- }
252
-
253
- //get/set the next run time
254
- action.date = getNextActionTime(action.date, action.repeat);
255
- }
256
-
257
- if (execute) {
258
- debug('Time: ' + printDate(Date.now()));
259
- debug('Executing Action "' + action.name + '"...');
260
-
261
- //update the execute var even if there is no function to run
262
- action.repeat.executed ++;
263
-
264
- //run the cmd with the payload (make sure the cmd is a function first)
265
- //it will obviously not be if the cmd is not defined at all or if the user
266
- //didn't pass a "functions" object into the automator
267
- if (typeof _functions[action.cmd] === 'function') {
268
- try {
269
- _functions[action.cmd](action.payload);
270
- } catch (err) {
271
- emit('error','Problem executing action ' + action.name + ': ' + err);
272
- }
273
- } else {
274
- //emit('error', action.name + ' has no function.');
275
- }
276
- }
277
-
278
- return action; //return the modified action
279
- }
280
-
281
- function getNextActionTime(start, repeat) {
282
- //returns a new date based on a start date (may be a string) and a repeat options object.
283
-
284
- //if a repeat object isn't supplied or is false, return the start (same) time
285
- if (typeof repeat === 'undefined') { return new Date(start); }
286
-
287
- var dateStart = new Date(start); //convert input to valid date object
288
-
289
- //the following call breaks the DST->Standard time crossover, so for now don't do it
290
- //potentially if a user sets an action start time and includes milliseconds it might
291
- //break the action, not sure
292
- //dateStart.setMilliseconds(0); //since the minimum tick is 1 second;
293
-
294
- start = Date.parse(dateStart.toString()); //convert to milliseconds
295
- var nextTime = null; //by default there will be no next action time
296
- var inc = 0; //the number of milliseconds to increment by
297
- var i = 0;
298
- switch (repeat.type) {
299
- case 'second':
300
- inc = 1000 * repeat.interval;
301
- break;
302
- case 'minute':
303
- inc = (1000 * 60) * repeat.interval;
304
- break;
305
- case 'hour':
306
- inc = (1000 * 60 * 60) * repeat.interval;
307
- break;
308
- case 'day':
309
- inc = (1000 * 60 * 60 * 24) * repeat.interval;
310
- break;
311
- case 'week':
312
- inc = (1000 * 60 * 60 * 24 * 7) * repeat.interval;
313
- break;
314
- case 'month':
315
- dateStart.setMonth(dateStart.getMonth() + repeat.interval);
316
- start = Date.parse(dateStart.toString());
317
- inc = 0;
318
- break;
319
- case 'year':
320
- //12 months in a year
321
- dateStart.setMonth(dateStart.getMonth() + (repeat.interval * 12));
322
- start = Date.parse(dateStart.toString());
323
- inc = 0;
324
- break;
325
- case 'weekday':
326
- while (i<repeat.interval) {
327
- //we're going to iterate ahead 1 day at a time manually until we get to the interval
328
- //if we hit a weekend date (Sun=0, Sat=6) then we're going to jump ahead the
329
- //appropriate amount to the next weekday.
330
- dateStart.setDate(dateStart.getDate() + 1); //increment the day by one
331
-
332
- if (dateStart.getDay() == 0) { //we've hit sun, extra inc by 1 day
333
- dateStart.setDate(dateStart.getDate() + 1);
334
- }
335
- if (dateStart.getDay() == 6) { //we've hit sat, extra inc by 2 day
336
- dateStart.setDate(dateStart.getDate() + 2);
337
- }
338
- i++; //next day
339
- }
340
- start = Date.parse(dateStart.toString());
341
- inc = 0;
342
- break;
343
- case 'weekend':
344
- while (i<repeat.interval) {
345
- //similar to weekdays we will increment manually through each day, but this time
346
- //we will jump the weekdays by adding the number of days necessary to get to the
347
- //next weekend
348
- dateStart.setDate(dateStart.getDate() + 1); //increment the day by one
349
- //if the day is 1-5 (Mon-Fri)
350
- if (dateStart.getDay() > 0 && dateStart.getDay() < 6) {
351
- //add the needed days to get to the weekend (6 minus today's day#)
352
- dateStart.setDate(dateStart.getDate() + (6-dateStart.getDay()));
353
- }
354
- i++; //next day
355
- }
356
- start = Date.parse(dateStart.toString());
357
- inc = 0;
358
- break;
359
-
360
- }
361
-
362
- nextTime = new Date(start + inc);
363
- return nextTime; //returns a date object
364
- }
365
-
366
-
367
- function printDate(date) {
368
- date = new Date(date);
369
- var days = ['Sun','Mon','Tues','Wed','Thurs','Fri','Sat'];
370
- var ds = days[date.getDay()] + ' ' + date.getFullYear() + '/' + parseInt(date.getMonth() + 1) + '/';
371
- if (date.getDate() < 10) { ds +=0; }
372
- ds += date.getDate();
373
- ds += ' ' + date.getHours() + ':';
374
- if (date.getMinutes() < 10) { ds +=0; }
375
- ds += date.getMinutes() + ':';
376
- if (date.getSeconds() < 10) { ds +=0; }
377
- ds += date.getSeconds();
378
-
379
- return ds; //a string
380
- }
381
-
382
- function updateAction(oldAction, newAction) {
383
- Object.keys(newAction).forEach(function(key) {
384
- oldAction[key] = newAction[key];
385
- });
386
- }
387
-
388
-
389
- /******************* Public functions **************************************************/
390
-
391
- /**
392
- * Start the Automator
393
- */
394
- this.start = function() {
395
- startUp();
396
- };
397
-
398
- /**
399
- * Add an action to the automator
400
- * @param {object} action
401
- * @param {string} action.name - Name of the action
402
- * @param {string|object} [action.date] - The start time. Blank for now
403
- * @param {string} [action.cmd] - The name of the function (from addFunction)
404
- * @param {string} [action.payload] - The param to pass to the cmd (use JSON for multi-var)
405
- * @param {boolean} [action.unBuffered] - If true actions missed due to delays will be skipped
406
- * @param {object} [action.repeat] - Define how the action should repeat
407
- * @param {'second'|'minute'|'hour'|'day'|'week'|'month'|'year'|'weekday'|'weekend'} [action.repeat.type] - How should the action repeat
408
- * @param {number} [action.repeat.interval] - 3 means run every 3rd interval, etc...
409
- * @param {number} [action.repeat.count] - Usually not needed, how many times the action has already run
410
- * @param {number|boolean} [action.repeat.limit] - Total number of times to run
411
- * @param {string} [action.repeat.endDate] - The date/time to remove the action
412
- */
413
- this.addAction = function(action) {
414
- if (!action.date) {
415
- action.date = new Date();
416
- action.date.setSeconds(action.date.getSeconds() + 1 );
417
- }
418
- /* should we allow undefined actions? Maybe yes for calendar entry support....
419
- if (!action.cmd) {
420
- emit('error','No action cmd provided');
421
- return undefined;
422
- }
423
- */
424
- action.date = clearMilliSeconds(action.date); //force a date object and clear the seconds
425
- if (action.repeat) {
426
- if (action.repeat.endDate) {
427
- action.repeat.endDate = clearMilliSeconds(action.repeat.endDate);
428
- }
429
- // @ts-ignore
430
- action.repeat.executed = 0;
431
- }
432
-
433
- // @ts-ignore
434
- action.id = Date.now(); //will always be a unique ID
435
- _actions.push(action); //add the new action to the global list
436
- if (_saveState) { saveActions(_actions); }//save the new actions to a file
437
-
438
- //run the newly added action if its first tick is now
439
- //actually, don't. This causes more problems then it solves and the need is minimal
440
- /*
441
- if (dateToMilliseconds(action.date) === dateToMilliseconds(clearMilliSeconds(Date.now()))) {
442
- action = executeAction(action, true);
443
- //emit a list of just this one action being run to the client
444
- emit('action',
445
- [
446
- {
447
- // @ts-ignore
448
- id: action.id,
449
- name: action.name,
450
- date: clearMilliSeconds(Date.now())
451
- }
452
- ]
453
- );
454
- }
455
- */
456
-
457
- };
458
-
459
- /**
460
- * @returns {object} - A copy of the automator actions
461
- */
462
- this.getActions = function() {
463
- //return a copy not the actual object
464
- return JSON.parse(JSON.stringify(_actions));
465
- };
466
-
467
- /**
468
- * Add a function to the automator
469
- * @param {string} name - Common name for the function
470
- * @param {Function} cmd - The function
471
- */
472
- this.addFunction = function(name, cmd) {
473
- //add a new function to the functions object
474
- //due to the nature of Javascript you may use this function to modify an existing function too.
475
- //Currently there is no way to remove a function, but since you can modify it or set it to null
476
- //there's really no need/benefit of "removing" it completely.
477
- _functions[name] = cmd;
478
- };
479
-
480
- /**
481
- * Remove an action by it's ID
482
- * @param {Number|string} ID - The ID of the action
483
- */
484
- this.removeActionByID = function(ID) {
485
- //removes an action from the list based on the ActionID
486
- //returns true if the action was successfully removed
487
- //Returns false if not
488
- //ActionID's should be unique, but this will remove all matches just in case
489
- var removed = false;
490
- for (var i = _actions.length; i--;) {
491
- if (_actions[i].id === ID) {
492
- _actions.splice(i,1);
493
- removed = true;
494
- }
495
- }
496
- _self.emit('update'); //tell the clients that the actions have changed
497
- if (_saveState) { saveActions(_actions); } //save the new actions to a file
498
- return removed;
499
- };
500
-
501
- /**
502
- * Remove an action by it's name
503
- * @param {string} name - The name of the action
504
- */
505
- this.removeActionByName = function(name) {
506
- //removes an action from the list based on the action name
507
- //returns true if the action was successfully removed
508
- //Returns false if not
509
- //this will remove all matches, so useful if you want to use the "name" field
510
- //as more of a "type" field, so for example this could remove all your "Backup" actions
511
- var removed = false;
512
- for (var i = _actions.length; i--;) {
513
- if (_actions[i].name === name) {
514
- _actions.splice(i,1);
515
- removed = true;
516
- }
517
- }
518
- _self.emit('update'); //tell the clients that the actions have changed
519
- if (_saveState) { saveActions(_actions); } //save the new actions to a file
520
- return removed;
521
- };
522
-
523
- /**
524
- * Execute an action by it's ID
525
- * @param {Number|string} ID - The action ID
526
- * @param {Boolean} increment - Should this execution count towards the action's total
527
- *
528
- * @returns {Boolean} - Did the action(s) run
529
- */
530
- this.executeActionByID = function(ID, increment) {
531
- //executes an action based on it's action ID
532
- //returns true if the action is run
533
- //this shouldn't ever happen, but if more then one action shares an ID, run all
534
-
535
- //assume we don't want this to count against the total
536
- if (typeof increment === 'undefined') { increment = false; }
537
-
538
- for (var i=0; i<_actions.length; i++) {
539
- // @ts-ignore
540
- if(_actions[i].id === parseInt(ID)) {
541
- _actions[i] = executeAction(_actions[i], true, increment);
542
- _self.emit('action', [{
543
- id: _actions[i].id,
544
- name: _actions[i].name,
545
- date: clearMilliSeconds(Date.now())
546
- }]);
547
- if (_saveState) { saveActions(_actions); } //save the new actions to a file
548
- return true;
549
- }
550
- }
551
- return false;
552
- };
553
-
554
- /**
555
- * Execute an action by it's name
556
- * @param {string} name - The action name
557
- * @param {Boolean} increment - Should this execution count towards the action's total
558
- *
559
- * @returns {Boolean} - Did the action run?
560
- */
561
- this.executeActionByName = function(name, increment) {
562
- debug('Execute by name: ' + name);
563
- //executes an action based on it's name
564
- //returns true if the action is run
565
- //will run all matching actions.
566
-
567
- //assume we don't want this to count against the total
568
- if (typeof increment === 'undefined') { increment = false; }
569
-
570
- var actionRan = false;
571
- var actionsRun = [];
572
- var actionInfo = {};
573
-
574
- for (var i=0; i<_actions.length; i++) {
575
- if(_actions[i].name === name) {
576
- _actions[i] = executeAction(_actions[i], true, increment);
577
- actionRan = true;
578
- //since more then one action may run we're going to create the actionRun list
579
- //to emit to the client
580
- // @ts-ignore
581
- actionInfo = {};
582
- actionInfo.id = _actions[i].id;
583
- actionInfo.name = _actions[i].name;
584
- actionInfo.date = clearMilliSeconds(Date.now());
585
- actionsRun.push(actionInfo);
586
- }
587
- }
588
- if (actionRan) {
589
- _self.emit('action', actionsRun); //emit the list of actions run
590
- if (_saveState) { saveActions(_actions); } //save the new actions to a file
591
- }
592
-
593
- return actionRan;
594
- };
595
-
596
- /**
597
- * This is for simulation/debugging or for showing upcoming actions on a calendar.
598
- * @param {string|Date} start - Start date
599
- * @param {string|Date} end - End date
600
- * @param {Function} [callback] - Array of scheduled actions within the specified date range
601
- */
602
- this.GetActionsInRange = function(start, end, callback) {
603
- //returns an array of scheduled actions within the specified date range.
604
- //This is for simulation or for showing upcoming actions on a calendar.
605
-
606
- var tick = clearMilliSeconds(new Date(start)); //the tick time for our virtual automator
607
- end = clearMilliSeconds(new Date(end)); //the date/time to stop the simulation
608
- var actionList = []; //the list of actions to return
609
- //This will create a unique copy of the global _actions list
610
- //it wont copy the functions, but we're not running them anyway
611
- var actions = JSON.parse(JSON.stringify(_actions));
612
-
613
- while (dateToMilliseconds(tick) <= dateToMilliseconds(end)) {
614
- //run the actions in non-execute mode with a copy actions object
615
- actions = executeAllActions(actions, tick, false, function(actionsUpdated, actionsRun) {
616
- //instead of emitting the action list, we're going to add them to our master list
617
- //of actions run during the simulation
618
- if (actionsUpdated) {
619
- for (var i=0; i<actionsRun.length; i++) {
620
- actionList.push(JSON.parse(JSON.stringify(actionsRun[i])));
621
- }
622
- }
623
- });
624
- tick.setMinutes(tick.getMinutes() + 1); //add a minute to the virtual tick
625
- if (actions.length === 0) { //if there are no remaining actions, quit.
626
- if (typeof callback === 'function') {
627
- callback(actionList);
628
- }
629
- }
630
- }
631
-
632
- //we should now have a list of every action run within the specified period listed by
633
- //id and name and the tick-time they would have run
634
- //return actionList; //let's use/require a callback instead
635
-
636
- if (typeof callback === 'function') {
637
- callback(actionList);
638
- }
639
- };
640
-
641
- /**
642
- * Updates an action by it's name
643
- * @param {string} name - Name of the action
644
- * @param {object} newAction - The modified action object
645
- */
646
- this.updateActionByName = function(name, newAction) {
647
- for (var i=0; i<_actions.length; i++) {
648
- if(_actions[i].name === name) {
649
- updateAction(_actions[i], newAction);
650
- }
651
- }
652
- };
653
-
654
- /**
655
- * Updates an action by it's ID
656
- * @param {string} ID - ID of the action
657
- * @param {object} newAction - The modified action object
658
- */
659
- this.updateActionByID = function(ID, newAction) {
660
- for (var i=0; i<_actions.length; i++) {
661
- if(_actions[i].id === ID) {
662
- updateAction(_actions[i], newAction);
663
- }
664
- }
665
- };
666
- }
667
-
668
- exports.automator = automator;
669
-
670
-
671
-
672
-
673
-
674
-
675
- /**************************************************************************************** */
676
-
677
- //Here's a copy/paste version of the action object:
678
-
679
- var action = {
680
- name: '', //user definable
681
- date: null, //next time the action should run, set default immediately
682
- cmd: null, //cmd to call
683
- payload: null, //payload to send to cmd
684
- unBuffered: null, //when true actions missed due to sync delay will be skipped
685
- repeat: { //set this to null to only run the action once, alternatively set limit to 1
686
- type:'minute', // second/minute/hour/day/week/month/year/weekday/weekend
687
- interval: 1, //how many of the type to skip, 3=every 3rd type
688
- count: 0, //number of times the action has run, 0=hasn't run yet
689
- limit: null, //number of times the action should run, false means don't limit
690
- endDate: null //null = no end date
691
- }
692
- };
693
-
694
- /**************************************************************************************** */