#include "App.h" #include "Client.h" #include #include #include #include #include #include #include #include #include #include #include #include "SshClient.h" #include "ActiveClient.h" #include "ServerQueryThread.h" #include "Settings.h" App::App(int &argc, char **argv) : QCoreApplication(argc, argv), myServer(new QTcpServer()), mySocketConnectedFlag(false), myQWNETSshClient(new SshClient(this)) { print("CIMS Bot Service v0.101\n=========================================================\n"); setApplicationName("CIMSBOT"); setOrganizationDomain("qwbr.tk"); setOrganizationName("CIMS"); setApplicationVersion("0.101"); myServer->listen(QHostAddress::Any, 45000); connect(myServer, SIGNAL(newConnection()), SLOT(onNewConnection())); myClientsFrameTimerID = startTimer(0); myQWNETSshClient->connectToHost("stomp", "b4r.org"); QThreadPool::globalInstance()->setMaxThreadCount(Settings::globalInstance()->maxThreads()); loadServerList(); Settings::globalInstance()->save(); } App::~App() { Settings::globalInstance()->save(); cleanup(); delete myServer; } void App::onNewConnection() { if(mySocketConnectedFlag) { print("Someone just connected to the bot.\nBye Bye.\n"); mySocket->disconnectFromHost(); if(mySocket->state() != QTcpSocket::UnconnectedState) mySocket->waitForDisconnected(); mySocketConnectedFlag = false; } mySocket = myServer->nextPendingConnection(); mySocketConnectedFlag = true; connect(mySocket, SIGNAL(readyRead()), SLOT(onDataArrival())); connect(mySocket, SIGNAL(disconnected()), SLOT(onDisconnection())); print("Connected to CIMS's bot service.\n"); /* Set socket on clients for echoing */ ActiveClient* ac; foreach(ac, myClients) { ac->client()->setSocket(mySocket); } } void App::onDisconnection() { /* set all sockets to null so it doenst echo anything on a dangling pointer */ ActiveClient* ac; foreach(ac, myClients) { ac->client()->setSocket(NULL); } mySocketConnectedFlag = false; mySocket->deleteLater(); } void App::loadServerList() { QStringList list = Settings::globalInstance()->serverList(); QString sv; foreach(sv, list) { ActiveClient* ac = new ActiveClient(this); QStringList parms = sv.split(':'); ac->setAddressAndStartThread(QHostAddress(parms.at(0)), parms.at(1).toUShort()); ac->client()->setQuakeFolder(Settings::globalInstance()->quakeFolder().toAscii().data()); ac->client()->setName(Settings::globalInstance()->botName().toAscii().data()); ac->client()->setSpectator(Settings::globalInstance()->botSpectator()); ac->client()->setPing(Settings::globalInstance()->botPing()); ac->client()->setColor(Settings::globalInstance()->botTopColor(), Settings::globalInstance()->botBottomColor()); myClients.push_back(ac); } } void App::saveServerList() { QStringList list; ActiveClient* ac; foreach(ac, myClients) list.push_back(ac->serverAddressString()); Settings::globalInstance()->setServerList(list); } void App::parseAddClientCommand(const QString &args) { if(!args.size()) { print("No server specified\n"); return; } if(args.contains(" ")) { print("Invalid server address\n"); return; } QStringList clientData = args.split(":"); if(clientData.size() == 1) { addClient(clientData.at(0), 27500); return; } if(clientData.size() == 2) { addClient(clientData.at(0), clientData.at(1).toUShort()); return; } } void App::parseRemoveClientCommand(const QString &args) { if(!args.size()) { print("No server specified\n"); return; } QStringList clientData = args.split(":"); if(clientData.size() == 1) { removeClient(clientData.at(0), 27500); return; } if(clientData.size() == 2) { removeClient(clientData.at(0), clientData.at(1).toUShort()); return; } } void App::onDataArrival() { while(mySocket->canReadLine()) { QByteArray line; line = mySocket->readLine(); QString data(line); QRegExp regex("([0-9a-zA-Z]+)\\s+([a-z]+)\\s+(.*)"); if(regex.indexIn(data) == -1) { print("command format: ?\nEg.: pss help\nDisconnected\n"); mySocket->disconnectFromHost(); return; } QString pass = regex.capturedTexts().at(1); if(!checkPassword(pass)) { print("Wrong password\nDisconnected\n"); mySocket->disconnectFromHost(); return; } QString cmd = regex.capturedTexts().at(2); QString args = regex.capturedTexts().at(3).trimmed(); if(cmd == "add") { parseAddClientCommand(args); return; } if(cmd == "remove") { parseRemoveClientCommand(args); return; } if(cmd == "say") { say(args); return; } if(cmd == "say_team") { sayTeam(args); return; } if(cmd == "servers") { listClients(); return; } if(cmd == "name") { setNick(args); return; } if(cmd == "color") { setColor(args); return; } if(cmd == "setping") { setPing(args); return; } if(cmd == "team") { setTeam(args); return; } if(cmd == "quit") { mySocket->disconnectFromHost(); return; } if(cmd == "help") { help(); return; } } } void App::help() { print("connect server:port -> connects the bot on a server\n"); print("disconnect server:port -> removes the bot from a server\n"); print("say message -> says the message on all servers where the bot is connected\n"); print("say_team message -> says the message on all servers where the bot is connected\n"); print("servers -> lists all servers the bot is connected\n"); print("name nick -> changes the bot name to nick\n"); print("color x x -> changes the player color\n"); print("setping x -> sets the bot ping to x. ofc you can't lower your actual ping with this.\n"); print("team teamname -> sets the bot team\n"); print("help -> displays this message\n"); } void App::setTeam(const QString &args) { ActiveClient* ac; foreach(ac, myClients) { ac->client()->setTeam(args); } print("Team changed.\n"); } void App::setColor(const QString &args) { ActiveClient* ac; quint8 bottom, top; QStringList colors = args.split(" "); if(colors.size() < 2) return; bottom = colors.at(0).toUShort(); top = colors.at(1).toUShort(); foreach(ac, myClients) { ac->client()->setColor(bottom, top); } print("All clients colors have changed.\n"); } void App::setPing(const QString &args) { ActiveClient* ac; foreach(ac, myClients) { ac->client()->setPing(args.toInt()); } print("All clients pings have changed.\n"); } void App::setNick(const QString &args) { ActiveClient* ac; foreach(ac, myClients) { ac->client()->setName(args.toAscii().data()); } print("All clients nicks have changed.\n"); } bool App::checkPassword(const QString &password) { if(QCryptographicHash::hash(password.toAscii(), QCryptographicHash::Md4).toHex().toLower() == "bf4df9f74d05c50ea00492224fb02854") return true; return false; } void App::print(const QString &msg) { printf("%s", msg.toAscii().data()); if(mySocketConnectedFlag) { mySocket->write(msg.toAscii()); mySocket->waitForBytesWritten(); } } void App::addClient(const QString &host, quint16 port) { ActiveClient* ac; QHostAddress ha = QHostInfo::fromName(host).addresses().at(0); foreach(ac, myClients) { if(QString(ac->client()->host()) == ha.toString() && ac->client()->port() == port) { print("That client is already on the list.\n"); return; } } ac = new ActiveClient(this); if(mySocketConnectedFlag) { if(mySocket->state() == QTcpSocket::ConnectedState) { ac->client()->setSocket(mySocket); } } ac->setAddressAndStartThread(ha, port); ac->client()->setQuakeFolder(Settings::globalInstance()->quakeFolder().toAscii().data()); ac->client()->setName(Settings::globalInstance()->botName().toAscii().data()); ac->client()->setSpectator(Settings::globalInstance()->botSpectator()); ac->client()->setPing(Settings::globalInstance()->botPing()); ac->client()->setColor(Settings::globalInstance()->botTopColor(), Settings::globalInstance()->botBottomColor()); myClients.push_back(ac); saveServerList(); print("Client added to watch list.\n"); } void App::removeClient(const QString &host, quint16 port) { ActiveClient* ac; QHostAddress ha = QHostInfo::fromName(host).addresses().at(0); foreach(ac, myClients) { if(ac->serverAddressString() == QString(ha.toString() + ':' + QString::number(port))) { ac->client()->disconnect(); delete ac; myClients.removeAll(ac); saveServerList(); print("Client removed from watch list.\n"); return; } } print("Client not found on the list.\n"); } void App::say(const QString &msg, int *serverCount, int *userCount) { ActiveClient* ac; *serverCount = 0; *userCount = 0; foreach(ac, myClients) { if(ac->client()->state() == Client::ConnectedState) { ac->client()->say(msg); *userCount += ac->queryThread()->playerCount() - 1; (*serverCount)++; } } print("Say command sent to all clients\n"); } void App::say(const QString &msg) { ActiveClient* ac; foreach(ac, myClients) { if(ac->client()->state() == Client::ConnectedState) { ac->client()->say(msg); } } print("Say command sent to all clients\n"); } void App::sayTeam(const QString &msg) { ActiveClient* ac; foreach(ac, myClients) { ac->client()->sayTeam(msg); } print("Say_team command sent to all clients\n"); } void App::listClients() { ActiveClient* ac; foreach(ac, myClients) { print(QString(ac->serverAddressString() + '\n')); } } void App::activeClientsReplyCounters(int *serverCount, int *playerCount) { ActiveClient* ac; foreach(ac, myClients) { if(ac->client()->state() == Client::ConnectedState) { int pc = ac->queryThread()->playerCount(); if(pc == 255 || pc == 0) pc = 0; else pc--; *playerCount += pc; (*serverCount)++; } } } void App::timerEvent(QTimerEvent *e) { if(e->timerId() == myClientsFrameTimerID) { ActiveClient *ac; foreach(ac, myClients) { ac->run(); } return; } } void App::requestBroadcast(const QString &type, const QString &user, const QString &server, const QString &message) { myQWNETSshClient->write("REQ_BC QDEV,-" + type + "-,qw://" + server + ",'" + user + "','" + message + "'\n"); } void App::broadcast(const QString &msg) { say(msg); } void App::broadcast(const QString &msg, int *serverCount, int *userCount) { say(msg, serverCount, userCount); } void App::cleanup() { ActiveClient* ac; foreach(ac, myClients) { ac->client()->disconnect(); delete ac; } } void App::setReplyHash(const QString &serverAddress, const QString &hash) { ActiveClient* ac; foreach(ac, myClients) { if(serverAddress == ac->serverAddressString()) { ac->setReplyHash(hash); return; } } } void App::incrementReplyCounters(const QString &hash, int userCount, int channelCount, int playerCount, int serverCount) { ActiveClient* ac; foreach(ac, myClients) { if(ac->replyHash() == hash) { ac->incrementReplyCounters(userCount, channelCount, playerCount, serverCount); return; } } }