zabbix_export: version: '7.0' media_types: - name: Discord type: WEBHOOK parameters: - name: alert_message value: '{ALERT.MESSAGE}' - name: alert_subject value: '{ALERT.SUBJECT}' - name: discord_endpoint value: '{ALERT.SENDTO}' - name: event_date value: '{EVENT.DATE}' - name: event_id value: '{EVENT.ID}' - name: event_name value: '{EVENT.NAME}' - name: event_nseverity value: '{EVENT.NSEVERITY}' - name: event_opdata value: '{EVENT.OPDATA}' - name: event_recovery_date value: '{EVENT.RECOVERY.DATE}' - name: event_recovery_time value: '{EVENT.RECOVERY.TIME}' - name: event_severity value: '{EVENT.SEVERITY}' - name: event_source value: '{EVENT.SOURCE}' - name: event_tags value: '{EVENT.TAGS}' - name: event_time value: '{EVENT.TIME}' - name: event_update_action value: '{EVENT.UPDATE.ACTION}' - name: event_update_date value: '{EVENT.UPDATE.DATE}' - name: event_update_message value: '{EVENT.UPDATE.MESSAGE}' - name: event_update_status value: '{EVENT.UPDATE.STATUS}' - name: event_update_time value: '{EVENT.UPDATE.TIME}' - name: event_update_user value: '{USER.FULLNAME}' - name: event_value value: '{EVENT.VALUE}' - name: host_ip value: '{HOST.IP}' - name: host_name value: '{HOST.NAME}' - name: trigger_description value: '{TRIGGER.DESCRIPTION}' - name: trigger_id value: '{TRIGGER.ID}' - name: use_default_message value: 'false' - name: zabbix_url value: '{$ZABBIX.URL}' script: | var SEVERITY_COLORS = [ '#97AAB3', // Not classified. '#7499FF', // Information. '#FFC859', // Warning. '#FFA059', // Average. '#E97659', // High. '#E45959', // Disaster. '#009900' // Resolved. ]; function stringTruncate(str, len) { return str.length > len ? str.substring(0, len - 3) + '...' : str; } try { Zabbix.log(4, '[ Discord Webhook ] Executed with params: ' + value); var params = JSON.parse(value); if (!params.discord_endpoint) { throw 'Cannot get discord_endpoint'; } else { params.discord_endpoint = params.discord_endpoint.replace('/api/', '/api/v7/') + '?wait=True'; } params.zabbix_url = (params.zabbix_url.endsWith('/')) ? params.zabbix_url.slice(0, -1) : params.zabbix_url; if ([0, 1, 2, 3, 4].indexOf(parseInt(params.event_source)) === -1) { throw 'Incorrect "event_source" parameter given: "' + params.event_source + '".\nMust be 0-4.'; } // Set params to true for non trigger-based events. if (params.event_source !== '0') { params.use_default_message = 'true'; params.event_nseverity = '0'; } // Check {EVENT.VALUE} for trigger-based and internal events. if (params.event_value !== '0' && params.event_value !== '1' && (params.event_source === '0' || params.event_source === '3')) { throw 'Incorrect "event_value" parameter given: "' + params.event_value + '".\nMust be 0 or 1.'; } // Check {EVENT.UPDATE.STATUS} only for trigger-based events. if (params.event_update_status !== '0' && params.event_update_status !== '1' && params.event_source === '0') { throw 'Incorrect "event_update_status" parameter given: "' + params.event_update_status + '".\nMust be 0 or 1.'; } if (params.event_value == 0) { params.event_nseverity = '6'; } if (!SEVERITY_COLORS[params.event_nseverity]) { throw 'Incorrect "event_nseverity" parameter given: ' + params.event_nseverity + '\nMust be 0-5.'; } var color = parseInt(SEVERITY_COLORS[params.event_nseverity].replace('#', ''), 16), fields = [], body = { embeds: [ { color: color || 0, url: (params.event_source === '0') ? params.zabbix_url + '/tr_events.php?triggerid=' + params.trigger_id + '&eventid=' + params.event_id : params.zabbix_url } ] }; // Default message from {ALERT.MESSAGE}. if (params.use_default_message.toLowerCase() == 'true') { body.embeds[0].title = stringTruncate(params.alert_subject, 256); body.embeds[0].description = stringTruncate(params.alert_message, 2048); } else { fields.push( { name: 'Host', value: params.host_name + ' [' + params.host_ip + ']' } ); // Resolved message. if (params.event_value == 0 && params.event_update_status == 0) { body.embeds[0].title = stringTruncate('OK: ' + params.event_name, 256); fields.push( { name: 'Recovery time', value: params.event_recovery_time + ' ' + params.event_recovery_date, inline: 'True' } ); } // Problem message. else if (params.event_value == 1 && params.event_update_status == 0) { body.embeds[0].title = stringTruncate('PROBLEM: ' + params.event_name, 256); fields.push( { name: 'Event time', value: params.event_time + ' ' + params.event_date, inline: 'True' } ); } // Update message. else if (params.event_update_status == 1) { body.embeds[0].title = stringTruncate('UPDATE: ' + params.event_name, 256); body.embeds[0].description = params.event_update_user + ' ' + params.event_update_action + '.'; if (params.event_update_message) { body.embeds[0].description += ' Comment:\n>>> ' + params.event_update_message; } body.embeds[0].description = stringTruncate(body.embeds[0].description, 2048); fields.push( { name: 'Event update time', value: params.event_update_time + ' ' + params.event_update_date, inline: 'True' } ); } fields.push( { name: 'Severity', value: params.event_severity, inline: 'True' } ); if (params.event_opdata) { fields.push( { name: 'Operational data', value: stringTruncate(params.event_opdata, 1024), inline: 'True' } ); } if (params.event_value == 1 && params.event_update_status == 0 && params.trigger_description) { fields.push( { name: 'Trigger description', value: stringTruncate(params.trigger_description, 1024) } ); } body.embeds[0].footer = { text: 'Event ID: ' + params.event_id }; if (params.event_tags) { body.embeds[0].footer.text += '\nEvent tags: ' + params.event_tags; } body.embeds[0].footer.text = stringTruncate(body.embeds[0].footer.text, 2048); } if (fields.length > 0) { body.embeds[0].fields = fields; } var req = new HttpRequest(); if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') { req.setProxy(params.HTTPProxy); } req.addHeader('Content-Type: application/json'); var resp = req.post(params.discord_endpoint, JSON.stringify(body)), data = JSON.parse(resp); Zabbix.log(4, '[ Discord Webhook ] JSON: ' + JSON.stringify(body)); Zabbix.log(4, '[ Discord Webhook ] Response: ' + resp); if (data.id) { return resp; } else { var message = ((typeof data.message === 'string') ? data.message : 'Unknown error'); Zabbix.log(3, '[ Discord Webhook ] FAILED with response: ' + resp); throw message + '. For more details check zabbix server log.'; } } catch (error) { Zabbix.log(3, '[ Discord Webhook ] ERROR: ' + error); throw 'Sending failed: ' + error; } message_templates: - event_source: TRIGGERS operation_mode: PROBLEM subject: '[{EVENT.STATUS}] {EVENT.NAME}' message: | Problem started at {EVENT.TIME} on {EVENT.DATE} Problem name: {EVENT.NAME} Host: {HOST.NAME} Severity: {EVENT.SEVERITY} Operational data: {EVENT.OPDATA} Original problem ID: {EVENT.ID} {TRIGGER.URL} - event_source: TRIGGERS operation_mode: RECOVERY subject: '[{EVENT.STATUS}] {EVENT.NAME}' message: | Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE} Problem name: {EVENT.NAME} Host: {HOST.NAME} Severity: {EVENT.SEVERITY} Original problem ID: {EVENT.ID} {TRIGGER.URL} - event_source: TRIGGERS operation_mode: UPDATE subject: '[{EVENT.STATUS}] {EVENT.NAME}' message: | {USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}. {EVENT.UPDATE.MESSAGE} Current problem status is {EVENT.STATUS}, acknowledged: {EVENT.ACK.STATUS}. - event_source: DISCOVERY operation_mode: PROBLEM subject: 'Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}' message: | Discovery rule: {DISCOVERY.RULE.NAME} Device IP: {DISCOVERY.DEVICE.IPADDRESS} Device DNS: {DISCOVERY.DEVICE.DNS} Device status: {DISCOVERY.DEVICE.STATUS} Device uptime: {DISCOVERY.DEVICE.UPTIME} Device service name: {DISCOVERY.SERVICE.NAME} Device service port: {DISCOVERY.SERVICE.PORT} Device service status: {DISCOVERY.SERVICE.STATUS} Device service uptime: {DISCOVERY.SERVICE.UPTIME} - event_source: AUTOREGISTRATION operation_mode: PROBLEM subject: 'Autoregistration: {HOST.HOST}' message: | Host name: {HOST.HOST} Host IP: {HOST.IP} Agent port: {HOST.PORT} - event_source: SERVICE operation_mode: PROBLEM subject: 'Service "{SERVICE.NAME}" problem: {EVENT.NAME}' message: | Service problem started at {EVENT.TIME} on {EVENT.DATE} Service problem name: {EVENT.NAME} Service: {SERVICE.NAME} Severity: {EVENT.SEVERITY} Original problem ID: {EVENT.ID} Service description: {SERVICE.DESCRIPTION} {SERVICE.ROOTCAUSE} - event_source: SERVICE operation_mode: RECOVERY subject: 'Service "{SERVICE.NAME}" resolved in {EVENT.DURATION}: {EVENT.NAME}' message: | Service "{SERVICE.NAME}" has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE} Problem name: {EVENT.NAME} Problem duration: {EVENT.DURATION} Severity: {EVENT.SEVERITY} Original problem ID: {EVENT.ID} Service description: {SERVICE.DESCRIPTION} - event_source: SERVICE operation_mode: UPDATE subject: 'Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} in {EVENT.AGE}' message: | Changed "{SERVICE.NAME}" service status to {EVENT.UPDATE.SEVERITY} at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}. Current problem age is {EVENT.AGE}. Service description: {SERVICE.DESCRIPTION} {SERVICE.ROOTCAUSE}