Skip to content

Commit 5a47fb0

Browse files
Merge pull request #10 from Tom-Hirschberger/development
Development
2 parents 9cce7e5 + f1ca497 commit 5a47fb0

3 files changed

Lines changed: 136 additions & 66 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Add the following code to your ~/MagicMirror/config/config.js:
4141

4242
| Option | Description | Mandatory | Type | Default |
4343
| ------- | --- | --- | --- | --- |
44-
| script | Either a absolute path or the realtive path of a script starting at the "scripts" directory. Make sure to add a "./" as prefix if you call a script in the "scripts" directory. | true | String | null |
44+
| script | Either a absolute path or the realtive path of a script starting at the "scripts" directory. | true | String | null |
4545
| args | Arguments which should be passed to the script | false | String | "" |
4646
| timeout | Should the script be killed if it does not return within a specific amount of milliseconds? | false | Integer | infinity |
4747
| notifications | A array containing names of the notifications to send if script returns output. If not present the script gets called but no notification will be send. If you want to override the payload instead of using the output please look at the notification section. | false | Array | [] |

node_helper.js

Lines changed: 134 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ module.exports = NodeHelper.create({
1919
self.started = false
2020

2121
self.cmdSkips = {}
22-
23-
console.log(self.name+": "+"Module helper started")
2422
self.asyncOutput = {}
2523
},
2624

@@ -44,14 +42,6 @@ module.exports = NodeHelper.create({
4442
scriptOutput+=data;
4543
});
4644

47-
// child.stderr.setEncoding('utf8');
48-
// child.stderr.on('data', function(data) {
49-
// console.log('stderr: ' + data);
50-
51-
// data=data.toString();
52-
// scriptOutput+=data;
53-
// });
54-
5545
child.on('close', function(code) {
5646
if (scriptOutput != null){
5747
scriptOutput = scriptOutput.trim()
@@ -106,6 +96,54 @@ module.exports = NodeHelper.create({
10696
}
10797
},
10898

99+
validateAndModifyPath: function(thePath){
100+
let newPath = null
101+
let testPath = null
102+
103+
if(thePath.startsWith("/")){
104+
//absolute path. Nothing to do
105+
newPath = thePath
106+
testPath = newPath
107+
} else if (thePath.indexOf("/") > 0){
108+
//path contains a "/". lets check if it is a relative one
109+
if (thePath.startsWith("./")){
110+
//relative starting at the current directory
111+
newPath = thePath
112+
testPath = scriptsDir+thePath.substring(1)
113+
} else if (thePath.startsWith("../")) {
114+
//relative targeting the directory one up
115+
newPath = thePath
116+
testPath = scriptsDir+"/"+thePath
117+
} else {
118+
//its a relative path so we add a "./"
119+
newPath = "./"+thePath
120+
testPath = scriptsDir+"/"+thePath
121+
}
122+
} else {
123+
//as it is a path without any "/" it is either a script in the scripts directory or a command in $PATH
124+
//lets check if the script exists in the script directory
125+
testPath = scriptsDir+"/"+thePath
126+
if(fs.existsSync(testPath)){
127+
//its a script in the scripts dir
128+
newPath = testPath
129+
} else {
130+
//it might be a command in $PATH but we can not test it
131+
newPath = thePath
132+
testPath = null
133+
}
134+
}
135+
136+
if (testPath != null){
137+
try {
138+
testPath = fs.realpathSync(testPath)
139+
} catch {
140+
testPath = testPath
141+
}
142+
}
143+
144+
return {"thePath": newPath, "testPath": testPath}
145+
},
146+
109147
callCommands: async function(){
110148
const self = this
111149
console.log(self.name+": "+"Calling commands")
@@ -119,77 +157,105 @@ module.exports = NodeHelper.create({
119157
self.cmdSkips[cmdIdx] = 1
120158

121159
let curCommand = curCmdConfig["script"]
122-
let curArgs = curCmdConfig["args"]
123-
if(typeof curCmdConfig["args"] !== "undefined"){
124-
if(Array.isArray(curCmdConfig["args"])){
125-
curArgs = curCmdConfig["args"]
126-
} else {
127-
curArgs = curCmdConfig["args"].split(" ")
160+
161+
let modCommand = self.validateAndModifyPath(curCommand)
162+
163+
if ((modCommand.testPath == null) || fs.existsSync(modCommand.testPath)){
164+
let isExecutable = true
165+
if (modCommand.testPath != null){
166+
try {
167+
fs.accessSync(modCommand.testPath, fs.constants.X_OK)
168+
} catch(err) {
169+
isExecutable = false
170+
}
128171
}
129-
}
130-
let curNotifications = curCmdConfig["notifications"]
172+
173+
if (isExecutable){
174+
let curArgs = curCmdConfig["args"]
175+
if(typeof curCmdConfig["args"] !== "undefined"){
176+
if(Array.isArray(curCmdConfig["args"])){
177+
curArgs = curCmdConfig["args"]
178+
} else {
179+
curArgs = curCmdConfig["args"].split(" ")
180+
}
181+
}
182+
let curNotifications = curCmdConfig["notifications"]
131183

132-
let curEncoding = "utf8"
133-
if(typeof curCmdConfig["encoding"] !== "undefined"){
134-
curEncoding = curCmdConfig["encoding"]
135-
}
184+
let curEncoding = "utf8"
185+
if(typeof curCmdConfig["encoding"] !== "undefined"){
186+
curEncoding = curCmdConfig["encoding"]
187+
}
136188

137-
let options = {
138-
shell: true,
139-
encoding: curEncoding,
140-
cwd: scriptsDir,
141-
}
189+
let options = {
190+
shell: true,
191+
encoding: curEncoding,
192+
cwd: scriptsDir,
193+
}
142194

143-
if(typeof curCmdConfig["timeout"] !== "undefined"){
144-
options["timeout"] = curCmdConfig["timeout"]
145-
}
195+
if(typeof curCmdConfig["timeout"] !== "undefined"){
196+
options["timeout"] = curCmdConfig["timeout"]
197+
}
146198

147-
let output = null
148-
let returnCode = null
149-
let sync = self.config.sync
150-
if(typeof curCmdConfig["sync"] !== "undefined"){
151-
sync = curCmdConfig["sync"]
152-
}
153-
try {
154-
if (sync){
155-
console.log("Running "+ curCommand + " synchronous")
156-
let spawnOutput = spawnSync(curCommand, curArgs, options)
157-
returnCode = spawnOutput.status
158-
output = spawnOutput.stdout
159-
if (output != null){
160-
output = output.trim()
199+
let output = null
200+
let returnCode = null
201+
let sync = self.config.sync
202+
if(typeof curCmdConfig["sync"] !== "undefined"){
203+
sync = curCmdConfig["sync"]
161204
}
162-
if(returnCode == null){
163-
returnCode = 1
164-
output += "Timeout"
205+
try {
206+
if (sync){
207+
if (self.config.debug){
208+
console.log(self.name+": Running "+ modCommand.thePath + " synchronous")
209+
}
210+
211+
let spawnOutput = spawnSync(modCommand.thePath, curArgs, options)
212+
returnCode = spawnOutput.status
213+
output = spawnOutput.stdout
214+
if (output != null){
215+
output = output.trim()
216+
}
217+
if(returnCode == null){
218+
returnCode = 1
219+
output += "Timeout"
220+
}
221+
222+
self.postProcessCommand(cmdIdx, curCmdConfig, curNotifications, output, returnCode)
223+
} else {
224+
if (self.config.debug){
225+
console.log(self.name+": Running "+curCommand + " asynchronous")
226+
}
227+
self.runScript(modCommand.thePath, curArgs, options, cmdIdx, curCmdConfig, curNotifications)
228+
}
229+
} catch (error) {
230+
console.log(self.name+": Error during call of command with index "+cmdIdx)
231+
console.log(error)
165232
}
166-
167-
self.postProcessCommand(cmdIdx, curCmdConfig, curNotifications, output, returnCode)
168233
} else {
169-
console.log("Running "+curCommand + " asynchronous")
170-
self.runScript(curCommand, curArgs, options, cmdIdx, curCmdConfig, curNotifications)
234+
console.log(self.name+": The command with index "+cmdIdx+" could not be executed. The file "+modCommand.testPath+" is not executable!")
171235
}
172-
} catch (error) {
173-
console.log(error)
236+
} else {
237+
console.log(self.name+": The command with index "+cmdIdx+" could not be executed. The file "+modCommand.testPath+" does not exist!")
174238
}
175239
if (curCmdConfig["delayNext"] || false){
176-
console.log("Delaying next: "+curCmdConfig["delayNext"])
240+
if (self.config.debug){
241+
console.log(self.name+": Delaying next: "+curCmdConfig["delayNext"])
242+
}
177243
await self.sleep(curCmdConfig["delayNext"])
178244
}
179245
} else {
180246
self.cmdSkips[cmdIdx] += 1
181247
}
182248
} else {
183-
console.log(self.name+": "+"The command with index "+cmdIdx+" is not configured properly. It is missing the script configuration option!")
249+
console.log(self.name+": The command with index "+cmdIdx+" is not configured properly. It is missing the script configuration option!")
184250
}
185251
}
186252
},
187253

188254
postProcessCommand: function(cmdIdx, curCmdConfig, curNotifications, output, returnCode){
189255
const self = this
190256
if (self.config.debug){
191-
console.log("Postprocessing cmdIdx: "+cmdIdx)
192-
console.log("curCmdConfig: "+JSON.stringify(curCmdConfig))
257+
console.log(self.name+": Postprocessing cmdIdx: "+cmdIdx)
258+
console.log(self.name+": curCmdConfig: "+JSON.stringify(curCmdConfig))
193259
console.log(output)
194260
console.log(returnCode)
195261
}
@@ -210,15 +276,17 @@ module.exports = NodeHelper.create({
210276
}
211277
}
212278
} else {
213-
console.log(self.name+": "+"The command with idx: "+cmdIdx+" has no notifications configured. It had been called but no notification will be send!")
279+
console.log(self.name+": The command with idx: "+cmdIdx+" has no notifications configured. It had been called but no notification will be send!")
214280
}
215281
}
216282
},
217283

218284
setDefaultsAndStart: function(){
219285
const self = this
220286
if(self.started){
221-
console.log(self.name+": "+"Setting the defaults")
287+
if (self.config.debug){
288+
console.log(self.name+": Setting the defaults")
289+
}
222290
if (typeof self.config["commands"] !== "undefined"){
223291
for (let cmdIdx = 0; cmdIdx < self.config.commands.length; cmdIdx++) {
224292
let curCmdConfig = self.config.commands[cmdIdx]
@@ -227,13 +295,17 @@ module.exports = NodeHelper.create({
227295
}
228296
}
229297

230-
console.log(self.name+": "+"Call the commands initially")
298+
if (self.config.debug){
299+
console.log(self.name+": Call the commands initially")
300+
}
231301
self.callCommands()
232-
console.log(self.name+": "+"Reschedule the next calls")
302+
if (self.config.debug){
303+
console.log(self.name+": Reschedule the next calls")
304+
}
233305
self.rescheduleCommandCall()
234306
}
235307
} else {
236-
console.log(self.name+": "+"Defaults can not be set because module is not started at the moment")
308+
console.log(self.name+": Defaults can not be set because module is not started at the moment")
237309
}
238310
},
239311

@@ -251,10 +323,8 @@ module.exports = NodeHelper.create({
251323
socketNotificationReceived: function (notification, payload) {
252324
const self = this
253325
if (notification === 'CONFIG' && self.started === false) {
254-
console.log(self.name+": "+"node_helper received CONFIG notification")
255326
self.config = payload
256327
self.started = true
257-
console.log(self.name+": "+"node_helper now will set some defaults")
258328
self.setDefaultsAndStart()
259329
}
260330
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "MMM-CommandToNotification",
3-
"version": "0.0.6",
3+
"version": "0.0.7",
44
"description": "A MagicMirror² module which calls system-commands or scripts periodically and sends the output as notifications.",
55
"main": "MMM-CommandToNotification",
66
"dependencies": {},

0 commit comments

Comments
 (0)