forked from mikaelbr/node-notifier
-
Notifications
You must be signed in to change notification settings - Fork 0
/
toaster.js
145 lines (122 loc) · 3.52 KB
/
toaster.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* Wrapper for the toaster (https://github.com/nels-o/toaster)
*/
var path = require('path');
var notifier = path.resolve(__dirname, '../vendor/snoreToast/snoretoast');
var utils = require('../lib/utils');
var Balloon = require('./balloon');
var os = require('os');
const uuid = require('uuid/v4');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var fallback;
const PIPE_NAME = 'notifierPipe';
const PIPE_PATH_PREFIX = '\\\\.\\pipe\\';
module.exports = WindowsToaster;
function WindowsToaster(options) {
options = utils.clone(options || {});
if (!(this instanceof WindowsToaster)) {
return new WindowsToaster(options);
}
this.options = options;
EventEmitter.call(this);
}
util.inherits(WindowsToaster, EventEmitter);
function noop() {}
function parseResult(data) {
if (!data) {
return {};
}
return data.split(';').reduce((acc, cur) => {
const split = cur.split('=');
if (split && split.length === 2) {
acc[split[0]] = split[1];
}
return acc;
}, {});
}
function getPipeName() {
return `${PIPE_PATH_PREFIX}${PIPE_NAME}-${uuid()}`;
}
WindowsToaster.prototype.notify = function(options, callback) {
options = utils.clone(options || {});
callback = callback || noop;
var is64Bit = os.arch() === 'x64';
var resultBuffer;
const namedPipe = getPipeName();
if (typeof options === 'string') {
options = { title: 'node-notifier', message: options };
}
if (typeof callback !== 'function') {
throw new TypeError(
'The second argument must be a function callback. You have passed ' +
typeof fn
);
}
var snoreToastResultParser = (err, callback) => {
/* Possible exit statuses from SnoreToast, we only want to include err if it's -1 code
Exit Status : Exit Code
Failed : -1
Success : 0
Hidden : 1
Dismissed : 2
TimedOut : 3
ButtonPressed : 4
TextEntered : 5
*/
const result = parseResult(
resultBuffer && resultBuffer.toString('utf16le')
);
// parse action
if (result.action === 'buttonClicked' && result.button) {
result.activationType = result.button;
} else if (result.action) {
result.activationType = result.action;
}
if (err && err.code === -1) {
callback(err, result);
}
callback(null, result);
};
var actionJackedCallback = err =>
snoreToastResultParser(
err,
utils.actionJackerDecorator(
this,
options,
callback,
data => data || false
)
);
options.title = options.title || 'Node Notification:';
if (
typeof options.message === 'undefined' &&
typeof options.close === 'undefined'
) {
callback(new Error('Message or ID to close is required.'));
return this;
}
if (!utils.isWin8() && !utils.isWSL() && !!this.options.withFallback) {
fallback = fallback || new Balloon(this.options);
return fallback.notify(options, callback);
}
// Add pipeName option, to get the output
utils.createNamedPipe(namedPipe).then(out => {
resultBuffer = out;
options.pipeName = namedPipe;
options = utils.mapToWin8(options);
var argsList = utils.constructArgumentList(options, {
explicitTrue: true,
wrapper: '',
keepNewlines: true,
noEscape: true
});
var notifierWithArch = notifier + '-x' + (is64Bit ? '64' : '86') + '.exe';
utils.fileCommand(
this.options.customPath || notifierWithArch,
argsList,
actionJackedCallback
);
});
return this;
};