Merge pull request from Salanto/refactor-discord

Refactor Discord class to be reloadable
This commit is contained in:
Rosemary Witchaven 2021-08-19 15:00:47 -05:00 committed by GitHub
commit bd6498c35b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 197 additions and 124 deletions

View File

@ -82,36 +82,6 @@ max_value=100
; The maximum number of dice that can be rolled at once.
max_dice=100
[Discord]
; Whether the discord webhook is enabled or not.
; The server will send messages to this webhook whenever a modcall is sent.
; Changing this requires a server restart.
webhook_enabled=false
; The URL of the discord webhook to send messages to. Must contain the webhook ID and token.
webhook_modcall_url=
; Whether to attach a file containing the area log when a modcall message is sent to the webhook.
webhook_modcall_sendfile=false
; Additional text to send with the webhook message. Usually for adding tags for role. Ensure the format is <@&[RoleID]>.
webhook_content=
; Enables the ban webhook.
webhook_ban_enabled = false
; The URL of the ban discord webhook to send messages to. Must contain the webhook ID and token.
webhook_ban_url=
; Enables Uptime Webhook.
webhook_uptime_enabled = false
; The time between message posting. This time is in minutes, with a default of 60.
webhook_uptime_time = 60
; The URL of the uptime discord webhook to send messages to. Must contain the webhook ID and token.
webhook_uptime_url=
[Password]
; Whether or not to enforce password requirements. Only applicable under advanced authorization.
password_requirements = true

View File

@ -0,0 +1,30 @@
[Discord]
; Enables the Discord Webhook Integration
webhook_enabled=false
; Enables the modcall webhook to post a message when a modcall is made.
webhook_modcall_enabled=false
; The URL of the modcall webhook. Must contain the webhook ID and token.
webhook_modcall_url=
; Optional text. Usually for adding tags for roles. Ensure the format is <@&[RoleID]>.
webhook_modcall_content=
; Attaches a logfile of the area to the modcall webhook.
webhook_modcall_sendfile=false
; Enables the ban webhook.
webhook_ban_enabled = false
; The URL of the ban discord webhook to send messages to. Must contain the webhook ID and token.
webhook_ban_url=
; Enables Uptime Webhook.
webhook_uptime_enabled = false
; The time between message posting. Time is in minutes.
webhook_uptime_time = 60
; The URL of the Uptime Webhook. Must contain the webhook ID and token.
webhook_uptime_url=

View File

@ -29,6 +29,7 @@
#include <QSettings>
#include <QUrl>
#include <QMetaEnum>
#include <QElapsedTimer>
/**
* @brief The config file handler class.
@ -191,12 +192,19 @@ class ConfigManager {
static int diceMaxDice();
/**
* @brief Returns true if the discord webhook is enabled.
* @brief Returns true if the discord webhook integration is enabled.
*
* @return See short description.
*/
static bool discordWebhookEnabled();
/**
* @brief Returns true if the discord modcall webhook is enabled.
*
* @return See short description.
*/
static bool discordModcallWebhookEnabled();
/**
* @brief Returns the discord webhook URL.
*
@ -348,6 +356,11 @@ class ConfigManager {
*/
static QUrl advertiserHTTPIP();
/**
* @brief Returns the uptime of the server in miliseconds.
*/
static qint64 uptime();
/**
* @brief Sets the server's authorization type.
*
@ -406,6 +419,16 @@ private:
*/
static QSettings* m_settings;
/**
* @brief Stores all discord webhook configuration values.
*/
static QSettings* m_discord;
/**
* @brief Pointer to QElapsedTimer to track the uptime of the server.
*/
static QElapsedTimer* m_uptimeTimer;
/**
* @brief Returns a stringlist with the contents of a .txt file from config/text/.
*

View File

@ -46,6 +46,67 @@ public:
*/
~Discord();
/**
* @brief Method to start the Uptime Webhook posting timer.
*/
void startUptimeTimer();
/**
* @brief Method to stop the Uptime Webhook posting timer.
*/
void stopUptimeTimer();
public slots:
/**
* @brief Handles a modcall webhook request.
*
* @param f_name The name of the modcall sender.
* @param f_area The name of the area the modcall was sent from.
* @param f_reason The reason for the modcall.
* @param f_buffer The area's log buffer.
*/
void onModcallWebhookRequested(const QString& f_name, const QString& f_area, const QString& f_reason, const QQueue<QString>& f_buffer);
/**
* @brief Handles a ban webhook request.
*
* @param f_ipid The IPID of the client.
* @param f_moderator The name of the moderator banning.
* @param f_duration The date the ban expires.
* @param f_reason The reason of the ban.
*/
void onBanWebhookRequested(const QString& f_ipid, const QString& f_moderator, const QString& f_duration, const QString& f_reason, const int& f_banID);
/**
* @brief Handles a uptime webhook request.
*/
void onUptimeWebhookRequested();
private:
/**
* @brief The QNetworkAccessManager for webhooks.
*/
QNetworkAccessManager* m_nam;
/**
* @brief The QNetworkRequest for webhooks.
*/
QNetworkRequest m_request;
/**
* @brief Timer to post a message that the server is still alive.
*/
QTimer* m_uptimePostTimer;
private slots:
/**
* @brief Handles a network reply from a webhook POST request.
*
* @param f_reply Pointer to the QNetworkReply created by the webhook POST request.
*/
void onReplyFinished(QNetworkReply* f_reply);
/**
* @brief Sends a webhook POST request with the given JSON document.
*
@ -98,67 +159,6 @@ public:
* @return A QHttpMultiPart containing the log file.
*/
QHttpMultiPart* constructLogMultipart(const QQueue<QString>& f_buffer) const;
public slots:
/**
* @brief Handles a modcall webhook request.
*
* @param f_name The name of the modcall sender.
* @param f_area The name of the area the modcall was sent from.
* @param f_reason The reason for the modcall.
* @param f_buffer The area's log buffer.
*/
void onModcallWebhookRequested(const QString& f_name, const QString& f_area, const QString& f_reason, const QQueue<QString>& f_buffer);
/**
* @brief Handles a ban webhook request.
*
* @param f_ipid The IPID of the client.
* @param f_moderator The name of the moderator banning.
* @param f_duration The date the ban expires.
* @param f_reason The reason of the ban.
*/
void onBanWebhookRequested(const QString& f_ipid, const QString& f_moderator, const QString& f_duration, const QString& f_reason, const int& f_banID);
/**
* @brief Handles a uptime webhook request.
*/
void onUptimeWebhookRequested();
private:
/**
* @brief The QNetworkAccessManager for webhooks.
*/
QNetworkAccessManager* m_nam;
/**
* @brief The QNetworkRequest for webhooks.
*/
QNetworkRequest m_request;
/**
* @brief Timer to post a message that the server is still alive.
*/
QTimer* m_uptimePostTimer;
/**
* @brief Stores how long the interval between postings is.
**/
int m_uptimeInterval;
/**
* @brief Proof that Salanto does not know what he is doing.
* @details Counts how often the server alive counter has been posted.
*/
int m_uptimeCounter;
private slots:
/**
* @brief Handles a network reply from a webhook POST request.
*
* @param f_reply Pointer to the QNetworkReply created by the webhook POST request.
*/
void onReplyFinished(QNetworkReply* f_reply);
};
#endif // DISCORD_H

View File

@ -228,6 +228,13 @@ class Server : public QObject {
*/
void allowMessage();
/**
* @brief Method to construct and reconstruct Discord Webhook Integration.
*
* @details Constructs or rebuilds Discord Object during server startup and configuration reload.
*/
void handleDiscordIntegration();
signals:
/**
@ -260,7 +267,14 @@ class Server : public QObject {
*/
void modcallWebhookRequest(const QString& f_name, const QString& f_area, const QString& f_reason, const QQueue<QString>& f_buffer);
/**
* @brief Sends a ban webhook request, emitted by AOClient::cmdBan
* @param f_ipid The IPID of the banned client.
* @param f_moderator The moderator who issued the ban.
* @param f_duration The duration of the ban in a human readable format.
* @param f_reason The reason for the ban.
* @param f_banID The ID of the issued ban.
*/
void banWebhookRequest(const QString& f_ipid, const QString& f_moderator, const QString& f_duration, const QString& f_reason, const int& f_banID);
private:

View File

@ -417,6 +417,7 @@ void AOClient::cmdReload(int argc, QStringList argv)
ConfigManager::reloadSettings();
emit server->reloadRequest(ConfigManager::serverName(), ConfigManager::serverDescription());
server->updateHTTPAdvertiserConfig();
server->handleDiscordIntegration();
sendServerMessage("Reloaded configurations");
}

View File

@ -18,7 +18,9 @@
#include "include/config_manager.h"
QSettings* ConfigManager::m_settings = new QSettings("config/config.ini", QSettings::IniFormat);
QSettings* ConfigManager::m_discord = new QSettings("config/discord.ini", QSettings::IniFormat);
ConfigManager::CommandSettings* ConfigManager::m_commands = new CommandSettings();
QElapsedTimer* ConfigManager::m_uptimeTimer = new QElapsedTimer;
bool ConfigManager::verifyServerConfig()
{
@ -84,12 +86,15 @@ bool ConfigManager::verifyServerConfig()
m_commands->reprimands = (loadConfigFile("reprimands"));
m_commands->gimps = (loadConfigFile("gimp"));
m_uptimeTimer->start();
return true;
}
void ConfigManager::reloadSettings()
{
m_settings->sync();
m_discord->sync();
}
QStringList ConfigManager::loadConfigFile(const QString filename)
@ -267,43 +272,48 @@ int ConfigManager::diceMaxDice()
bool ConfigManager::discordWebhookEnabled()
{
return m_settings->value("Discord/webhook_enabled", false).toBool();
return m_discord->value("Discord/webhook_enabled", false).toBool();
}
bool ConfigManager::discordModcallWebhookEnabled()
{
return m_discord->value("Discord/webhook_modcall_enabled", false).toBool();
}
QString ConfigManager::discordModcallWebhookUrl()
{
return m_settings->value("Discord/webhook_modcall_url", "").toString();
return m_discord->value("Discord/webhook_modcall_url", "").toString();
}
QString ConfigManager::discordWebhookContent()
{
return m_settings->value("Discord/webhook_content", "").toString();
return m_discord->value("Discord/webhook_content", "").toString();
}
bool ConfigManager::discordModcallWebhookSendFile()
{
return m_settings->value("Discord/webhook_modcall_sendfile", false).toBool();
return m_discord->value("Discord/webhook_modcall_sendfile", false).toBool();
}
bool ConfigManager::discordBanWebhookEnabled()
{
return m_settings->value("Discord/webhook_ban_enabled", false).toBool();
return m_discord->value("Discord/webhook_ban_enabled", false).toBool();
}
QString ConfigManager::discordBanWebhookUrl()
{
return m_settings->value("Discord/webhook_ban_url", "").toString();
return m_discord->value("Discord/webhook_ban_url", "").toString();
}
bool ConfigManager::discordUptimeEnabled()
{
return m_settings->value("Discord/webhook_uptime_enabled","false").toBool();
return m_discord->value("Discord/webhook_uptime_enabled","false").toBool();
}
int ConfigManager::discordUptimeTime()
{
bool ok;
int l_aliveTime = m_settings->value("Discord/webhook_uptime_time","60").toInt(&ok);
int l_aliveTime = m_discord->value("Discord/webhook_uptime_time","60").toInt(&ok);
if (!ok) {
qWarning("alive_time is not an int");
l_aliveTime = 60;
@ -313,7 +323,7 @@ int ConfigManager::discordUptimeTime()
QString ConfigManager::discordUptimeWebhookUrl()
{
return m_settings->value("Discord/webhook_uptime_url", "").toString();
return m_discord->value("Discord/webhook_uptime_url", "").toString();
}
bool ConfigManager::passwordRequirements()
@ -414,6 +424,11 @@ QUrl ConfigManager::advertiserHTTPIP()
return m_settings->value("ModernAdvertiser/ms_ip","").toUrl();
}
qint64 ConfigManager::uptime()
{
return m_uptimeTimer->elapsed();
}
void ConfigManager::setMotd(const QString f_motd)
{
m_settings->setValue("Options/motd", f_motd);

View File

@ -24,16 +24,9 @@ Discord::Discord(QObject* parent) :
connect(m_nam, &QNetworkAccessManager::finished,
this, &Discord::onReplyFinished);
if (ConfigManager::discordUptimeEnabled()){
m_uptimePostTimer = new QTimer;
m_uptimeInterval = ConfigManager::discordUptimeTime() * 60000;
m_uptimeCounter = 0;
connect(m_uptimePostTimer, &QTimer::timeout,
this, &Discord::onUptimeWebhookRequested);
m_uptimePostTimer->start(m_uptimeInterval);
onUptimeWebhookRequested();
}
m_uptimePostTimer = new QTimer;
connect(m_uptimePostTimer, &QTimer::timeout,
this, &Discord::onUptimeWebhookRequested);
}
void Discord::onModcallWebhookRequested(const QString &f_name, const QString &f_area, const QString &f_reason, const QQueue<QString> &f_buffer)
@ -57,7 +50,7 @@ void Discord::onBanWebhookRequested(const QString &f_ipid, const QString &f_mode
void Discord::onUptimeWebhookRequested()
{
ulong l_expiredTimeSeconds = (m_uptimeCounter * m_uptimeInterval) / 1000;
qint64 l_expiredTimeSeconds = ConfigManager::uptime() / 1000;
int minutes = (l_expiredTimeSeconds / 60) % 60;
int hours = (l_expiredTimeSeconds / (60 * 60)) % 24;
int days = (l_expiredTimeSeconds / (60 * 60 * 24)) % 365;
@ -66,7 +59,6 @@ void Discord::onUptimeWebhookRequested()
QString f_timeExpired = QString::number(days) + " days, " + QString::number(hours) + " hours and " + QString::number(minutes) + " minutes.";
QJsonDocument l_json = constructUptimeJson(f_timeExpired);
postJsonWebhook(l_json);
m_uptimeCounter++;
}
QJsonDocument Discord::constructModcallJson(const QString &f_name, const QString &f_area, const QString &f_reason) const
@ -107,8 +99,8 @@ QJsonDocument Discord::constructUptimeJson(const QString& f_timeExpired)
QJsonArray l_array;
QJsonObject l_object {
{"color", "13312842"},
{"title", "Your server is still running!"},
{"description", "Hello World!\nYour server has been online for " + f_timeExpired}
{"title", "Your server is online!"},
{"description", "Your server has been online for " + f_timeExpired}
};
l_array.append(l_object);
l_json["embeds"] = l_array;
@ -166,3 +158,14 @@ Discord::~Discord()
{
m_nam->deleteLater();
}
void Discord::startUptimeTimer()
{
m_uptimePostTimer->start(ConfigManager::discordUptimeTime() * 60000);
onUptimeWebhookRequested();
}
void Discord::stopUptimeTimer()
{
m_uptimePostTimer->stop();
}

View File

@ -352,7 +352,7 @@ void AOClient::pktModCall(AreaData* area, int argc, QStringList argv, AOPacket p
}
area->log(current_char, ipid, packet);
if (ConfigManager::discordWebhookEnabled()) {
if (ConfigManager::discordModcallWebhookEnabled()) {
QString name = ooc_name;
if (ooc_name.isEmpty())
name = current_char;

View File

@ -52,13 +52,8 @@ void Server::start()
qDebug() << "Server listening on" << port;
}
if (ConfigManager::discordWebhookEnabled()) {
discord = new Discord(this);
connect(this, &Server::modcallWebhookRequest,
discord, &Discord::onModcallWebhookRequested);
connect(this, &Server::banWebhookRequest,
discord, &Discord::onBanWebhookRequested);
}
discord = new Discord(this);
handleDiscordIntegration();
if (ConfigManager::advertiseHTTPServer()) {
httpAdvertiserTimer = new QTimer(this);
@ -289,6 +284,28 @@ void Server::allowMessage()
can_send_ic_messages = true;
}
void Server::handleDiscordIntegration()
{
// Prevent double connecting by preemtively disconnecting them.
disconnect(this, nullptr, discord, nullptr);
if (ConfigManager::discordWebhookEnabled()) {
if (ConfigManager::discordModcallWebhookEnabled())
connect(this, &Server::modcallWebhookRequest,
discord, &Discord::onModcallWebhookRequested);
if (ConfigManager::discordBanWebhookEnabled())
connect(this, &Server::banWebhookRequest,
discord, &Discord::onBanWebhookRequested);
if (ConfigManager::discordUptimeEnabled())
discord->startUptimeTimer();
else
discord->stopUptimeTimer();
}
return;
}
Server::~Server()
{
for (AOClient* client : clients) {