obs-scheduler 0.1.1 → 0.1.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.
- package/cli.js +1 -1
- package/config-schema.json +98 -66
- package/dist/config.js +36 -15
- package/dist/index.js +6 -1
- package/dist/obs.js +3 -1
- package/examples/config-example.json +9 -9
- package/package.json +1 -1
package/cli.js
CHANGED
package/config-schema.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "OBS Scheduler
|
|
3
|
+
"title": "OBS Scheduler Configuration",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"required": [
|
|
6
6
|
"events"
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"format": "tabs",
|
|
14
14
|
"items": {
|
|
15
15
|
"title": "Event",
|
|
16
|
+
"headerTemplate": "{{ self.name }}",
|
|
16
17
|
"description": "A scheduled event for triggering a set action in OBS.",
|
|
17
18
|
"type": "object",
|
|
18
19
|
"required": [
|
|
@@ -40,11 +41,23 @@
|
|
|
40
41
|
"$ref": "#/definitions/ScheduleType"
|
|
41
42
|
},
|
|
42
43
|
"date": {
|
|
43
|
-
"title": "Date",
|
|
44
|
-
"description": "A date/time for when the action should trigger.",
|
|
44
|
+
"title": "Date(s)",
|
|
45
|
+
"description": "A date/time (or a list of dates/times) for when the action should trigger.",
|
|
45
46
|
"propertyOrder": 4,
|
|
46
|
-
"
|
|
47
|
-
|
|
47
|
+
"anyOf": [
|
|
48
|
+
{
|
|
49
|
+
"title": "Single Date/Time",
|
|
50
|
+
"$ref": "#/definitions/DateString"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"title": "Multiple Dates/Times",
|
|
54
|
+
"type": "array",
|
|
55
|
+
"uniqueItems": true,
|
|
56
|
+
"items": {
|
|
57
|
+
"$ref": "#/definitions/DateString"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
],
|
|
48
61
|
"options": {
|
|
49
62
|
"dependencies": {
|
|
50
63
|
"schedule_type": "date"
|
|
@@ -52,12 +65,23 @@
|
|
|
52
65
|
}
|
|
53
66
|
},
|
|
54
67
|
"schedule": {
|
|
55
|
-
"title": "Schedule",
|
|
56
|
-
"description": "A schedule for a recurring event in crontab format.",
|
|
68
|
+
"title": "Schedule(s)",
|
|
69
|
+
"description": "A schedule (or a list of schedules) for a recurring event in crontab format.",
|
|
57
70
|
"propertyOrder": 4,
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
"anyOf": [
|
|
72
|
+
{
|
|
73
|
+
"title": "Single Schedule",
|
|
74
|
+
"$ref": "#/definitions/CronTabString"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"title": "Multiple Schedules",
|
|
78
|
+
"type": "array",
|
|
79
|
+
"uniqueItems": true,
|
|
80
|
+
"items": {
|
|
81
|
+
"$ref": "#/definitions/CronTabString"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
],
|
|
61
85
|
"options": {
|
|
62
86
|
"dependencies": {
|
|
63
87
|
"schedule_type": "recurring"
|
|
@@ -81,69 +105,70 @@
|
|
|
81
105
|
},
|
|
82
106
|
"ws_request": {
|
|
83
107
|
"title": "OBS Websocket Message",
|
|
84
|
-
"$ref": "#/definitions/OBSWSRequest"
|
|
108
|
+
"$ref": "#/definitions/OBSWSRequest",
|
|
109
|
+
"options": {
|
|
110
|
+
"dependencies": {
|
|
111
|
+
"action": "obs_ws"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
85
114
|
}
|
|
86
115
|
},
|
|
87
116
|
"allOf": [
|
|
88
117
|
{
|
|
89
|
-
"
|
|
90
|
-
{
|
|
91
|
-
"
|
|
92
|
-
"date"
|
|
93
|
-
],
|
|
94
|
-
"properties": {
|
|
95
|
-
"schedule_type": {
|
|
96
|
-
"const": "date"
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
"required": [
|
|
102
|
-
"schedule"
|
|
103
|
-
],
|
|
104
|
-
"properties": {
|
|
105
|
-
"schedule_type": {
|
|
106
|
-
"const": "recurring"
|
|
107
|
-
}
|
|
118
|
+
"if": {
|
|
119
|
+
"properties": {
|
|
120
|
+
"schedule_type": {
|
|
121
|
+
"const": "date"
|
|
108
122
|
}
|
|
109
123
|
}
|
|
110
|
-
|
|
124
|
+
},
|
|
125
|
+
"then": {
|
|
126
|
+
"required": [
|
|
127
|
+
"date"
|
|
128
|
+
]
|
|
129
|
+
}
|
|
111
130
|
},
|
|
112
131
|
{
|
|
113
|
-
"
|
|
114
|
-
{
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"action": {
|
|
118
|
-
"enum": [
|
|
119
|
-
"advanced_scene_switcher",
|
|
120
|
-
"obs_ws"
|
|
121
|
-
]
|
|
122
|
-
}
|
|
123
|
-
}
|
|
132
|
+
"if": {
|
|
133
|
+
"properties": {
|
|
134
|
+
"schedule_type": {
|
|
135
|
+
"const": "recurring"
|
|
124
136
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"then": {
|
|
140
|
+
"required": [
|
|
141
|
+
"schedule"
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"if": {
|
|
147
|
+
"properties": {
|
|
148
|
+
"action": {
|
|
149
|
+
"const": "advanced_scene_switcher"
|
|
134
150
|
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
"then": {
|
|
154
|
+
"required": [
|
|
155
|
+
"switcher_message"
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"if": {
|
|
161
|
+
"properties": {
|
|
162
|
+
"action": {
|
|
163
|
+
"const": "obs_ws"
|
|
144
164
|
}
|
|
145
165
|
}
|
|
146
|
-
|
|
166
|
+
},
|
|
167
|
+
"then": {
|
|
168
|
+
"required": [
|
|
169
|
+
"ws_request"
|
|
170
|
+
]
|
|
171
|
+
}
|
|
147
172
|
}
|
|
148
173
|
],
|
|
149
174
|
"options": {
|
|
@@ -168,6 +193,15 @@
|
|
|
168
193
|
]
|
|
169
194
|
}
|
|
170
195
|
},
|
|
196
|
+
"DateString": {
|
|
197
|
+
"type": "string",
|
|
198
|
+
"format": "datetime-local"
|
|
199
|
+
},
|
|
200
|
+
"CronTabString": {
|
|
201
|
+
"type": "string",
|
|
202
|
+
"format": "crontab",
|
|
203
|
+
"pattern": "^((((\\d+,)+\\d+|(\\d+(\\/|-|#)\\d+)|\\d+L?|\\*(\\/\\d+)?|L(-\\d+)?|\\?|[A-Z]{3}(-[A-Z]{3})?) ?){5,7})|(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\\d+(ns|us|µs|ms|s|m|h))+)$"
|
|
204
|
+
},
|
|
171
205
|
"EventAction": {
|
|
172
206
|
"description": "An action to trigger in OBS.",
|
|
173
207
|
"type": "string",
|
|
@@ -201,17 +235,15 @@
|
|
|
201
235
|
],
|
|
202
236
|
"additionalProperties": false,
|
|
203
237
|
"properties": {
|
|
238
|
+
"id": {
|
|
239
|
+
"type": "string"
|
|
240
|
+
},
|
|
204
241
|
"type": {
|
|
205
242
|
"type": "string"
|
|
206
243
|
},
|
|
207
244
|
"data": {
|
|
208
245
|
"type": "object"
|
|
209
246
|
}
|
|
210
|
-
},
|
|
211
|
-
"options": {
|
|
212
|
-
"dependencies": {
|
|
213
|
-
"action": "obs_ws"
|
|
214
|
-
}
|
|
215
247
|
}
|
|
216
248
|
}
|
|
217
249
|
}
|
package/dist/config.js
CHANGED
|
@@ -9,6 +9,7 @@ import { DateTime } from "luxon";
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @typedef {Object} OBSWSRequest
|
|
12
|
+
* @property {string} [id]
|
|
12
13
|
* @property {string} type
|
|
13
14
|
* @property {Object} data
|
|
14
15
|
*/
|
|
@@ -18,8 +19,8 @@ import { DateTime } from "luxon";
|
|
|
18
19
|
* @property {string} [name]
|
|
19
20
|
* @property {boolean} [enabled=true]
|
|
20
21
|
* @property {ConfigEventType} schedule_type
|
|
21
|
-
* @property {string} [date] Only present if `schedule_type` is `'date'`.
|
|
22
|
-
* @property {string} [schedule] Only present if `schedule_type` is `'recurring'`.
|
|
22
|
+
* @property {string|string[]} [date] Only present if `schedule_type` is `'date'`.
|
|
23
|
+
* @property {string|string[]} [schedule] Only present if `schedule_type` is `'recurring'`.
|
|
23
24
|
* @property {ConfigEventAction} action
|
|
24
25
|
* @property {string} [switcher_message] Only present if `action` is `'advanced_scene_switcher'`.
|
|
25
26
|
* @property {OBSWSRequest} [ws_request] Only present if `action` is `'obs_ws'`.
|
|
@@ -43,21 +44,41 @@ export function checkEventSchedule(date, event) {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
if (event.date) { // If event has the `date` field
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
/** @type {string[]} */
|
|
48
|
+
let datesToCompare = new Array();
|
|
49
|
+
if (typeof event.date == 'string') {
|
|
50
|
+
datesToCompare.push(event.date);
|
|
51
|
+
} else {
|
|
52
|
+
datesToCompare.push(...event.date);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return datesToCompare.some((eventDate) => {
|
|
56
|
+
// Parse event's date string to `DateTime`
|
|
57
|
+
const eventDateTime = DateTime.fromISO(eventDate);
|
|
58
|
+
// console.log(eventDate.getTime(), date.getTime())
|
|
59
|
+
// Compare parsed date (rounded to the previous second) to the current `date`
|
|
60
|
+
return eventDateTime.startOf('second').toMillis() == date.toMillis();
|
|
61
|
+
});
|
|
51
62
|
} else if (event.schedule) { // If event has the `schedule` field
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// If parse fails, return `false`
|
|
59
|
-
return false;
|
|
63
|
+
/** @type {string[]} */
|
|
64
|
+
let schedulesToCompare = new Array();
|
|
65
|
+
if (typeof event.schedule == 'string') {
|
|
66
|
+
schedulesToCompare.push(event.schedule);
|
|
67
|
+
} else {
|
|
68
|
+
schedulesToCompare.push(...event.schedule);
|
|
60
69
|
}
|
|
70
|
+
|
|
71
|
+
return schedulesToCompare.some((eventSchedule) => {
|
|
72
|
+
try {
|
|
73
|
+
// Parse crontab string
|
|
74
|
+
const schedule = CronExpressionParser.parse(eventSchedule);
|
|
75
|
+
// Return if the parsed schedule includes the current `date`
|
|
76
|
+
return schedule.includesDate(date.toJSDate());
|
|
77
|
+
} catch (error) {
|
|
78
|
+
// If parse fails, return `false`
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
61
82
|
} else {
|
|
62
83
|
return false;
|
|
63
84
|
}
|
package/dist/index.js
CHANGED
|
@@ -33,12 +33,14 @@ export async function run() {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/** @type {Config} */
|
|
36
|
-
let config
|
|
36
|
+
let config;
|
|
37
37
|
|
|
38
38
|
function updateConfigFromFile() {
|
|
39
39
|
const fileContents = fs.readFileSync(configPath, "utf8")
|
|
40
40
|
.replace(/^[ \t]*\/\/.+$\n/gm, '');
|
|
41
|
+
const firstRun = config == undefined;
|
|
41
42
|
config = JSON.parse(fileContents);
|
|
43
|
+
console.log((firstRun ? 'Read' : 'Updated') + ' configuration file.');
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
// Read config file for initial value
|
|
@@ -54,6 +56,9 @@ export async function run() {
|
|
|
54
56
|
const matchingEvents = config.events
|
|
55
57
|
.filter(e => checkEventSchedule(date, e));
|
|
56
58
|
|
|
59
|
+
// console.log(config.events);
|
|
60
|
+
console.log(matchingEvents);
|
|
61
|
+
|
|
57
62
|
const wsRequests = matchingEvents
|
|
58
63
|
.flatMap(convertEventToWebsocketRequest);
|
|
59
64
|
|
package/dist/obs.js
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
* @returns {import("obs-websocket-js").RequestBatchRequest[]}
|
|
7
7
|
*/
|
|
8
8
|
export function convertEventToWebsocketRequest(event) {
|
|
9
|
-
const requestID =
|
|
9
|
+
const requestID = event.action == 'obs_ws' && event.ws_request?.id
|
|
10
|
+
? event.ws_request.id
|
|
11
|
+
: `${event.name ? event.name + '.' : ''}${event.action}`;
|
|
10
12
|
|
|
11
13
|
switch (event.action) {
|
|
12
14
|
case "start_stream":
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
2
|
+
"$schema": "/Users/edon/Documents/Developer Stuff/NPM Packages/obs-scheduler/config-schema.json",
|
|
3
3
|
"events": [
|
|
4
4
|
{
|
|
5
5
|
"name": "Example Event 1",
|
|
6
6
|
"schedule_type": "date",
|
|
7
|
-
"date": "2026-01-
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
7
|
+
// "date": "2026-01-09T14:49:30",
|
|
8
|
+
"date": [
|
|
9
|
+
"2026-01-09T15:06:15",
|
|
10
|
+
"2026-01-09T15:06:45",
|
|
11
|
+
"2026-01-09T15:07"
|
|
12
|
+
],
|
|
13
|
+
"action": "advanced_scene_switcher",
|
|
14
|
+
"switcher_message": "test"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|