toaster.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * Wrapper for the toaster (https://github.com/nels-o/toaster)
  3. */
  4. var path = require('path');
  5. var notifier = path.resolve(__dirname, '../vendor/snoreToast/SnoreToast.exe');
  6. var utils = require('../lib/utils');
  7. var Balloon = require('./balloon');
  8. var EventEmitter = require('events').EventEmitter;
  9. var util = require('util');
  10. var fallback = void 0;
  11. module.exports = WindowsToaster;
  12. function WindowsToaster(options) {
  13. options = utils.clone(options || {});
  14. if (!(this instanceof WindowsToaster)) {
  15. return new WindowsToaster(options);
  16. }
  17. this.options = options;
  18. EventEmitter.call(this);
  19. }
  20. util.inherits(WindowsToaster, EventEmitter);
  21. function noop() {}
  22. var timeoutMessage = 'the toast has timed out';
  23. var successMessage = 'user clicked on the toast';
  24. function hasText(str, txt) {
  25. return str && str.indexOf(txt) !== -1;
  26. }
  27. WindowsToaster.prototype.notify = function(options, callback) {
  28. options = utils.clone(options || {});
  29. callback = callback || noop;
  30. if (typeof options === 'string') {
  31. options = { title: 'node-notifier', message: options };
  32. }
  33. if (typeof callback !== 'function') {
  34. throw new TypeError(
  35. 'The second argument must be a function callback. You have passed ' +
  36. typeof fn
  37. );
  38. }
  39. var actionJackedCallback = utils.actionJackerDecorator(
  40. this,
  41. options,
  42. function cb(err, data) {
  43. // Needs to filter out timeout. Not an actual error.
  44. if (err && hasText(data, timeoutMessage)) {
  45. return callback(null, data);
  46. }
  47. callback(err, data);
  48. },
  49. function mapper(data) {
  50. if (hasText(data, successMessage)) {
  51. return 'click';
  52. }
  53. if (hasText(data, timeoutMessage)) {
  54. return 'timeout';
  55. }
  56. return false;
  57. }
  58. );
  59. options.title = options.title || 'Node Notification:';
  60. if (
  61. typeof options.message === 'undefined' &&
  62. typeof options.close === 'undefined'
  63. ) {
  64. callback(new Error('Message or ID to close is required.'));
  65. return this;
  66. }
  67. if (!utils.isWin8() && !utils.isWSL() && !!this.options.withFallback) {
  68. fallback = fallback || new Balloon(this.options);
  69. return fallback.notify(options, callback);
  70. }
  71. options = utils.mapToWin8(options);
  72. var argsList = utils.constructArgumentList(options, {
  73. explicitTrue: true,
  74. wrapper: '',
  75. keepNewlines: true,
  76. noEscape: true
  77. });
  78. utils.fileCommand(
  79. this.options.customPath || notifier,
  80. argsList,
  81. actionJackedCallback
  82. );
  83. return this;
  84. };