diff --git a/lib/notifier.js b/lib/notifier.js index 883fe6b8..ccd912b4 100644 --- a/lib/notifier.js +++ b/lib/notifier.js @@ -1,5 +1,5 @@ const crypto = require('crypto') -const R = require('ramda') +const _ = require('lodash/fp') const prettyMs = require('pretty-ms') const numeral = require('numeral') @@ -11,13 +11,25 @@ const STALE_STATE = 2 * T.minute const NETWORK_DOWN_TIME = T.minute const ALERT_SEND_INTERVAL = T.hour +const PING = Symbol('PING') +const STALE = Symbol('STALE') +const LOW_BALANCE = Symbol('LOW_BALANCE') + +const CODES_DISPLAY = { + [PING]: 'Machine Down', + [STALE]: 'Machine Stuck', + [LOW_BALANCE]: 'Low Balance' +} + let alertFingerprint let lastAlertTime -function toInt10 (str) { return parseInt(str, 10) } +function codeDisplay (code) { + return CODES_DISPLAY[code] +} function jsonParse (event) { - return R.assoc('note', JSON.parse(event.note), event) + return _.set('note', JSON.parse(event.note), event) } function sameState (a, b) { @@ -77,26 +89,37 @@ function checkNotification (plugins) { .catch(logger.error) } +const getDeviceTime = _.flow(_.get('device_time'), _.unary(parseInt)) + function checkPing (deviceEvents) { - const sortedEvents = R.sortBy(R.compose(toInt10, R.prop('device_time')), R.map(jsonParse, deviceEvents)) - const lastEvent = R.last(sortedEvents) + const sortedEvents = _.sortBy(getDeviceTime, _.map(jsonParse, deviceEvents)) + const lastEvent = _.last(sortedEvents) if (!lastEvent) { - return [{code: 'ping'}] + return [{code: PING}] } const age = Math.floor(lastEvent.age) if (age > NETWORK_DOWN_TIME) { - return [{code: 'ping', age: age}] + return [{code: PING, age: age}] } return [] } +function dropRepeatsWith (comparator, arr) { + var fullReduce = _.reduce.convert({cap: false}) + const iteratee = (acc, val) => val === acc.last + ? acc + : {arr: _.concat(acc.arr, val), last: val} + + return fullReduce(iteratee, {arr: []}, arr).arr +} + function checkStuckScreen (deviceEvents) { - const sortedEvents = R.sortBy(R.compose(toInt10, R.prop('device_time')), R.map(jsonParse, deviceEvents)) - const noRepeatEvents = R.dropRepeatsWith(sameState, sortedEvents) - const lastEvent = R.last(noRepeatEvents) + const sortedEvents = _.sortBy(getDeviceTime, _.map(jsonParse, deviceEvents)) + const noRepeatEvents = dropRepeatsWith(sameState, sortedEvents) + const lastEvent = _.last(noRepeatEvents) if (!lastEvent) { return [] @@ -111,7 +134,7 @@ function checkStuckScreen (deviceEvents) { const age = Math.floor(lastEvent.age) if (age > STALE_STATE) { - return [{code: 'stale', state: state, age: age}] + return [{code: STALE, state: state, age: age}] } return [] @@ -154,18 +177,18 @@ function formatCurrency (num, code) { function emailAlert (alert) { switch (alert.code) { - case 'ping': + case PING: if (alert.age) { const pingAge = prettyMs(alert.age, {compact: true, verbose: true}) - return 'Connection to machine down for ' + pingAge + return `Machine down for ${pingAge}` } - return 'Machine down for a while or never connected' - case 'stale': + return 'Machine down for a while.' + case STALE: const stuckAge = prettyMs(alert.age, {compact: true, verbose: true}) - return 'Machine is stuck on ' + alert.state + 'screen for ' + stuckAge - case 'lowBalance': + return `Machine is stuck on ${alert.state} screen for ${stuckAge}` + case LOW_BALANCE: const balance = formatCurrency(alert.fiatBalance.balance, alert.fiatCode) - return 'Low balance of ' + balance + ' in ' + alert.cryptoCode + ' wallet' + return `Low balance of ${balance} in ${alert.cryptoCode} wallet` } } @@ -181,7 +204,7 @@ function printEmailAlerts (alertRec) { body = body + emailAlerts(alertRec.general) } - R.keys(alertRec.devices).forEach(function (device) { + _.keys(alertRec.devices).forEach(function (device) { const deviceName = alertRec.deviceNames[device] body = body + '\nErrors for ' + deviceName + ':\n' body = body + emailAlerts(alertRec.devices[device]) @@ -193,13 +216,13 @@ function printEmailAlerts (alertRec) { function alertSubject (alertRec) { let alerts = alertRec.general - R.keys(alertRec.devices).forEach(function (device) { - alerts = R.concat(alerts, alertRec.devices[device]) + _.keys(alertRec.devices).forEach(function (device) { + alerts = _.concat(alerts, alertRec.devices[device]) }) if (alerts.length === 0) return null - const alertTypes = R.uniq(R.pluck('code', alerts)).sort() + const alertTypes = _.map(codeDisplay, _.uniq(_.map('code', alerts))).sort() return '[Lamassu] Errors reported: ' + alertTypes.join(', ') } diff --git a/lib/plugins.js b/lib/plugins.js index 405a8560..ce2f3f33 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -440,7 +440,7 @@ function plugins (settings, deviceId) { const lowBalanceThreshold = config.lowBalanceThreshold return rec.fiatBalance.balance <= lowBalanceThreshold - ? {code: 'lowBalance', cryptoCode: rec.cryptoCode, fiatBalance: rec.fiatBalance, fiatCode: rec.fiatCode} + ? {code: Symbol('LOW_BALANCE'), cryptoCode: rec.cryptoCode, fiatBalance: rec.fiatBalance, fiatCode: rec.fiatCode} : null }