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