diff --git a/include/aoclient.h b/include/aoclient.h index 88c78c1..05ec8c6 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -1399,6 +1399,27 @@ class AOClient : public QObject { */ void cmd8Ball(int argc, QStringList argv); + /** + * @brief Sends an out-of-character message with the judgelog of an area. + * + * @details No arguments. + * + * @iscommand + */ + void cmdJudgeLog(int argc, QStringList argv); + + /** + * @brief Looks up info on a ban. + * + * @details If it is called with **one argument**, that argument is the ban ID to look up. + * + * If it is called with **two arguments**, then the first argument is either a ban ID, an IPID, + * or an HDID, and the the second argument specifies the ID type. + * + * @iscommand + */ + void cmdBanInfo(int argc, QStringList argv); + ///@} /** @@ -1592,7 +1613,9 @@ class AOClient : public QObject { {"notecard_clear", {ACLFlags.value("NONE"), 0, &AOClient::cmdNoteCardClear}}, {"8ball", {ACLFlags.value("NONE"), 1, &AOClient::cmd8Ball}}, {"lm", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdLM}}, + {"judgelog", {ACLFlags.value("CM"), 0, &AOClient::cmdJudgeLog}}, {"allow_blankposting", {ACLFlags.value("MODCHAT"), 0, &AOClient::cmdAllow_Blankposting}}, + {"baninfo", {ACLFlags.value("BAN"), 1, &AOClient::cmdBanInfo}}, }; /** @@ -1640,6 +1663,17 @@ class AOClient : public QObject { * @details Used to determine if the incoming message is a duplicate. */ QString last_message; + + /** + * @brief A helper function to add recorded packets to an area's judgelog. + * + * @param area Pointer to the area where the packet was sent. + * + * @param client Pointer to the client that sent the packet. + * + * @param action String containing the info that is being recorded. + */ + void updateJudgeLog(AreaData* area, AOClient* client, QString action); }; #endif // AOCLIENT_H diff --git a/include/area_data.h b/include/area_data.h index 4ed538b..45246a1 100644 --- a/include/area_data.h +++ b/include/area_data.h @@ -278,6 +278,13 @@ class AreaData : public QObject { EvidenceMod evi_mod; QMap notecards; + /** + * @brief The judgelog of an area. + * + * @details This list contains up to 10 recorded packets of the most recent judge actions (WT/CE or penalty updates) in an area. + */ + QStringList judgelog; + /** * @brief The last IC packet sent in an area. */ diff --git a/include/db_manager.h b/include/db_manager.h index 575df07..b696dfe 100644 --- a/include/db_manager.h +++ b/include/db_manager.h @@ -239,6 +239,15 @@ public: */ QStringList getUsers(); + /** + * @brief Gets information on a ban. + * + * @param lookup_type The type of ID to search + * + * @param id A Ban ID, IPID, or HDID to search for + */ + QList getBanInfo(QString lookup_type, QString id); + private: /** * @brief The name of the database connection driver. diff --git a/src/area_data.cpp b/src/area_data.cpp index 95926bb..6c2fad3 100644 --- a/src/area_data.cpp +++ b/src/area_data.cpp @@ -25,6 +25,7 @@ AreaData::AreaData(QString p_name, int p_index) : document("No document."), def_hp(10), pro_hp(10), + judgelog(), last_ic_message() { QStringList name_split = p_name.split(":"); diff --git a/src/commands.cpp b/src/commands.cpp index 9aaff9f..fd65f09 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -1287,6 +1287,24 @@ void AOClient::cmd8Ball(int argc, QStringList argv) } +void AOClient::cmdJudgeLog(int argc, QStringList argv) +{ + AreaData* area = server->areas[current_area]; + if (area->judgelog.isEmpty()) { + sendServerMessage("There have been no judge actions in this area."); + return; + } + QString message = area->judgelog.join("\n"); + //Judgelog contains an IPID, so we shouldn't send that unless the caller has appropriate permissions + if (checkAuth(ACLFlags.value("KICK")) == 1 || checkAuth(ACLFlags.value("BAN")) == 1) { + sendServerMessage(message); + } + else { + QString filteredmessage = message.remove(QRegularExpression("[(].*[)]")); //Filter out anything between two parentheses. This should only ever be the IPID + sendServerMessage(filteredmessage); + } +} + void AOClient::cmdAllow_Blankposting(int argc, QStringList argv) { QString sender_name = ooc_name; @@ -1300,6 +1318,44 @@ void AOClient::cmdAllow_Blankposting(int argc, QStringList argv) } } +void AOClient::cmdBanInfo(int argc, QStringList argv) +{ + QStringList ban_info; + ban_info << ("Ban Info for " + argv[0]); + ban_info << "-----"; + QString lookup_type; + + if (argc == 1) { + lookup_type = "banid"; + } + else if (argc == 2) { + lookup_type = argv[1]; + if (!((lookup_type == "banid") || (lookup_type == "ipid") || (lookup_type == "hdid"))) { + sendServerMessage("Invalid ID type."); + return; + } + } + else { + sendServerMessage("Invalid command."); + return; + } + QString id = argv[0]; + for (DBManager::BanInfo ban : server->db_manager->getBanInfo(lookup_type, id)) { + QString banned_until; + if (ban.duration == -2) + banned_until = "The heat death of the universe"; + else + banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm"); + ban_info << "Affected IPID: " + ban.ipid; + ban_info << "Affected HDID: " + ban.hdid; + ban_info << "Reason for ban: " + ban.reason; + ban_info << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm"); + ban_info << "Ban lasts until: " + banned_until; + ban_info << "-----"; + } + sendServerMessage(ban_info.join("\n")); +} + QStringList AOClient::buildAreaList(int area_idx) { QStringList entries; diff --git a/src/db_manager.cpp b/src/db_manager.cpp index 217ca25..861ec1a 100644 --- a/src/db_manager.cpp +++ b/src/db_manager.cpp @@ -325,6 +325,42 @@ QStringList DBManager::getUsers() return users; } +QList DBManager::getBanInfo(QString lookup_type, QString id) +{ + QList return_list; + QSqlQuery query; + QList invalid; + if (lookup_type == "banid") { + query.prepare("SELECT * FROM BANS WHERE ID = ?"); + } + else if (lookup_type == "hdid") { + query.prepare("SELECT * FROM BANS WHERE HDID = ?"); + } + else if (lookup_type == "ipid") { + query.prepare("SELECT * FROM BANS WHERE IPID = ?"); + } + else { + qCritical("Invalid ban lookup type!"); + return invalid; + } + query.addBindValue(id); + query.setForwardOnly(true); + query.exec(); + + while (query.next()) { + BanInfo ban; + ban.ipid = query.value(0).toString(); + ban.hdid = query.value(1).toString(); + ban.ip = QHostAddress(query.value(2).toString()); + ban.time = static_cast(query.value(3).toULongLong()); + ban.reason = query.value(4).toString(); + ban.duration = query.value(5).toLongLong(); + return_list.append(ban); + } + std::reverse(return_list.begin(), return_list.end()); + return return_list; +} + DBManager::~DBManager() { db.close(); diff --git a/src/packets.cpp b/src/packets.cpp index b5e944a..87db193 100644 --- a/src/packets.cpp +++ b/src/packets.cpp @@ -265,6 +265,7 @@ void AOClient::pktWtCe(AreaData* area, int argc, QStringList argv, AOPacket pack return; last_wtce_time = QDateTime::currentDateTime().toSecsSinceEpoch(); server->broadcast(packet, current_area); + updateJudgeLog(area, this, "WT/CE"); } void AOClient::pktHpBar(AreaData* area, int argc, QStringList argv, AOPacket packet) @@ -281,6 +282,7 @@ void AOClient::pktHpBar(AreaData* area, int argc, QStringList argv, AOPacket pac } server->broadcast(AOPacket("HP", {"1", QString::number(area->def_hp)}), area->index); server->broadcast(AOPacket("HP", {"2", QString::number(area->pro_hp)}), area->index); + updateJudgeLog(area, this, "updated the penalties"); } void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPacket packet) @@ -657,3 +659,21 @@ bool AOClient::checkEvidenceAccess(AreaData *area) return false; } } + +void AOClient::updateJudgeLog(AreaData* area, AOClient* client, QString action) +{ + QString timestamp = QTime::currentTime().toString("hh:mm:ss"); + QString uid = QString::number(client->id); + QString char_name = client->current_char; + QString ipid = client->getIpid(); + QString message = action; + QString logmessage = QString("[%1]: [%2] %3 (%4) %5").arg(timestamp, uid, char_name, ipid, message); + int size = area->judgelog.size(); + if (size == 10) { + area->judgelog.removeFirst(); + area->judgelog.append(logmessage); + } + else area->judgelog.append(logmessage); + + +}