diff --git a/akashi.pro b/akashi.pro index 8e995b4..611f8f8 100644 --- a/akashi.pro +++ b/akashi.pro @@ -40,6 +40,7 @@ SOURCES += src/advertiser.cpp \ src/commands/roleplay.cpp \ src/config_manager.cpp \ src/db_manager.cpp \ + src/discord.cpp \ src/logger.cpp \ src/main.cpp \ src/packets.cpp \ @@ -55,6 +56,7 @@ HEADERS += include/advertiser.h \ include/area_data.h \ include/config_manager.h \ include/db_manager.h \ + include/discord.h \ include/logger.h \ include/server.h \ include/ws_client.h \ diff --git a/bin/config_sample/config.ini b/bin/config_sample/config.ini index bd43618..a0c7dab 100644 --- a/bin/config_sample/config.ini +++ b/bin/config_sample/config.ini @@ -22,3 +22,7 @@ multiclient_limit=15 [Dice] max_value=100 max_dice=100 + +[Discord] +webhook_enabled=false +webhook_url=Your webhook url here. diff --git a/include/discord.h b/include/discord.h new file mode 100644 index 0000000..c0339cd --- /dev/null +++ b/include/discord.h @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////////////// +// akashi - a server for Attorney Online 2 // +// Copyright (C) 2020 scatterflower // +// // +// This program is free software: you can redistribute it and/or modify // +// it under the terms of the GNU Affero General Public License as // +// published by the Free Software Foundation, either version 3 of the // +// License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU Affero General Public License for more details. // +// // +// You should have received a copy of the GNU Affero General Public License // +// along with this program. If not, see . // +////////////////////////////////////////////////////////////////////////////////////// +#ifndef DISCORD_H +#define DISCORD_H + +#include +#include +#include "server.h" + +class Server; + +class Discord : public QObject { + Q_OBJECT + +public: + /** + * @brief Creates an instance of the Discord class. + * + * @param p_server A pointer to the Server instance Discord is constructed by. + * @param parent Qt-based parent, passed along to inherited constructor from QObject. + */ + Discord(Server* p_server, QObject* parent = nullptr) + : QObject(parent), server(p_server) { + }; + +public slots: + + /** + * @brief Sends a modcall to a discord webhook. + * + * @param name The character or OOC name of the client who sent the modcall. + * @param area The area name of the area the modcall was sent from. + * @param reason The reason the client specified for the modcall. + */ + void postModcallWebhook(QString name, QString area, QString reason); + +private: + + /** + * @brief A pointer to the Server. + */ + Server* server; + +private slots: + + /** + * @brief Sends the reply to the POST request sent by Discord::postModcallWebhook. + */ + void onFinish(QNetworkReply *reply); + +}; + +#endif // DISCORD_H diff --git a/include/server.h b/include/server.h index f96fd79..46b6062 100644 --- a/include/server.h +++ b/include/server.h @@ -23,6 +23,7 @@ #include "include/area_data.h" #include "include/ws_proxy.h" #include "include/db_manager.h" +#include "include/discord.h" #include #include @@ -37,6 +38,7 @@ class AOClient; class DBManager; class AreaData; +class Discord; /** * @brief The class that represents the actual server as it is. @@ -237,6 +239,16 @@ class Server : public QObject { */ int afk_timeout; + /** + * @brief Whether discord webhooks are enabled on this server. + */ + bool webhook_enabled; + + /** + * @brief The URL of the discord webhook. + */ + QString webhook_url; + /** * @brief The server-wide global timer. */ @@ -305,6 +317,15 @@ class Server : public QObject { */ void reloadRequest(QString p_name, QString p_desc); + /** + * @brief Sends a modcall webhook request, emitted by AOClient::pktModcall. + * + * @param name The character or OOC name of the client who sent the modcall. + * @param area_name The name of the area the modcall was sent from. + * @param reason The reason the client specified for the modcall. + */ + void webhookRequest(QString name, QString area_name, QString reason); + private: /** * @brief The proxy used for WebSocket connections. @@ -327,6 +348,11 @@ class Server : public QObject { * @brief The port through which the server will accept WebSocket connections. */ int ws_port; + + /** + * @brief Handles discord webhooks. + */ + Discord* discord; }; #endif // SERVER_H diff --git a/src/discord.cpp b/src/discord.cpp new file mode 100644 index 0000000..173522e --- /dev/null +++ b/src/discord.cpp @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////////////////// +// akashi - a server for Attorney Online 2 // +// Copyright (C) 2020 scatterflower // +// // +// This program is free software: you can redistribute it and/or modify // +// it under the terms of the GNU Affero General Public License as // +// published by the Free Software Foundation, either version 3 of the // +// License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU Affero General Public License for more details. // +// // +// You should have received a copy of the GNU Affero General Public License // +// along with this program. If not, see . // +////////////////////////////////////////////////////////////////////////////////////// +#include "include/discord.h" + +void Discord::postModcallWebhook(QString name, QString area, QString reason) +{ + if (!QUrl (server->webhook_url).isValid()) { + qWarning() << "Invalid webhook url!"; + return; + } + QNetworkRequest request(QUrl (server->webhook_url)); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + // This is the kind of garbage Qt makes me write. + // I am so tired. Qt has broken me. + QJsonObject json; + QJsonArray jsonArray; + QJsonObject jsonObject { + {"color", "13312842"}, + {"title", name + " filed a modcall in " + area}, + {"description", reason} + }; + + jsonArray.append(jsonObject); + json["embeds"] = jsonArray; + + QNetworkAccessManager* nam = new QNetworkAccessManager(); + connect(nam, &QNetworkAccessManager::finished, + this, &Discord::onFinish); + + nam->post(request, QJsonDocument(json).toJson()); +} + +void Discord::onFinish(QNetworkReply *reply) +{ + QByteArray data = reply->readAll(); + QString str_reply = data; + qDebug() << str_reply; +} diff --git a/src/packets.cpp b/src/packets.cpp index 498ed9f..b5f3d59 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -322,6 +322,14 @@ void AOClient::pktModCall(AreaData* area, int argc, QStringList argv, AOPacket p client->sendPacket(packet); } area->logger->logModcall(this, &packet); + + if (server->webhook_enabled) { + QString name = ooc_name; + if (ooc_name.isEmpty()) + name = current_char; + + server->webhookRequest(name, area->name, packet.contents[0]); + } } void AOClient::pktAddEvidence(AreaData* area, int argc, QStringList argv, AOPacket packet) diff --git a/src/server.cpp b/src/server.cpp index 30dea51..f4b00c4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -53,6 +53,13 @@ void Server::start() loadServerConfig(); loadCommandConfig(); + + if (webhook_enabled) { + discord = new Discord(this, this); + connect(this, &Server::webhookRequest, + discord, &Discord::postModcallWebhook); + + } proxy = new WSProxy(port, ws_port, this); if(ws_port != -1) @@ -290,6 +297,11 @@ void Server::loadServerConfig() dice_value = config.value("value_type", "100").toInt(); max_dice = config.value("max_dice","100").toInt(); config.endGroup(); + + //Load discord webhook + config.beginGroup("Discord"); + webhook_enabled = config.value("webhook_enabled", "false").toBool(); + webhook_url = config.value("webhook_url", "Your webhook url here.").toString(); } Server::~Server()