matterbridge-webhooks
Version:
Matterbridge webhooks plugin
110 lines (109 loc) • 6.11 kB
JavaScript
import { bridgedNode, MatterbridgeDynamicPlatform, MatterbridgeEndpoint, onOffLight, onOffOutlet, onOffSwitch } from 'matterbridge';
import { isValidObject } from 'matterbridge/utils';
import { fetch } from './fetch.js';
export default function initializePlugin(matterbridge, log, config) {
return new WebhooksPlatform(matterbridge, log, config);
}
export class WebhooksPlatform extends MatterbridgeDynamicPlatform {
webhooks;
bridgedDevices = new Map();
constructor(matterbridge, log, config) {
super(matterbridge, log, config);
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.3.0')) {
throw new Error(`This plugin requires Matterbridge version >= "3.3.0". Please update Matterbridge to the latest version in the frontend.`);
}
this.log.info('Initializing platform:', this.config.name);
this.webhooks = config.webhooks;
this.log.info('Finished initializing platform:', this.config.name);
}
async onStart(reason) {
this.log.info('onStart called with reason:', reason ?? 'none');
await this.ready;
await this.clearSelect();
let i = 0;
for (const webhookName in this.webhooks) {
this.log.debug(`Loading webhook ${++i} ${webhookName} with method ${this.webhooks[webhookName].method} and url ${this.webhooks[webhookName].httpUrl}`);
const webhook = this.webhooks[webhookName];
this.setSelectDevice('webhook' + i, webhookName, undefined, 'hub');
if (!this.validateDevice(['webhook' + i, webhookName], true))
continue;
this.log.info(`Registering device: ${webhookName} with method ${webhook.method} and url ${webhook.httpUrl}`);
const device = new MatterbridgeEndpoint([this.config.deviceType === 'Outlet' ? onOffOutlet : this.config.deviceType === 'Light' ? onOffLight : onOffSwitch, bridgedNode], { uniqueStorageKey: webhookName }, this.config.debug)
.createDefaultBridgedDeviceBasicInformationClusterServer(webhookName, 'webhook' + i++, this.matterbridge.aggregatorVendorId, 'Matterbridge', 'Matterbridge Webhook', 0, this.config.version)
.createOnOffClusterServer(false)
.addRequiredClusterServers()
.addCommandHandler('on', async () => {
this.log.info(`Webhook ${webhookName} triggered.`);
await device.setAttribute('onOff', 'onOff', false, device.log);
fetch(webhook.httpUrl, webhook.method)
.then(() => this.log.notice(`Webhook ${webhookName} successful!`))
.catch((err) => {
this.log.error(`Webhook ${webhookName} failed: ${err instanceof Error ? err.message : err}`);
});
});
await this.registerDevice(device);
this.bridgedDevices.set(webhookName, device);
}
}
async onConfigure() {
await super.onConfigure();
this.log.info('onConfigure called');
this.bridgedDevices.forEach(async (device) => {
this.log.info(`Configuring device: ${device.deviceName}`);
await device.setAttribute('onOff', 'onOff', false, device.log);
});
}
async onAction(action, value, id, formData) {
this.log.info('onAction called with action:', action, 'and value:', value ?? 'none', 'and id:', id ?? 'none');
this.log.debug('onAction called with formData:', formData ?? 'none');
if (id?.startsWith('root_webhooks_'))
id = id.replace('root_webhooks_', '');
if (id?.endsWith('_test'))
id = id.replace('_test', '');
if (action === 'test') {
if (isValidObject(formData, 1) && isValidObject(formData.webhooks, 1)) {
const webhooks = formData.webhooks;
for (const webhookName in webhooks) {
if (Object.prototype.hasOwnProperty.call(webhooks, webhookName)) {
const webhook = webhooks[webhookName];
if (id?.includes(webhookName)) {
this.log.info(`Testing new webhook ${webhookName} method ${webhook.method} url ${webhook.httpUrl}`);
fetch(webhook.httpUrl, webhook.method)
.then(() => {
this.log.notice(`Webhook test ${webhookName} successful!`);
return;
})
.catch((err) => {
this.log.error(`Webhook test ${webhookName} failed: ${err instanceof Error ? err.message : err}`);
});
}
}
}
return;
}
for (const webhookName in this.webhooks) {
if (Object.prototype.hasOwnProperty.call(this.webhooks, webhookName)) {
const webhook = this.webhooks[webhookName];
if (id?.includes(webhookName)) {
this.log.info(`Testing webhook ${webhookName} method ${webhook.method} url ${webhook.httpUrl}`);
fetch(webhook.httpUrl, webhook.method)
.then(() => {
this.log.notice(`Webhook test ${webhookName} successful!`);
return;
})
.catch((err) => {
this.log.error(`Webhook test ${webhookName} failed: ${err instanceof Error ? err.message : err}`);
});
}
}
}
}
}
async onShutdown(reason) {
await super.onShutdown(reason);
this.log.info('onShutdown called with reason:', reason ?? 'none');
if (this.config.unregisterOnShutdown === true)
await this.unregisterAllDevices();
this.bridgedDevices.clear();
}
}