Reworks plugin loading and structure

Implements #4358
This commit is contained in:
Simone Mainardi 2020-09-15 11:33:50 +02:00
parent 81f55a02a4
commit f7e1ea9709
164 changed files with 106 additions and 84 deletions

View file

@ -0,0 +1,181 @@
--
-- (C) 2020 - ntop.org
--
--
-- This is the core plugin file where everything
-- has birth
--
require "lua_utils"
local json = require "dkjson"
local alert_utils = require "alert_utils"
local endpoint_key = "discord_alert_endpoint"
local discord = {
name = "Discord", -- A human readable name which will be shown in the UI
-- (1) Endpoint (see https://birdie0.github.io/discord-webhooks-guide/tools/curl.html)
conf_params = {
-- Define here the endpoint parameters used in the endpoint GUI
{ param_name = "discord_url" },
},
conf_template = {
plugin_key = endpoint_key, -- Unique string key
-- Filename of the GUI block for this endpoint
-- relative pathname to discord_alert_endpoint/templates/discord_endpoint.template
template_name = "discord_endpoint.template"
},
-- (2) Recipient
recipient_params = {
-- Define here the endpoint parameters used in the recipient GUI
{ param_name = "discord_username" }
},
recipient_template = {
plugin_key = endpoint_key, -- Unique string key
template_name = "discord_recipient.template"
},
}
-- ##############################################
-- How often this script will be called (in seconds) for checking if there are messages to be processes
discord.EXPORT_FREQUENCY = 5
-- ##############################################
-- Extract settings from recipients and place them on a simple datastructure
local function readSettings(recipient)
local settings = {
-- Endpoint
url = recipient.endpoint_conf.discord_url, -- this information is coming from the endpoint configuration recipient.endpoint_conf. ...
-- Recipient
discord_username = recipient.recipient_params.discord_username, -- (**) this information is coming from the recipient configuration recipient.recipient_params. ...
}
return settings
end
-- ##############################################
-- Function called whenever a message has to be sent out to discord
function discord.sendMessage(message_body, settings)
local rc = false
local retry_attempts = 3
local username = settings.discord_username:gsub("%s+", "") -- Zap spaces
if isEmptyString(settings.url) then
return false
end
-- Discord usernames don't have spaces. This line of code will be removed when
-- (***) will be solved and the input will be clean
while retry_attempts > 0 do
local message = {
username = username,
content = message_body,
}
local msg = json.encode(message)
if ntop.httpPost(settings.url, msg) then
rc = true
break
end
retry_attempts = retry_attempts - 1
end
return rc
end
-- ##############################################
local function formatDiscordMessage(alert)
local msg = alert_utils.formatAlertNotification(alert, {nohtml=true, add_cr=true, no_bracket_around_date=true})
return(msg)
end
-- ##############################################
-- Function called periodically to process queued alerts to be delivered via Discord
function discord.dequeueRecipientAlerts(recipient, budget, high_priority)
local start_time = os.time()
local sent = 0
local more_available = true
local budget_used = 0
local settings = readSettings(recipient)
local max_alerts_per_request = 1 -- collapse up to X alerts per request
-- Dequeue alerts up to budget x max_alerts_per_request
-- Note: in this case budget is the number of email to send
while budget_used <= budget and more_available do
local diff = os.time() - start_time
if diff >= 5 then
break
end
-- Dequeue max_alerts_per_request notifications
local notifications = {}
for i=1, max_alerts_per_request do
local notification = ntop.recipient_dequeue(recipient.recipient_id, high_priority)
if notification then
notifications[#notifications + 1] = notification
else
break
end
end
if not notifications or #notifications == 0 then
more_available = false
break
end
local alerts = {}
for _, json_message in ipairs(notifications) do
table.insert(alerts, formatDiscordMessage(json.decode(json_message)))
end
if not discord.sendMessage(table.concat(alerts, "\n"), settings) then
return {success=false, error_message="Unable to send alerts to the discord"}
end
-- Remove the processed messages from the queue
budget_used = budget_used + #notifications
sent = sent + 1
end
return {success = true, more_available = more_available}
end
-- ##############################################
-- This is a testing function invoked by the web GUI whenever a test message has to be sent out
function discord.runTest(recipient)
local message_info
local settings = readSettings(recipient)
local success = discord.sendMessage("test", settings)
if not success then
message_info = i18n("discord_alert_endpoint.discord_send_error")
end
return success, message_info
end
-- ##############################################
return discord

View file

@ -0,0 +1,28 @@
--
-- (C) 2019-20 - ntop.org
--
--
-- Place here the checks for parameters used by this plugins
-- In essence it extends (and references) checks present in
-- scripts/lua/modules/http_lint.lua
--
local script = {}
-- ##############################################
-- @brief Called by the main http_lint module to load additional parameters.
-- @params http_lint a reference to the scripts/lua/modules/http_lint.lua module
-- @return a (possibly empty) table with parameter_name -> validator mappings
function script.getAdditionalParameters(http_lint)
return {
["discord_url"] = { http_lint.webhookCleanup, http_lint.validateUnquoted },
["discord_sender"] = http_lint.validateUnquoted,
["discord_username"] = http_lint.validateEmptyOr(http_lint.validateSingleWord),
}
end
-- ##############################################
return(script)

View file

@ -0,0 +1,18 @@
--
-- (C) 2020 - ntop.org
--
return {
url = "WebHook URL",
username = "Username",
validation = {
empty_url = "Discord Webook URL cannot be empty.",
invalid_url = "Invalid Discord Webhook URL. See https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks.",
invalid_username = "Invalid Discord username.",
},
discord_send_error = "Error sending message to Discord.",
message_sender = "Nickname of the discord message sender (optional). ",
webhook_description = "Instructions:<ul><li>Open the Discord channel you want to receive ntopng notifications from.<li>From the channel menu, select Edit channel (or click on the wheel icon). <li>Click on Webhooks menu item.<li>Click the Create Webhook button and fill in the name of the bot that will post the messages (note that you can set it on the ntopng recipients page)<li>Note the URL from the WebHook URL field to be copied in the field above. <li>Click the Save button.</ul>"
}

View file

@ -0,0 +1,16 @@
--
-- (C) 2019-20 - ntop.org
--
-- This file contains the plugin metadata information.
-- NOTE: Plugins are loaded at startup, any change to this plugin
-- can be applied by restarting ntopng or by manually reloading the
-- plugins from http://127.0.0.1:3000/lua/plugins_overview.lua .
return {
title = "Discords Alert Endpoint",
description = "Provides alerts notifications to discord",
author = "ntop",
dependencies = {},
}

View file

@ -0,0 +1,12 @@
<div class="form-group row">
<label class="col-form-label col-sm-3">
<b>{{ i18n("discord_alert_endpoint.url") }}</b>
</label>
<div class="col-sm-5">
<input
data-validation-message="{{ i18n('discord_alert_endpoint.validation.invalid_url') }}"
data-validation-empty-message="{{ i18n('discord_alert_endpoint.validation.empty_url') }}"
data-pattern="https" name="discord_url" type="text" class="form-control" required />
</div>
</div>
<small>{* i18n('discord_alert_endpoint.webhook_description') *}</small>

View file

@ -0,0 +1,11 @@
<div class="form-group row">
<label class="col-form-label col-sm-3">
{{ i18n("discord_alert_endpoint.username") }}
</label>
<div class="col-sm-5">
<input
data-validation-message="{{ i18n('discord_alert_endpoint.validation.invalid_username') }}"
data-pattern="username" name="discord_username" type="text" class="form-control" />
<small class="text-muted">{{ i18n('discord_alert_endpoint.message_sender') }}</small>
</div>
</div>