UNPKG

homebridge-notifyevents

Version:

HomeBridge plugin to send message using Notify.Events service

534 lines (459 loc) 19.4 kB
(function(exports) { const CONFIG_DEFAULT_ACTION = { name: '', title: 'Click Me' }; const CONFIG_DEFAULT_IMAGE = { filename: '' }; const CONFIG_DEFAULT_FILE = { filename: '' }; const CONFIG_DEFAULT_MESSAGE = { name: '', priority: 'normal', level: 'info', images: [], files: [], actions: [] }; const CONFIG_DEFAULT_CHANNEL = { title: 'My Channel', messages: [ CONFIG_DEFAULT_MESSAGE ] }; const CONFIG_DEFAULT_PLATFORM = { platform: 'Notify.Events', action: { enabled: false, listen: '0.0.0.0', port: 53535, host: '', path: '/' }, channels: [ CONFIG_DEFAULT_CHANNEL ] }; const CONFIG = { type: 'object', default: CONFIG_DEFAULT_PLATFORM, properties: { platform: { type: 'string', required: true, default: CONFIG_DEFAULT_PLATFORM.platform }, action: { type: 'object', required: false, properties: { enabled: { type: 'boolean', required: false, default: CONFIG_DEFAULT_PLATFORM.action.enabled }, listen: { type: 'string', required: function (config) { return getValue(config, 'action.enabled'); }, validate: function (value, config, errors, key) { if (!getValue(config, 'action.enabled')) { return value; } if (!isIpv4(value) && !isIpv6(value)) { errors[key] = 'Invalid address'; } return value; }, default: CONFIG_DEFAULT_PLATFORM.action.listen }, port: { type: 'number', required: function (config) { return getValue(config, 'action.enabled'); }, default: CONFIG_DEFAULT_PLATFORM.action.port, min: 1, max: 65535 }, host: { type: 'string', required: function (config) { return getValue(config, 'action.enabled'); }, validate: function (value, config, errors, key) { if (!getValue(config, 'action.enabled')) { return value; } if (!isHost(value)) { errors[key] = 'Invalid host'; } return value; }, default: CONFIG_DEFAULT_PLATFORM.action.host }, path: { type: 'string', required: function (config) { return getValue(config, 'action.enabled'); }, default: CONFIG_DEFAULT_PLATFORM.action.path } }, default: CONFIG_DEFAULT_PLATFORM.action }, channels: { type: 'array', required: true, default: [ CONFIG_DEFAULT_CHANNEL ], items: { type: 'object', default: CONFIG_DEFAULT_CHANNEL, properties: { title: { type: 'string', required: true, default: CONFIG_DEFAULT_CHANNEL.title }, token: { type: 'string', required: true, validate: function (value, config, errors, key) { const regexp = /^[a-z0-9_-]{32}$/gi; if (!regexp.test(value)) { errors[key] = 'Invalid token'; } return value; }, default: CONFIG_DEFAULT_CHANNEL.token, min: 32, max: 32 }, messages: { type: 'array', required: true, default: [ CONFIG_DEFAULT_MESSAGE ], items: { type: 'object', default: CONFIG_DEFAULT_MESSAGE, properties: { name: { type: 'string', required: true, default: CONFIG_DEFAULT_MESSAGE.name }, title: { type: 'string', required: false, default: CONFIG_DEFAULT_MESSAGE.title }, text: { type: 'string', required: true, default: CONFIG_DEFAULT_MESSAGE.text }, priority: { type: 'enum', required: true, default: CONFIG_DEFAULT_MESSAGE.priority, values: [ 'lowest', 'low', 'normal', 'high', 'highest' ] }, level: { type: 'enum', required: true, default: CONFIG_DEFAULT_MESSAGE.level, values: [ 'verbose', 'info', 'notice', 'warning', 'error', 'success' ] }, images: { type: 'array', required: false, default: [], items: { type: 'object', default: CONFIG_DEFAULT_IMAGE, properties: { filename: { type: 'string', required: true, default: CONFIG_DEFAULT_IMAGE.filename } } } }, files: { type: 'array', required: false, default: [], items: { type: 'object', default: CONFIG_DEFAULT_FILE, properties: { filename: { type: 'string', required: true, default: CONFIG_DEFAULT_FILE.filename } } } }, actions: { type: 'array', required: false, default: [], items: { type: 'object', default: CONFIG_DEFAULT_ACTION, properties: { name: { type: 'string', required: true, default: CONFIG_DEFAULT_ACTION.name }, title: { type: 'string', required: true, default: CONFIG_DEFAULT_ACTION.title } } } } } } } } } } } }; const getValue = function(config, path, def = null) { path = path.split('.'); if (path.every(function (key) { if (key in config) { config = config[key]; return true; } return false; })) { return config; } else { return def; } }; const isIpv4 = function(value) { const regexp = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/gi; return regexp.test(value); }; const isIpv6 = function(value) { const regexp = /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/gi; return regexp.test(value); }; const isHost = function(value) { try { new URL('http://' + value + '/'); } catch (e) { return false; } return true; }; const isEmpty = function(value) { if (!value && (value !== false)) { return true; } if (Array.isArray(value) && !value.length) { return true; } if ((typeof(value) === 'string') && !value.trim().length) { return true; } return false; }; const convert_from_1_1_2 = function(platforms) { if (!platforms.length || !('token' in platforms[0])) { return platforms; } let result = { 'platform': 'NotifyEvents', 'channels': [] }; platforms.forEach((platform) => { let channel = { 'title': platform.name, 'token': platform.token, 'messages': [] }; if ('messages' in platform) { platform.messages.forEach((platformMessage) => { let message = { 'name': platformMessage.name, 'title': platformMessage.title, 'text': platformMessage.text, 'priority': platformMessage.priority, 'level': platformMessage.level }; channel.messages.push(message); }); } result.channels.push(channel); }); return [result]; }; const fill = function(value, config, key = 'platform') { if (value === undefined) { value = config.default; } switch (config.type) { case 'object': { if (typeof(value) !== 'object') { value = config.default; } let object = {}; for (let field in config.properties) { object[field] = fill(value[field], config.properties[field], key + '.' + field); } value = object; } break; case 'array': { if (!Array.isArray(value)) { value = config.default; } let array = []; for (let index in value) { array.push(fill(value[index], config.items, key + '.' + index)); } value = array; } break; } return value; }; const validate = function(value, config, errors, key = 'platform', initialValue = null) { if (initialValue === null) { initialValue = value; } let isRequired = ('required' in config) && config.required; if (isRequired && (typeof(config.required) === 'function')) { isRequired = config.required(initialValue); } if (isRequired && isEmpty(value)) { errors[key] = 'Value is required'; } switch (config.type) { case 'undefined': { // Nothing do } break; case 'string': { if (!(key in errors) && (typeof(value) !== 'string')) { if (!isRequired) { break; } errors[key] = 'Value must be a string'; } if (!(key in errors) && ('min' in config) && (config.min > value.length)) { errors[key] = 'Value length should not be less than: ' + config.min; } if (!(key in errors) && ('max' in config) && (config.max < value.length)) { errors[key] = 'Value length should not be more than: ' + config.max; } } break; case 'number': { if (!(key in errors) && (typeof(value) !== 'number')) { if (!isRequired) { break; } errors[key] = 'Value must be a number'; } if (!(key in errors) && ('min' in config) && config.min > value) { errors[key] = 'Value must not be less than: ' + config.min; } if (!(key in errors) && ('max' in config) && config.max < value) { errors[key] = 'Value must not be greater than: ' + config.max; } } break; case 'boolean': { if (typeof(value) !== 'boolean') { if (!isRequired) { break; } errors[key] = 'Value must be a boolean'; } } break; case 'enum': { if (typeof(value) !== 'string') { if (!isRequired) { break; } errors[key] = 'Value must be a string'; break; } if (!config.values.includes(value)) { errors[key] = 'Invalid value'; break; } } break; case 'object': { if (typeof(value) !== 'object') { if (!isRequired) { break; } errors[key] = 'Value must be an object'; break; } let object = {}; for (let field in config.properties) { object[field] = validate(value[field], config.properties[field], errors, key + '.' + field, initialValue); } value = object; } break; case 'array': { if (!Array.isArray(value)) { if (!isRequired) { break; } errors[key] = 'Value must be an array'; break; } let array = []; for (let index in value) { array.push(validate(value[index], config.items, errors, key + '.' + index, initialValue)); } value = array; } break; default: { throw new Error('Unknown type: ' + config.type); } } if (('validate' in config) && !(key in errors)) { value = config.validate(value, initialValue, errors, key); } return value; }; exports.CONFIG = CONFIG; exports.CONFIG_DEFAULT_PLATFORM = CONFIG_DEFAULT_PLATFORM; exports.CONFIG_DEFAULT_CHANNEL = CONFIG_DEFAULT_CHANNEL; exports.CONFIG_DEFAULT_MESSAGE = CONFIG_DEFAULT_MESSAGE; exports.CONFIG_DEFAULT_IMAGE = CONFIG_DEFAULT_IMAGE; exports.CONFIG_DEFAULT_FILE = CONFIG_DEFAULT_FILE; exports.CONFIG_DEFAULT_ACTION = CONFIG_DEFAULT_ACTION; exports.convert_from_1_1_2 = convert_from_1_1_2; exports.fill = fill; exports.validate = validate; })(typeof exports === 'undefined' ? this['common'] = {} : exports);