UNPKG

matterbridge-dyson-robot

Version:

A Matterbridge plugin that connects Dyson robot vacuums and air treatment devices to the Matter smart home ecosystem via their local or cloud MQTT APIs.

77 lines 3.39 kB
// Matterbridge plugin for Dyson robot vacuum and air treatment devices // Copyright © 2025-2026 Alexander Thoukydides import { AnsiLogger } from 'matterbridge/logger'; import { formatList } from './utils.js'; // Regular expressions for different types of sensitive data const REGEXP_SERIAL_NUMBER = /[A-Z0-9]{3}-[A-Z]{2}-[A-Z0-9]{8}/g; const REGEXP_CLOUD_TOKEN = /[0-9A-F]{64}-1/g; const REGEXP_EMAIL = /[\w-.]+@([\w-]+\.)+[\w-]+/g; // A logger with filtering and support for an additional prefix export class FilterLogger extends AnsiLogger { delegate; // Configuration config = new Set(); // Log level to be used for debug messages debugLevel = "debug" /* LogLevel.DEBUG */; // Create a new logger constructor(delegate) { super({ extLog: delegate, logTimestampFormat: delegate.logTimestampFormat, logCustomTimestampFormat: delegate.logCustomTimestampFormat }); this.delegate = delegate; } // Get and set the log level (in the delegate logger) get logLevel() { return this.delegate.logLevel; } set logLevel(logLevel) { this.delegate.logLevel = logLevel; } // Get and set the log name (in the delegate logger) get logName() { return this.delegate.logName; } set logName(logName) { this.delegate.logName = logName; } // Log a message with sensitive data filtered log(level, message, ...parameters) { // Allow debug messages to be logged as a different level if (level === "debug" /* LogLevel.DEBUG */ && this.config.has('Log Debug as Info')) { level = "info" /* LogLevel.INFO */; } // Filter the log message and parameters const filteredMessage = this.filterSensitive(message); const filteredParameters = parameters.map(p => this.filterSensitive(p)); // Call the delegate directly (not super.log) to avoid double-logging this.delegate.log(level, filteredMessage, ...filteredParameters); } // Apply configuration configure(config) { for (const feature of config) this.config.add(feature); } // Filter sensitive data within a log message or parameter filterSensitive(value) { const { filtered, redacted } = this.filterString(String(value)); let jsonRedacted = true; try { jsonRedacted = this.filterString(JSON.stringify(value)).redacted; } catch { /* empty */ } return redacted || jsonRedacted ? filtered : value; } // Filter sensitive data within a string filterString(value) { let filtered = value .replace(REGEXP_CLOUD_TOKEN, v => maskToken('TOKEN', v)) .replace(REGEXP_EMAIL, v => maskToken('EMAIL', v)); if (!this.config.has('Log Serial Numbers')) { filtered = filtered.replace(REGEXP_SERIAL_NUMBER, v => maskToken('SERIAL_NUMBER', v)); } return { filtered, redacted: filtered !== value }; } } // Mask a token, leaving just the first and final few characters function maskToken(type, token, details = {}) { let masked = `${token.slice(0, 4)}...${token.slice(-8)}`; const parts = Object.entries(details).map(([key, value]) => `${key}=${value}`); if (parts.length) masked += ` (${formatList(parts)})`; return `<${type}: ${masked}>`; } //# sourceMappingURL=logger-filter.js.map