1 | var cp = require('child_process'),
|
2 | os = require('os'),
|
3 | fs = require('fs'),
|
4 | path = require('path'),
|
5 | shellwords = require('shellwords'),
|
6 | semver = require('semver'),
|
7 | clone = require('lodash.clonedeep');
|
8 |
|
9 |
|
10 | var escapeQuotes = function (str) {
|
11 | if (typeof str === 'string') {
|
12 | return str.replace(/(["$`\\])/g, '\\$1');
|
13 | } else {
|
14 | return str;
|
15 | }
|
16 | };
|
17 |
|
18 | var inArray = function (arr, val) {
|
19 | for(var i = 0; i < arr.length; i++) {
|
20 | if (arr[i] === val) {
|
21 | return true;
|
22 | }
|
23 | }
|
24 | return false;
|
25 | };
|
26 |
|
27 | var notifySendFlags = {
|
28 | "u": "urgency",
|
29 | "urgency": "urgency",
|
30 | "t": "expire-time",
|
31 | "e": "expire-time",
|
32 | "expire": "expire-time",
|
33 | "expire-time": "expire-time",
|
34 | "i": "icon",
|
35 | "icon": "icon",
|
36 | "c": "category",
|
37 | "category": "category",
|
38 | "subtitle": "category",
|
39 | "h": "hint",
|
40 | "hint": "hint"
|
41 | };
|
42 |
|
43 | module.exports.command = function (notifier, options, cb) {
|
44 | notifier = shellwords.escape(notifier);
|
45 | return cp.exec(notifier + ' ' + options.join(' '), function (error, stdout, stderr) {
|
46 | if (error) return cb(error);
|
47 | cb(stderr, stdout);
|
48 | });
|
49 | };
|
50 |
|
51 | module.exports.fileCommand = function (notifier, options, cb) {
|
52 | return cp.execFile(notifier, options, function (error, stdout, stderr) {
|
53 | if (error) return cb(error, stdout);
|
54 | cb(stderr, stdout);
|
55 | });
|
56 | };
|
57 |
|
58 | module.exports.immediateFileCommand = function (notifier, options, cb) {
|
59 | notifierExists(notifier, function (exists) {
|
60 | if (!exists) return cb(new Error('Notifier (' + notifier + ') not found on system.'));
|
61 | cp.execFile(notifier, options);
|
62 | cb();
|
63 | });
|
64 | };
|
65 |
|
66 | function notifierExists (notifier, cb) {
|
67 | return fs.stat(notifier, function (err, stat) {
|
68 | if (!err) return cb(stat.isFile());
|
69 |
|
70 |
|
71 | if (!!path.extname(notifier)) {
|
72 |
|
73 | return cb(false);
|
74 | }
|
75 |
|
76 |
|
77 | return fs.stat(notifier + '.exe', function (err, stat) {
|
78 | cb(stat.isFile());
|
79 | });
|
80 | });
|
81 | }
|
82 |
|
83 | var mapAppIcon = function (options) {
|
84 | if (options.appIcon) {
|
85 | options.icon = options.appIcon;
|
86 | delete options.appIcon;
|
87 | }
|
88 |
|
89 | return options;
|
90 | };
|
91 |
|
92 | var mapText = function (options) {
|
93 | if (options.text) {
|
94 | options.message = options.text;
|
95 | delete options.text;
|
96 | }
|
97 |
|
98 | return options;
|
99 | };
|
100 |
|
101 | var mapIconShorthand = function (options) {
|
102 | if (options.i) {
|
103 | options.icon = options.i;
|
104 | delete options.i;
|
105 | }
|
106 |
|
107 | return options;
|
108 | };
|
109 |
|
110 | module.exports.mapToNotifySend = function (options) {
|
111 | options = mapAppIcon(options);
|
112 | options = mapText(options);
|
113 |
|
114 | for (var key in options) {
|
115 | if (key === "message" || key === "title") continue;
|
116 | if (options.hasOwnProperty(key) && (notifySendFlags[key] != key)) {
|
117 | options[notifySendFlags[key]] = options[key];
|
118 | delete options[key];
|
119 | }
|
120 | }
|
121 |
|
122 | return options;
|
123 | };
|
124 |
|
125 | module.exports.mapToGrowl = function (options) {
|
126 | options = mapAppIcon(options);
|
127 | options = mapIconShorthand(options);
|
128 |
|
129 | if (options.text) {
|
130 | options.message = options.text;
|
131 | delete options.text;
|
132 | }
|
133 |
|
134 | if (options.icon && !Buffer.isBuffer(options.icon)) {
|
135 | options.icon = fs.readFileSync(options.icon);
|
136 | }
|
137 |
|
138 | return options;
|
139 | };
|
140 |
|
141 | module.exports.mapToMac = function (options) {
|
142 | options = mapIconShorthand(options);
|
143 | options = mapText(options);
|
144 |
|
145 | if (options.icon) {
|
146 | options.appIcon = options.icon;
|
147 | delete options.icon;
|
148 | }
|
149 |
|
150 | if (options.sound === true) {
|
151 | options.sound = 'Bottle';
|
152 | }
|
153 |
|
154 | if (options.sound === false) {
|
155 | delete options.sound;
|
156 | }
|
157 |
|
158 | return options;
|
159 | };
|
160 |
|
161 | module.exports.actionJackerDecorator = function (emitter, options, fn, mapper) {
|
162 | options = clone(options);
|
163 | fn = fn || function (err, data) {};
|
164 | return function (err, data) {
|
165 | fn.apply(emitter, [err, data]);
|
166 | if (err || !mapper || !data) return;
|
167 |
|
168 | var key = mapper(data);
|
169 | if (!key) return;
|
170 | emitter.emit(key, emitter, options);
|
171 | };
|
172 | };
|
173 |
|
174 | module.exports.constructArgumentList = function (options, extra) {
|
175 | var args = [];
|
176 | extra = extra || {};
|
177 |
|
178 |
|
179 | var initial = extra.initial || [];
|
180 | var keyExtra = extra.keyExtra || "";
|
181 | var allowedArguments = extra.allowedArguments || [];
|
182 | var noEscape = extra.noEscape !== void 0;
|
183 | var checkForAllowed = extra.allowedArguments !== void 0;
|
184 | var explicitTrue = !!extra.explicitTrue;
|
185 | var wrapper = extra.wrapper === void 0 ? '"' : extra.wrapper;
|
186 |
|
187 | var escapeFn = noEscape ? function (i) { return i; } : escapeQuotes;
|
188 |
|
189 | initial.forEach(function (val) {
|
190 | args.push(wrapper + escapeFn(val) + wrapper);
|
191 | });
|
192 | for(var key in options) {
|
193 | if (options.hasOwnProperty(key) && (!checkForAllowed || inArray(allowedArguments, key))) {
|
194 | if (explicitTrue && options[key] === true) args.push('-' + keyExtra + key);
|
195 | else if (explicitTrue && options[key] === false) continue;
|
196 | else args.push('-' + keyExtra + key, wrapper + escapeFn(options[key]) + wrapper);
|
197 | }
|
198 | }
|
199 | return args;
|
200 | };
|
201 |
|
202 | module.exports.mapToWin8 = function (options){
|
203 |
|
204 | options = mapAppIcon(options);
|
205 | options = mapText(options);
|
206 |
|
207 | if(options.icon){
|
208 | options.p = options.icon;
|
209 | delete options.icon;
|
210 | }
|
211 |
|
212 | if(options.message){
|
213 |
|
214 | options.m = options.message.replace(/\x1b/g, '');
|
215 | delete options.message;
|
216 | }
|
217 |
|
218 | if (options.title) {
|
219 | options.t = options.title;
|
220 | delete options.title;
|
221 | }
|
222 |
|
223 | if (options.quiet || options.silent) {
|
224 | options.q = options.quiet || options.silent;
|
225 | delete options.quiet;
|
226 | delete options.silent;
|
227 | }
|
228 |
|
229 | if (options.q !== false) {
|
230 | options.q = true;
|
231 | } else {
|
232 | delete options.q;
|
233 | }
|
234 |
|
235 | if (options.sound) {
|
236 | delete options.q;
|
237 | delete options.sound;
|
238 | }
|
239 |
|
240 | if (options.wait) {
|
241 | options.w = options.wait;
|
242 | delete options.wait;
|
243 | }
|
244 |
|
245 | return options;
|
246 | };
|
247 |
|
248 | module.exports.mapToNotifu = function (options) {
|
249 | options = mapAppIcon(options);
|
250 | options = mapText(options);
|
251 |
|
252 | if(options.icon){
|
253 | options.i = options.icon;
|
254 | delete options.icon;
|
255 | }
|
256 |
|
257 | if(options.message){
|
258 | options.m = options.message;
|
259 | delete options.message;
|
260 | }
|
261 |
|
262 | if (options.title) {
|
263 | options.p = options.title;
|
264 | delete options.title;
|
265 | }
|
266 |
|
267 | if (options.time) {
|
268 | options.d = options.time;
|
269 | delete options.time;
|
270 | }
|
271 |
|
272 | if (options.q !== false) {
|
273 | options.q = true;
|
274 | } else {
|
275 | delete options.q;
|
276 | }
|
277 |
|
278 | if (options.quiet === false) {
|
279 | delete options.q;
|
280 | delete options.quiet;
|
281 | }
|
282 |
|
283 | if (options.sound) {
|
284 | delete options.q;
|
285 | delete options.sound;
|
286 | }
|
287 |
|
288 | if (options.t) {
|
289 | options.d = options.t;
|
290 | delete options.t;
|
291 | }
|
292 |
|
293 | return options;
|
294 | };
|
295 |
|
296 | module.exports.isMac = function() {
|
297 | return os.type() === 'Darwin';
|
298 | };
|
299 |
|
300 | module.exports.isMountainLion = function() {
|
301 | return os.type() === 'Darwin' && semver.satisfies(garanteeSemverFormat(os.release()), '>=12.0.0');
|
302 | };
|
303 |
|
304 | module.exports.isWin8 = function() {
|
305 | return os.type() === 'Windows_NT' && semver.satisfies(garanteeSemverFormat(os.release()), '>=6.2.9200');
|
306 | };
|
307 |
|
308 | module.exports.isLessThanWin8 = function() {
|
309 | return os.type() === 'Windows_NT' && semver.satisfies(garanteeSemverFormat(os.release()), '<6.2.9200');
|
310 | };
|
311 |
|
312 | function garanteeSemverFormat (version) {
|
313 | if (version.split('.').length === 2) {
|
314 | version += '.0';
|
315 | }
|
316 | return version;
|
317 | }
|