node-red-contrib-smartnora
Version:
Google Smart Home integration via Smart Nora https://smart-nora.eu/
122 lines (121 loc) • 6.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const nora_firebase_common_1 = require("@andrei-tatar/nora-firebase-common");
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const __1 = require("..");
const connection_1 = require("../nora/connection");
const device_context_1 = require("../nora/device-context");
const safe_update_1 = require("../nora/safe-update");
const sync_1 = require("../nora/sync");
const util_1 = require("./util");
const JSON_ACTION_PREFIX = 'json:';
const LINK_ACTION_PREFIX = 'https://';
module.exports = function (RED) {
RED.nodes.registerType('noraf-notify', function (config) {
var _a, _b, _c;
RED.nodes.createNode(this, config);
const noraConfig = RED.nodes.getNode(config.nora);
if (!(noraConfig === null || noraConfig === void 0 ? void 0 : noraConfig.valid)) {
return;
}
const identifier = `${(0, util_1.getId)(config)}|${noraConfig.group}`;
const configActions = config.actions;
const actions = (_a = configActions === null || configActions === void 0 ? void 0 : configActions.map(({ p: title, v: value, vt: type }, index) => ({
title,
action: type === 'link' ? value : `${index}`,
}))) === null || _a === void 0 ? void 0 : _a.splice(0, 3);
const defaultAction = (_c = actions === null || actions === void 0 ? void 0 : actions[(_b = configActions === null || configActions === void 0 ? void 0 : configActions.findIndex(c => !!c.d)) !== null && _b !== void 0 ? _b : -1]) === null || _c === void 0 ? void 0 : _c.action;
const close$ = (0, util_1.getClose)(this);
const notificationSent$ = new rxjs_1.Subject();
const ctx = new device_context_1.DeviceContext(this);
ctx.startUpdating(close$);
const connection$ = connection_1.FirebaseConnection
.withLogger(RED.log)
.fromConfig(noraConfig, ctx)
.pipe((0, __1.singleton)(), (0, operators_1.takeUntil)(close$));
connection$.pipe((0, operators_1.switchMap)(c => c.watchForActions(identifier)), (0, operators_1.takeUntil)(close$)).subscribe(action => {
if (action.startsWith(JSON_ACTION_PREFIX)) {
const actionJson = action.substring(JSON_ACTION_PREFIX.length);
this.send({
payload: JSON.parse(actionJson),
topic: config.topic,
});
}
else {
const actionIndex = parseInt(action, 10);
if ((configActions === null || configActions === void 0 ? void 0 : configActions.length) && actionIndex >= 0 && actionIndex < configActions.length) {
const { v: value, vt: valuetype } = configActions[actionIndex];
const payload = (0, util_1.getValue)(RED, this, value, valuetype);
this.send({
payload,
topic: config.topic,
});
}
}
});
notificationSent$.pipe((0, operators_1.switchMap)(_ => {
ctx.status$.next('sent');
ctx.local$.next(true);
return (0, rxjs_1.concat)((0, rxjs_1.timer)(1000), (0, rxjs_1.defer)(() => {
ctx.status$.next(null);
ctx.local$.next(false);
return rxjs_1.EMPTY;
}));
}), (0, operators_1.takeUntil)(close$)).subscribe();
(0, util_1.handleNodeInput)({
node: this,
handler: async (msg) => {
var _a, _b, _c, _d, _e, _f;
const notification = {
title: config.title,
body: config.body,
icon: config.icon,
tag: config.tag || undefined,
actions: [],
data: {
close: (_b = (config.closeNotification || ((_a = msg.payload) === null || _a === void 0 ? void 0 : _a.close))) !== null && _b !== void 0 ? _b : undefined,
},
};
(_c = msg === null || msg === void 0 ? void 0 : msg.payload) === null || _c === void 0 ? true : delete _c.close;
if (typeof msg.payload === 'object' && Array.isArray(msg.payload.actions) && msg.payload.actions.length) {
msg.payload.actions = msg.payload.actions.map((v) => (Object.assign(Object.assign({}, v), { action: typeof v.action === 'string' && v.action.startsWith(LINK_ACTION_PREFIX)
? v.action
: JSON_ACTION_PREFIX + JSON.stringify(v.action) })));
msg.payload.data = Object.assign(Object.assign({}, msg.payload.data), { defaultAction: msg.payload.actions[0].action });
}
(0, safe_update_1.getSafeUpdate)({
update: (_d = msg.payload) !== null && _d !== void 0 ? _d : {},
safeUpdateObject: notification,
currentState: notification,
isValid: () => (0, nora_firebase_common_1.validateIndividual)('notification', notification).valid,
warn: (propName) => this.warn(`ignoring property ${propName}`),
});
if ((actions === null || actions === void 0 ? void 0 : actions.length) && !((_e = notification.actions) === null || _e === void 0 ? void 0 : _e.length)) {
notification.actions = actions;
notification.data = Object.assign(Object.assign({}, notification.data), { defaultAction });
}
if ((_f = notification.actions) === null || _f === void 0 ? void 0 : _f.length) {
notification.data = Object.assign(Object.assign({}, notification.data), { sender: identifier });
}
else {
delete notification.actions;
}
const connection = await (0, rxjs_1.firstValueFrom)(connection$);
try {
ctx.error$.next(null);
await connection.sendNotification(notification);
notificationSent$.next(null);
}
catch (err) {
if (err instanceof sync_1.RateLimitingError) {
ctx.error$.next('Too many notifications');
}
else {
throw err;
}
}
},
});
});
};