diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index d9a4800c..f9657ced 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -75,6 +75,7 @@ SET(cockatrice_SOURCES src/tab_admin.cpp src/tab_userlists.cpp src/tab_deck_editor.cpp + src/tab_logs.cpp src/replay_timeline_widget.cpp src/deckstats_interface.cpp src/chatview.cpp diff --git a/cockatrice/src/tab_logs.cpp b/cockatrice/src/tab_logs.cpp new file mode 100644 index 00000000..8be008cd --- /dev/null +++ b/cockatrice/src/tab_logs.cpp @@ -0,0 +1,336 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tab_logs.h" +#include "abstractclient.h" +#include "window_sets.h" +#include "pending_command.h" +#include "pb/moderator_commands.pb.h" +#include "pb/response_viewlog_history.pb.h" + +#include +#if QT_VERSION >= 0x050000 +#include +#endif + +TabLog::TabLog(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent) + : Tab(_tabSupervisor, parent), client(_client) +{ + MainWindow = new QMainWindow; + createDock(); + restartLayout(); + clearClicked(); + retranslateUi(); +} + +TabLog::~TabLog() +{ + +} + +void TabLog::retranslateUi() +{ + +} + +void TabLog::getClicked() +{ + if (findUsername->text().isEmpty() && findIPAddress->text().isEmpty() && findGameName->text().isEmpty() && findGameID->text().isEmpty() && findMessage->text().isEmpty()) { + QMessageBox::critical(this, tr("Error"), tr("You must select at least one filter.")); + return; + } + + if (!lastHour->isChecked() && !today->isChecked() && !pastDays->isChecked()){ + pastDays->setChecked(true); + pastXDays->setValue(20); + } + + if (pastDays->isChecked() && pastXDays->value() == 0) { + QMessageBox::critical(this, tr("Error"), tr("You have to select a valid number of days to locate.")); + return; + } + + if (!mainRoom->isChecked() && !gameRoom->isChecked() && !privateChat->isChecked()) { + mainRoom->setChecked(true); + gameRoom->setChecked(true); + privateChat->setChecked(true); + } + + if (maximumResults->value() == 0) + maximumResults->setValue(1000); + + int dateRange; + if (lastHour->isChecked()) + dateRange = 1; + + if (today->isChecked()) + dateRange = 24; + + if (pastDays->isChecked()) + dateRange = pastXDays->value() * 24; + + Command_ViewLogHistory cmd; + cmd.set_user_name(findUsername->text().toStdString()); + cmd.set_ip_address(findIPAddress->text().toStdString()); + cmd.set_game_name(findGameName->text().toStdString()); + cmd.set_game_id(findGameID->text().toStdString()); + cmd.set_message(findMessage->text().toStdString()); + if (mainRoom->isChecked()) { cmd.add_log_location("room"); }; + if (gameRoom->isChecked()) { cmd.add_log_location("game"); }; + if (privateChat->isChecked()) { cmd.add_log_location("chat"); }; + cmd.set_date_range(dateRange); + cmd.set_maximum_results(maximumResults->value()); + PendingCommand *pend = client->prepareModeratorCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(viewLogHistory_processResponse(Response))); + client->sendCommand(pend); +} + +void TabLog::clearClicked() +{ + findUsername->clear(); + findIPAddress->clear(); + findGameName->clear(); + findGameID->clear(); + findMessage->clear(); + pastXDays->clear(); + maximumResults->clear(); + mainRoom->setChecked(false); + gameRoom->setChecked(false); + privateChat->setChecked(false); + pastDays->setAutoExclusive(false); + pastDays->setChecked(false); + today->setAutoExclusive(false); + today->setChecked(false); + lastHour->setAutoExclusive(false); + lastHour->setChecked(false); + pastDays->setAutoExclusive(true); + today->setAutoExclusive(true); + lastHour->setAutoExclusive(true); +} + +void TabLog::createDock() +{ + + labelFindUserName = new QLabel(tr("Username: ")); + findUsername = new QLineEdit(""); + findUsername->setAlignment(Qt::AlignCenter); + labelFindIPAddress = new QLabel(tr("IP Address: ")); + findIPAddress = new QLineEdit(""); + findIPAddress->setAlignment(Qt::AlignCenter); + labelFindGameName = new QLabel(tr("Game Name: ")); + findGameName = new QLineEdit(""); + findGameName->setAlignment(Qt::AlignCenter); + labelFindGameID = new QLabel(tr("GameID: ")); + findGameID = new QLineEdit(""); + findGameID->setAlignment(Qt::AlignCenter); + labelMessage = new QLabel(tr("Message: ")); + findMessage = new QLineEdit(""); + findMessage->setAlignment(Qt::AlignCenter); + + mainRoom = new QCheckBox(tr("Main Room")); + gameRoom = new QCheckBox(tr("Game Room")); + privateChat = new QCheckBox(tr("Private Chat")); + + pastDays = new QRadioButton(tr("Past X Days: ")); + today = new QRadioButton(tr("Today")); + lastHour = new QRadioButton(tr("Last Hour")); + pastXDays = new QSpinBox; + pastXDays->setMaximum(20); + + + labelMaximum = new QLabel(tr("Maximum Results: ")); + maximumResults = new QSpinBox; + maximumResults->setMaximum(1000); + + labelDescription = new QLabel(tr("At least one filter is required.\nThe more information you put in, the more specific your results will be.")); + + getButton = new QPushButton(tr("Get User Logs")); + getButton->setAutoDefault(true); + connect(getButton, SIGNAL(clicked()), this, SLOT(getClicked())); + + clearButton = new QPushButton(tr("Clear Filters")); + clearButton->setAutoDefault(true); + connect(clearButton, SIGNAL(clicked()), this, SLOT(clearClicked())); + + criteriaGrid = new QGridLayout; + criteriaGrid->addWidget(labelFindUserName, 0, 0); + criteriaGrid->addWidget(findUsername, 0, 1); + criteriaGrid->addWidget(labelFindIPAddress, 1, 0); + criteriaGrid->addWidget(findIPAddress, 1, 1); + criteriaGrid->addWidget(labelFindGameName, 2, 0); + criteriaGrid->addWidget(findGameName, 2, 1); + criteriaGrid->addWidget(labelFindGameID, 3, 0); + criteriaGrid->addWidget(findGameID, 3, 1); + criteriaGrid->addWidget(labelMessage, 4, 0); + criteriaGrid->addWidget(findMessage, 4, 1); + + criteriaGroupBox = new QGroupBox(tr("Filters")); + criteriaGroupBox->setLayout(criteriaGrid); + criteriaGroupBox->setFixedSize(500,300); + + locationGrid = new QGridLayout; + locationGrid->addWidget(mainRoom, 0, 0); + locationGrid->addWidget(gameRoom, 0, 1); + locationGrid->addWidget(privateChat, 0, 2); + + locationGroupBox = new QGroupBox(tr("Log Locations")); + locationGroupBox->setLayout(locationGrid); + + rangeGrid = new QGridLayout; + rangeGrid->addWidget(pastDays, 0, 0); + rangeGrid->addWidget(pastXDays, 0, 1); + rangeGrid->addWidget(today, 0, 2); + rangeGrid->addWidget(lastHour, 0, 3); + + rangeGroupBox = new QGroupBox(tr("Date Range")); + rangeGroupBox->setLayout(rangeGrid); + + maxResultsGrid = new QGridLayout; + maxResultsGrid->addWidget(labelMaximum, 0, 0); + maxResultsGrid->addWidget(maximumResults, 0, 1); + + maxResultsGroupBox = new QGroupBox(tr("Maximum Results")); + maxResultsGroupBox->setLayout(maxResultsGrid); + + descriptionGrid = new QGridLayout; + descriptionGrid->addWidget(labelDescription, 0, 0); + + descriptionGroupBox = new QGroupBox(tr("")); + descriptionGroupBox->setLayout(descriptionGrid); + + buttonGrid = new QGridLayout; + buttonGrid->addWidget(getButton, 0, 0); + buttonGrid->addWidget(clearButton, 0, 1); + + buttonGroupBox = new QGroupBox(tr("")); + buttonGroupBox->setLayout(buttonGrid); + + mainLayout = new QVBoxLayout(MainWindow); + mainLayout->addWidget(criteriaGroupBox); + mainLayout->addWidget(locationGroupBox); + mainLayout->addWidget(rangeGroupBox); + mainLayout->addWidget(maxResultsGroupBox); + mainLayout->addWidget(descriptionGroupBox); + mainLayout->addWidget(buttonGroupBox); + mainLayout->setAlignment(Qt::AlignCenter); + + searchDockContents = new QWidget(MainWindow); + searchDockContents->setLayout(mainLayout); + + searchDock = new QDockWidget(MainWindow); + searchDock->setFeatures(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable); + searchDock->setWidget(searchDockContents); + + QVBoxLayout *mainVLayoutContent = new QVBoxLayout; + QHBoxLayout *mainHLayoutContent = new QHBoxLayout; + mainHLayoutContent->addWidget(MainWindow); + mainHLayoutContent->addLayout(mainVLayoutContent); + setLayout(mainHLayoutContent); +} + +void TabLog::viewLogHistory_processResponse(const Response &resp) +{ + const Response_ViewLogHistory &response = resp.GetExtension(Response_ViewLogHistory::ext); + if (resp.response_code() == Response::RespOk) { + + if (response.log_message_size() > 0) { + + int j = 0; + QTableWidget *roomTable = new QTableWidget(); + roomTable->setWindowTitle(tr("Room Logs")); + roomTable->setRowCount(response.log_message_size()); + roomTable->setColumnCount(6); + roomTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + roomTable->setHorizontalHeaderLabels(QString(tr("Time;SenderName;SenderIP;Message;TargetID;TargetName")).split(";")); + + int k = 0; + QTableWidget *gameTable = new QTableWidget(); + gameTable->setWindowTitle(tr("Game Logs")); + gameTable->setRowCount(response.log_message_size()); + gameTable->setColumnCount(6); + gameTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + gameTable->setHorizontalHeaderLabels(QString(tr("Time;SenderName;SenderIP;Message;TargetID;TargetName")).split(";")); + + int l = 0; + QTableWidget *chatTable = new QTableWidget(); + chatTable->setWindowTitle(tr("Chat Logs")); + chatTable->setRowCount(response.log_message_size()); + chatTable->setColumnCount(6); + chatTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + chatTable->setHorizontalHeaderLabels(QString(tr("Time;SenderName;SenderIP;Message;TargetID;TargetName")).split(";")); + + ServerInfo_ChatMessage message; for (int i = 0; i < response.log_message_size(); ++i) { + message = response.log_message(i); + if (QString::fromStdString(message.target_type()) == "room") { + roomTable->setItem(j, 0, new QTableWidgetItem(QString::fromStdString(message.time()))); + roomTable->setItem(j, 1, new QTableWidgetItem(QString::fromStdString(message.sender_name()))); + roomTable->setItem(j, 2, new QTableWidgetItem(QString::fromStdString(message.sender_ip()))); + roomTable->setItem(j, 3, new QTableWidgetItem(QString::fromStdString(message.message()))); + roomTable->setItem(j, 4, new QTableWidgetItem(QString::fromStdString(message.target_id()))); + roomTable->setItem(j, 5, new QTableWidgetItem(QString::fromStdString(message.target_name()))); + ++j; + } + + if (QString::fromStdString(message.target_type()) == "game") { + gameTable->setItem(k, 0, new QTableWidgetItem(QString::fromStdString(message.time()))); + gameTable->setItem(k, 1, new QTableWidgetItem(QString::fromStdString(message.sender_name()))); + gameTable->setItem(k, 2, new QTableWidgetItem(QString::fromStdString(message.sender_ip()))); + gameTable->setItem(k, 3, new QTableWidgetItem(QString::fromStdString(message.message()))); + gameTable->setItem(k, 4, new QTableWidgetItem(QString::fromStdString(message.target_id()))); + gameTable->setItem(k, 5, new QTableWidgetItem(QString::fromStdString(message.target_name()))); + ++k; + } + + if (QString::fromStdString(message.target_type()) == "chat") { + chatTable->setItem(l, 0, new QTableWidgetItem(QString::fromStdString(message.time()))); + chatTable->setItem(l, 1, new QTableWidgetItem(QString::fromStdString(message.sender_name()))); + chatTable->setItem(l, 2, new QTableWidgetItem(QString::fromStdString(message.sender_ip()))); + chatTable->setItem(l, 3, new QTableWidgetItem(QString::fromStdString(message.message()))); + chatTable->setItem(l, 4, new QTableWidgetItem(QString::fromStdString(message.target_id()))); + chatTable->setItem(l, 5, new QTableWidgetItem(QString::fromStdString(message.target_name()))); + ++l; + } + } + + roomTable->setRowCount(j); + roomTable->resizeColumnsToContents(); + gameTable->setRowCount(k); + gameTable->resizeColumnsToContents(); + chatTable->setRowCount(l); + chatTable->resizeColumnsToContents(); + + if (mainRoom->isChecked()) { + roomTable->resize(600, 200); + roomTable->show(); + } + + if (gameRoom->isChecked()) { + gameTable->resize(600, 200); + gameTable->show(); + } + + if (privateChat->isChecked()) { + chatTable->resize(600, 200); + chatTable->show(); + } + + } else + QMessageBox::information(static_cast(parent()), tr("Message History"), tr("There is no messages for the selected iilters.")); + + } else + QMessageBox::critical(static_cast(parent()), tr("Message History"), tr("Failed to collecting message history information.")); +} + +void TabLog::restartLayout() +{ + searchDock->setFloating(false); + MainWindow->addDockWidget(Qt::TopDockWidgetArea, searchDock); + searchDock->setVisible(true); +} \ No newline at end of file diff --git a/cockatrice/src/tab_logs.h b/cockatrice/src/tab_logs.h new file mode 100644 index 00000000..ab848c66 --- /dev/null +++ b/cockatrice/src/tab_logs.h @@ -0,0 +1,57 @@ +#ifndef TAB_LOG_H +#define TAB_LOG_H + +#include "tab.h" +#include + +class AbstractClient; + +class QGroupBox; +class QPushButton; +class QSpinBox; +class QLineEdit; +class QCheckBox; +class QRadioButton; +class QLabel; +class QDockWidget; +class QWidget; +class QGridLayout; +class CommandContainer; +class Response; +class AbstractClient; +class QMainWindow; + +class TabLog : public Tab { + Q_OBJECT +private: + AbstractClient *client; + QLabel *labelFindUserName, *labelFindIPAddress, *labelFindGameName, *labelFindGameID, *labelMessage, *labelMaximum, *labelDescription; + QLineEdit *findUsername, *findIPAddress, *findGameName, *findGameID, *findMessage; + QCheckBox *mainRoom, *gameRoom, *privateChat; + QRadioButton *pastDays, *today, *lastHour; + QSpinBox *maximumResults, *pastXDays; + QDockWidget *searchDock; + QWidget *searchDockContents; + QPushButton *getButton, *clearButton; + QGridLayout *criteriaGrid, *locationGrid, *rangeGrid, *maxResultsGrid, *descriptionGrid, *buttonGrid; + QGroupBox *criteriaGroupBox, *locationGroupBox, *rangeGroupBox, *maxResultsGroupBox, *descriptionGroupBox, *buttonGroupBox; + QVBoxLayout *mainLayout; + QMainWindow *MainWindow; + + void createDock(); +signals: + +private slots: + void getClicked(); + void clearClicked(); + void viewLogHistory_processResponse(const Response &resp); + void restartLayout(); + +public: + TabLog(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent = 0); + ~TabLog(); + void retranslateUi(); + QString getTabText() const { return tr("Logs"); } +}; + +#endif diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index 2dcbb49b..efb8a51f 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -13,6 +13,7 @@ #include "tab_message.h" #include "tab_userlists.h" #include "tab_deck_editor.h" +#include "tab_logs.h" #include "pixmapgenerator.h" #include "userlist.h" #include "settingscache.h" @@ -79,7 +80,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/) } TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent) - : QTabWidget(parent), userInfo(0), client(_client), tabServer(0), tabUserLists(0), tabDeckStorage(0), tabReplays(0), tabAdmin(0) + : QTabWidget(parent), userInfo(0), client(_client), tabServer(0), tabUserLists(0), tabDeckStorage(0), tabReplays(0), tabAdmin(0), tabLog(0) { setElideMode(Qt::ElideRight); setMovable(true); @@ -109,6 +110,7 @@ void TabSupervisor::retranslateUi() tabs.append(tabDeckStorage); tabs.append(tabAdmin); tabs.append(tabUserLists); + tabs.append(tabLog); QMapIterator roomIterator(roomTabs); while (roomIterator.hasNext()) tabs.append(roomIterator.next().value()); @@ -183,42 +185,54 @@ int TabSupervisor::myAddTab(Tab *tab) return idx; } -void TabSupervisor::start(const ServerInfo_User &_userInfo) -{ +void TabSupervisor::start(const ServerInfo_User &_userInfo) { isLocalGame = false; userInfo = new ServerInfo_User(_userInfo); - + tabServer = new TabServer(this, client); - connect(tabServer, SIGNAL(roomJoined(const ServerInfo_Room &, bool)), this, SLOT(addRoomTab(const ServerInfo_Room &, bool))); + connect(tabServer, SIGNAL(roomJoined( + const ServerInfo_Room &, bool)), this, SLOT(addRoomTab( + const ServerInfo_Room &, bool))); myAddTab(tabServer); - + tabUserLists = new TabUserLists(this, client, *userInfo); - connect(tabUserLists, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); + connect(tabUserLists, SIGNAL(openMessageDialog( + const QString &, bool)), this, SLOT(addMessageTab( + const QString &, bool))); connect(tabUserLists, SIGNAL(userJoined(ServerInfo_User)), this, SLOT(processUserJoined(ServerInfo_User))); - connect(tabUserLists, SIGNAL(userLeft(const QString &)), this, SLOT(processUserLeft(const QString &))); + connect(tabUserLists, SIGNAL(userLeft( + const QString &)), this, SLOT(processUserLeft( + const QString &))); myAddTab(tabUserLists); - + updatePingTime(0, -1); - + if (userInfo->user_level() & ServerInfo_User::IsRegistered) { tabDeckStorage = new TabDeckStorage(this, client); - connect(tabDeckStorage, SIGNAL(openDeckEditor(const DeckLoader *)), this, SLOT(addDeckEditorTab(const DeckLoader *))); + connect(tabDeckStorage, SIGNAL(openDeckEditor( + const DeckLoader *)), this, SLOT(addDeckEditorTab( + const DeckLoader *))); myAddTab(tabDeckStorage); - + tabReplays = new TabReplays(this, client); - connect(tabReplays, SIGNAL(openReplay(GameReplay *)), this, SLOT(openReplay(GameReplay *))); + connect(tabReplays, SIGNAL(openReplay(GameReplay * )), this, SLOT(openReplay(GameReplay * ))); myAddTab(tabReplays); } else { tabDeckStorage = 0; tabReplays = 0; } - + if (userInfo->user_level() & ServerInfo_User::IsModerator) { tabAdmin = new TabAdmin(this, client, (userInfo->user_level() & ServerInfo_User::IsAdmin)); connect(tabAdmin, SIGNAL(adminLockChanged(bool)), this, SIGNAL(adminLockChanged(bool))); myAddTab(tabAdmin); - } else + + tabLog = new TabLog(this, client); + myAddTab(tabLog); + } else { tabAdmin = 0; + tabLog = 0; + } retranslateUi(); } @@ -229,6 +243,7 @@ void TabSupervisor::startLocal(const QList &_clients) tabDeckStorage = 0; tabReplays = 0; tabAdmin = 0; + tabLog = 0; isLocalGame = true; userInfo = new ServerInfo_User; localClients = _clients; @@ -259,12 +274,15 @@ void TabSupervisor::stop() tabReplays->deleteLater(); if (tabAdmin) tabAdmin->deleteLater(); + if (tabLog) + tabLog->deleteLater(); } tabUserLists = 0; tabServer = 0; tabDeckStorage = 0; tabReplays = 0; tabAdmin = 0; + tabLog = 0; QMapIterator roomIterator(roomTabs); while (roomIterator.hasNext()) @@ -280,7 +298,7 @@ void TabSupervisor::stop() while (replayIterator.hasNext()) replayIterator.next()->deleteLater(); replayTabs.clear(); - + delete userInfo; userInfo = 0; } diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index d88dc62f..027ba64f 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -18,6 +18,7 @@ class TabAdmin; class TabMessage; class TabUserLists; class TabDeckEditor; +class TabLog; class RoomEvent; class GameEventContainer; class Event_GameJoined; @@ -51,6 +52,7 @@ private: TabDeckStorage *tabDeckStorage; TabReplays *tabReplays; TabAdmin *tabAdmin; + TabLog *tabLog; QMap roomTabs; QMap gameTabs; QList replayTabs; diff --git a/common/featureset.cpp b/common/featureset.cpp index 59135bfa..3c721df8 100644 --- a/common/featureset.cpp +++ b/common/featureset.cpp @@ -19,6 +19,7 @@ void FeatureSet::initalizeFeatureList(QMap &featureList) { featureList.insert("user_ban_history", false); featureList.insert("room_chat_history", false); featureList.insert("client_warnings", false); + featureList.insert("mod_log_lookup", false); } void FeatureSet::enableRequiredFeature(QMap &featureList, QString featureName){ diff --git a/common/pb/CMakeLists.txt b/common/pb/CMakeLists.txt index 875b067a..19677b93 100644 --- a/common/pb/CMakeLists.txt +++ b/common/pb/CMakeLists.txt @@ -132,6 +132,7 @@ SET(PROTO_FILES response_adjust_mod.proto response_warn_history.proto response_warn_list.proto + response_viewlog_history.proto response.proto room_commands.proto room_event.proto diff --git a/common/pb/moderator_commands.proto b/common/pb/moderator_commands.proto index 0c6b473b..e2cf306c 100644 --- a/common/pb/moderator_commands.proto +++ b/common/pb/moderator_commands.proto @@ -6,6 +6,7 @@ message ModeratorCommand { WARN_USER = 1002; WARN_HISTORY = 1003; WARN_LIST = 1004; + VIEWLOG_HISTORY = 1005; } extensions 100 to max; } @@ -53,4 +54,19 @@ message Command_GetWarnList { optional string mod_name = 1; optional string user_name = 2; optional string user_clientid = 3; +} + +message Command_ViewLogHistory { + extend ModeratorCommand { + optional Command_ViewLogHistory ext = 1005; + } + optional string user_name = 1; // user that created message + optional string ip_address = 2; // ip address of user that created message + optional string game_name = 3; // client id of user that created the message + optional string game_id = 4; // game number the message was sent to + optional string message = 5; // raw message that was sent + repeated string log_location = 6; // destination of message (ex: main room, game room, private chat) + required uint32 date_range = 7; // the length of time (in minutes) to look back for + optional uint32 maximum_results = 8; // the maximum number of query results + } \ No newline at end of file diff --git a/common/pb/response.proto b/common/pb/response.proto index a2947a0e..5f53f8e3 100644 --- a/common/pb/response.proto +++ b/common/pb/response.proto @@ -55,6 +55,7 @@ message Response { BAN_HISTORY = 1012; WARN_HISTORY = 1013; WARN_LIST = 1014; + VIEW_LOG = 1015; REPLAY_LIST = 1100; REPLAY_DOWNLOAD = 1101; } diff --git a/common/pb/response_viewlog_history.proto b/common/pb/response_viewlog_history.proto new file mode 100644 index 00000000..2572d7d2 --- /dev/null +++ b/common/pb/response_viewlog_history.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; +import "response.proto"; +import "serverinfo_chat_message.proto"; + +message Response_ViewLogHistory{ + extend Response { + optional Response_ViewLogHistory ext = 1015; + } + repeated ServerInfo_ChatMessage log_message = 1; +} diff --git a/common/server.h b/common/server.h index 490d8b95..9dc40fff 100644 --- a/common/server.h +++ b/common/server.h @@ -11,6 +11,7 @@ #include "pb/serverinfo_user.pb.h" #include "pb/serverinfo_ban.pb.h" #include "pb/serverinfo_warning.pb.h" +#include "pb/serverinfo_chat_message.pb.h" #include "server_player_reference.h" class Server_DatabaseInterface; diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index d4845be1..33b6ea9a 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -940,7 +940,6 @@ QList Servatrice_DatabaseInterface::getUserBanHistory(const QStr return results; } - //QString adminID,adminName,banTime,banLength,banReason,visibleReason; while (query->next()){ banDetails.set_admin_id(QString(query->value(0).toString()).toStdString()); banDetails.set_admin_name(QString(query->value(5).toString()).toStdString()); @@ -1000,4 +999,87 @@ QList Servatrice_DatabaseInterface::getUserWarnHistory(const } return results; -} \ No newline at end of file +} + +QList Servatrice_DatabaseInterface::getMessageLogHistory(const QString &user, const QString &ipaddress, const QString &gamename, const QString &gameid, const QString &message, bool &chat, bool &game, bool &room, int &range, int &maxresults) +{ + + QList results; + ServerInfo_ChatMessage chatMessage; + + if (!checkSql()) + return results; + + // BUILD QUERY STRING BASED ON PASSED IN VALUES + QString queryString = "SELECT * FROM cockatrice_log WHERE `sender_ip` IS NOT NULL"; + if (!user.isEmpty()) + queryString.append(" AND (`sender_name` = :user_name OR `target_name` = :user_name)"); + + if (!ipaddress.isEmpty()) + queryString.append(" AND `sender_ip` = :ip_to_find"); + + if (!gameid.isEmpty()) + queryString.append(" AND (`target_id` = :game_id AND `target_type` = 'game')"); + + if (!gamename.isEmpty()) + queryString.append(" AND (`target_name` = :game_name AND `target_type` = 'game')"); + + if (!message.isEmpty()) + queryString.append(" AND `log_message` LIKE :log_message"); + + if (chat || game || room) { + queryString.append(" AND ("); + + if (chat) + queryString.append("`target_type` = 'chat'"); + + if (game) { + if (chat) + queryString.append(" OR `target_type` = 'game'"); + else + queryString.append("`target_type` = 'game'"); + } + + if (room) { + if (game || chat) + queryString.append(" OR `target_type` = 'room'"); + else + queryString.append("`target_type` = 'room'"); + } + queryString.append(")"); + } + + if (range) + queryString.append(" AND log_time >= DATE_SUB(now(), INTERVAL :range_time HOUR)"); + + if (maxresults) + queryString.append(" LIMIT :limit_size"); + + QSqlQuery *query = prepareQuery(queryString); + if (!user.isEmpty()) { query->bindValue(":user_name", user); } + if (!ipaddress.isEmpty()) { query->bindValue(":ip_to_find", ipaddress); } + if (!gameid.isEmpty()) { query->bindValue(":game_id", gameid); } + if (!gamename.isEmpty()) { query->bindValue(":game_name", gamename); } + if (!message.isEmpty()) { query->bindValue(":log_message", message); } + if (range) { query->bindValue(":range_time", range); } + if (maxresults) { query->bindValue(":limit_size", maxresults); } + + if (!execSqlQuery(query)) { + qDebug("Failed to collect log history information: SQL Error"); + return results; + } + + while (query->next()) { + chatMessage.set_time(QString(query->value(0).toString()).toStdString()); + chatMessage.set_sender_id(QString(query->value(1).toString()).toStdString()); + chatMessage.set_sender_name(QString(query->value(2).toString()).toStdString()); + chatMessage.set_sender_ip(QString(query->value(3).toString()).toStdString()); + chatMessage.set_message(QString(query->value(4).toString()).toStdString()); + chatMessage.set_target_type(QString(query->value(5).toString()).toStdString()); + chatMessage.set_target_id(QString(query->value(6).toString()).toStdString()); + chatMessage.set_target_name(QString(query->value(7).toString()).toStdString()); + results << chatMessage; + } + + return results; +} diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index 23bdf3e4..7d4bf241 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -81,6 +81,7 @@ public: QList getUserBanHistory(const QString userName); bool addWarning(const QString userName, const QString adminName, const QString warningReason, const QString clientID); QList getUserWarnHistory(const QString userName); + QList getMessageLogHistory(const QString &user, const QString &ipaddress, const QString &gamename, const QString &gameid, const QString &message, bool &chat, bool &game, bool &room, int &range, int &maxresults); }; #endif diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 0ab23783..f7b73300 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -61,10 +61,12 @@ #include "pb/response_replay_download.pb.h" #include "pb/response_warn_history.pb.h" #include "pb/response_warn_list.pb.h" +#include "pb/response_viewlog_history.pb.h" #include "pb/serverinfo_replay.pb.h" #include "pb/serverinfo_user.pb.h" #include "pb/serverinfo_deckstorage.pb.h" #include "pb/serverinfo_ban.pb.h" +#include "pb/serverinfo_chat_message.pb.h" #include "version_string.h" #include @@ -310,6 +312,7 @@ Response::ResponseCode ServerSocketInterface::processExtendedModeratorCommand(in case ModeratorCommand::WARN_USER: return cmdWarnUser(cmd.GetExtension(Command_WarnUser::ext), rc); case ModeratorCommand::WARN_HISTORY: return cmdGetWarnHistory(cmd.GetExtension(Command_GetWarnHistory::ext), rc); case ModeratorCommand::WARN_LIST: return cmdGetWarnList(cmd.GetExtension(Command_GetWarnList::ext), rc); + case ModeratorCommand::VIEWLOG_HISTORY: return cmdGetLogHistory(cmd.GetExtension(Command_ViewLogHistory::ext), rc); default: return Response::RespFunctionNotAllowed; } } @@ -770,6 +773,38 @@ Response::ResponseCode ServerSocketInterface::cmdReplayDeleteMatch(const Command // MODERATOR FUNCTIONS. // May be called by admins and moderators. Permission is checked by the calling function. +Response::ResponseCode ServerSocketInterface::cmdGetLogHistory(const Command_ViewLogHistory &cmd, ResponseContainer &rc) +{ + + QList messageList; + QString userName = QString::fromStdString(cmd.user_name()); + QString ipAddress = QString::fromStdString(cmd.ip_address()); + QString gameName = QString::fromStdString(cmd.game_name()); + QString gameID = QString::fromStdString(cmd.game_id()); + QString message = QString::fromStdString(cmd.message()); + bool chatType = false; + bool gameType = false; + bool roomType = false; + + for (int i = 0; i != cmd.log_location_size(); ++i) { + if (QString::fromStdString(cmd.log_location(i)).simplified() == "room") + roomType = true; + if (QString::fromStdString(cmd.log_location(i)).simplified() == "game") + gameType = true; + if (QString::fromStdString(cmd.log_location(i)).simplified() == "chat") + chatType = true; + } + + int dateRange = cmd.date_range(); + int maximumResults = cmd.maximum_results(); + + Response_ViewLogHistory *re = new Response_ViewLogHistory; + QListIterator messageIterator(sqlInterface->getMessageLogHistory(userName,ipAddress,gameName,gameID,message,chatType,gameType,roomType,dateRange,maximumResults)); + while (messageIterator.hasNext()) + re->add_log_message()->CopyFrom(messageIterator.next()); + rc.setResponseExtension(re); + return Response::RespOk; +} Response::ResponseCode ServerSocketInterface::cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc) { diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index 0ba2f60b..05374987 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -98,6 +98,7 @@ private: Response::ResponseCode cmdReplayDeleteMatch(const Command_ReplayDeleteMatch &cmd, ResponseContainer &rc); Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc); Response::ResponseCode cmdWarnUser(const Command_WarnUser &cmd, ResponseContainer &rc); + Response::ResponseCode cmdGetLogHistory(const Command_ViewLogHistory &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetBanHistory(const Command_GetBanHistory &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetWarnList(const Command_GetWarnList &cmd, ResponseContainer &rc); Response::ResponseCode cmdGetWarnHistory(const Command_GetWarnHistory &cmd, ResponseContainer &rc);