diff --git a/SparrowBot.pro b/SparrowBot.pro index 3a23cf0..2071559 100644 --- a/SparrowBot.pro +++ b/SparrowBot.pro @@ -16,7 +16,9 @@ SOURCES += mainwindow.cpp \ user.cpp \ prompt.cpp \ ircbot.cpp \ - botapp.cpp + botapp.cpp \ + module.cpp \ + basemodule.cpp HEADERS += mainwindow.h \ socketirc.h \ @@ -24,6 +26,8 @@ HEADERS += mainwindow.h \ user.h \ prompt.h \ ircbot.h \ - botapp.h + botapp.h \ + module.h \ + basemodule.h FORMS += mainwindow.ui diff --git a/basemodule.cpp b/basemodule.cpp new file mode 100644 index 0000000..17e60c1 --- /dev/null +++ b/basemodule.cpp @@ -0,0 +1,120 @@ +#include "basemodule.h" + +BaseModule::BaseModule() : Module(), status(OFFLINE) +{ + +} + +bool BaseModule::messageHandler(Message msg) +{ + switch(status) + { + case OFFLINE : + status = ONLINE; + emit sendMsg(QString("NICK %1\r\nUSER %2 0 * %3").arg(getNick()).arg(getNick()).arg(getNick())); + break; + case ONLINE : + if(str.contains("PING")) + { + status = ON_CHAN; + emit sendMsg(pong(msg.nick)); + emit sendMsg(join(getChan())); + } + break; + case ON_CHAN : + if(str.contains("PING")) + answer = pong(msg.nick); + return onChanHandler(msg); + break; + } +} + +bool BaseModule::onChanHandler(Message msg) +{ + bool ret = false; + // si la ligne est un message + if(msg.command.compare(QString("PRIVMSG"), Qt::CaseInsensitive) == 0) + { + // mise à jour du bot + if(msg.args.compare("!update") == 0 && msg.src != NULL && msg.src->isOp()) + { + answer = quit("Rebooting for update..."); + ret = true; + } + + // affiche les gens connectés + else if(msg.args.compare("!list") == 0) + { + QString str = "Online users : "; + for(User* u : users) + { + if(u->isOp()) + str.append("@"); + str.append(u->getNick()); + str.append(" "); + } + answer = say(str); + ret = true; + } + } + + // renommage + else if(msg.command.compare("NICK", Qt::CaseInsensitive) == 0) + msg.src->rename(msg.args); + else if(msg.command.compare("QUIT", Qt::CaseInsensitive) == 0) + users.remove(msg.src); + else if(msg.command.compare("PART", Qt::CaseInsensitive) == 0) + users.remove(msg.src); + else if(msg.command.compare("KICK", Qt::CaseInsensitive) == 0) + { + if(getNick().compare(msg.target2) == 0) + { + answer = quit("i've been kicked :("); + ret = true; + } + users.remove(users.getFromNick(msg.target2)); + } + else if(msg.command.compare("JOIN", Qt::CaseInsensitive) == 0 + && msg.args.contains(getChan()) + && getNick().compare(msg.nick) != 0) + { + users.getOrAdd(msg.nick); + answer = whois(msg.nick); + ret = true; + } + + // 353 = code de la ligne qui liste les nicks connectés + // on les parse et on effectue un WHOIS sur chaque nick + else if(msg.command.compare(QString("353"), Qt::CaseInsensitive) == 0) + { + // names + QStringList names = msg.args.split(' '); + for(QString s : names) + { + users.getOrAdd(s); + answer = whois(s); + ret = true; + } + } + + // 319 = code de la ligne de réponse au whois qui indique les chans d'un user, et son statut dessus + else if(msg.command.compare(QString("319"), Qt::CaseInsensitive) == 0) + { + User* u = users.getOrAdd(msg.target2); + QStringList chanList = msg.args.split(' '); + for(QString s : chanList) + { + if(s.endsWith(getChan())) + { + u->setOp(s.startsWith('@')); + break; + } + } + } + return ret; +} + +QString BaseModule::getName() +{ + return "base"; +} diff --git a/basemodule.h b/basemodule.h new file mode 100644 index 0000000..a5057ad --- /dev/null +++ b/basemodule.h @@ -0,0 +1,20 @@ +#ifndef BASEMODULE_H +#define BASEMODULE_H + +#include "module.h" + +class BaseModule : public Module +{ + UserList users; + + enum{OFFLINE, ONLINE, ON_CHAN}; + int status; +public: + BaseModule(); + + bool messageHandler(Message msg); + bool onChanHandler(Message msg); + QString getName(); +}; + +#endif // BASEMODULE_H diff --git a/ircbot.cpp b/ircbot.cpp index 032d0e0..12458df 100644 --- a/ircbot.cpp +++ b/ircbot.cpp @@ -5,142 +5,30 @@ using namespace std; +IRCBot::IRCBot(QString nick_, QString chan_) : nick(nick_), chan(chan_) +{ + addModule(new BaseModule()); +} + void IRCBot::receiveMsg(QString str) { - Message msg = Message(str, &users); + Message msg = Message(str); - switch(status) + for(Module* m : modules) { - case OFFLINE : - status = ONLINE; - emit sendMsg(QString("NICK %1\r\nUSER %2 0 * %3").arg(nick).arg(nick).arg(nick)); - break; - case ONLINE : - if(str.contains("PING")) - { - status = ON_CHAN; - emit sendMsg(pong(msg.nick)); - emit sendMsg(join(chan)); - } - break; - case ON_CHAN : - if(str.contains("PING")) - emit sendMsg(pong(msg.nick)); - handleMessage(msg); - break; + if(m->messageHandler(msg)) + emit sendMsg(m->getAnswer()); } } -void IRCBot::handleMessage(Message msg) +void IRCBot::addModule(Module* module) { - // si la ligne est un message - if(msg.command.compare(QString("PRIVMSG"), Qt::CaseInsensitive) == 0) - { - // mise à jour du bot - if(msg.args.compare("!update") == 0 && msg.src != NULL && msg.src->isOp()) - emit sendMsg(quit("Rebooting for update...")); - - // affiche les gens connectés - if(msg.args.compare("!list") == 0) - { - QString str = "Online users : "; - for(User* u : users) - { - if(u->isOp()) - str.append("@"); - str.append(u->getNick()); - str.append(" "); - } - emit sendMsg(say(str)); - } - } - - // renommage - else if(msg.command.compare("NICK", Qt::CaseInsensitive) == 0) - msg.src->rename(msg.args); - else if(msg.command.compare("QUIT", Qt::CaseInsensitive) == 0) - users.remove(msg.src); - else if(msg.command.compare("PART", Qt::CaseInsensitive) == 0) - users.remove(msg.src); - else if(msg.command.compare("KICK", Qt::CaseInsensitive) == 0) - { - if(nick.compare(msg.target2) == 0) - emit sendMsg(quit("i've been kicked :(")); - users.remove(users.getFromNick(msg.target2)); - } - else if(msg.command.compare("JOIN", Qt::CaseInsensitive) == 0 - && msg.args.contains(chan) - && nick.compare(msg.nick) != 0) - { - users.getOrAdd(msg.nick); - emit sendMsg(whois(msg.nick)); - } - - // 353 = code de la ligne qui liste les nicks connectés - // on les parse et on effectue un WHOIS sur chaque nick - else if(msg.command.compare(QString("353"), Qt::CaseInsensitive) == 0) - { - // names - QStringList names = msg.args.split(' '); - for(QString s : names) - { - users.getOrAdd(s); - emit sendMsg(whois(s)); - } - } - - // 319 = code de la ligne de réponse au whois qui indique les chans d'un user, et son statut dessus - else if(msg.command.compare(QString("319"), Qt::CaseInsensitive) == 0) - { - User* u = users.getOrAdd(msg.target2); - QStringList chanList = msg.args.split(' '); - for(QString s : chanList) - { - if(s.endsWith(chan)) - { - u->setOp(s.startsWith('@')); - break; - } - } - } -} - -QString IRCBot::pong(QString target) -{ - return QString("PONG :%1").arg(target); -} - -QString IRCBot::join(QString theChan) -{ - return QString("JOIN #%1").arg(theChan); -} - -QString IRCBot::whois(QString nick) -{ - return QString("WHOIS %1").arg(nick); -} - -QString IRCBot::say(QString str) -{ - return QString("PRIVMSG #%1 :%2").arg(chan).arg(str); -} - -QString IRCBot::privateSay(QString str, QString target) -{ - return QString("PRIVMSG %1 :%2").arg(target).arg(str); -} - -QString IRCBot::action(QString str) -{ - return QString("PRIVMSG #%1 :\001ACTION %2\001").arg(chan).arg(str); -} - -QString IRCBot::quit(QString str) -{ - return QString("QUIT :%1").arg(str); + modules.push_back(module); + module->setChan(chan); + module->setNick(nick); } void IRCBot::disconnect() { - emit sendMsg(quit("I'll be back")); + emit sendMsg("QUIT :\r\n"); } diff --git a/ircbot.h b/ircbot.h index 59ef5c6..f30b5b7 100644 --- a/ircbot.h +++ b/ircbot.h @@ -4,33 +4,24 @@ #include "user.h" #include "message.h" #include +#include +#include "module.h" +#include "basemodule.h" class IRCBot : public QObject { Q_OBJECT - enum{OFFLINE, ONLINE, ON_CHAN}; - QString nick; QString chan; - int status; - UserList users; + std::vector modules; + BaseModule *base; public: - IRCBot(QString nick_, QString chan_) : nick(nick_), chan(chan_), status(OFFLINE) {} - -private: - void handleMessage(Message msg); + IRCBot(QString nick_, QString chan_); protected: - // IRC commands - QString pong(QString target); - QString join(QString theChan); - QString privateSay(QString str, QString target); - QString whois(QString nick); - QString say(QString str); - QString action(QString str); - QString quit(QString str); + void addModule(Module* module); public slots: void receiveMsg(QString msg); diff --git a/message.cpp b/message.cpp index fd1f4e5..9b2fe3a 100644 --- a/message.cpp +++ b/message.cpp @@ -5,13 +5,12 @@ using namespace std; -Message::Message(QString str, UserList* users) +Message::Message(QString str) { if(str.startsWith("PING")) { command = "PING"; target = "PING"; - src = NULL; nick = str.split(':')[1]; args = nick; } @@ -28,7 +27,6 @@ Message::Message(QString str, UserList* users) // source of the message (creates the user if he is new) QString temp = list.takeFirst(); nick = temp.left(temp.indexOf('!')); - src = users->getFromNick(nick); // command issued by the source command = list.takeFirst(); // target of the command diff --git a/message.h b/message.h index 7d865ff..91705f6 100644 --- a/message.h +++ b/message.h @@ -9,13 +9,12 @@ class Message { public: - User* src; QString nick; QString command; QString target; QString target2; QString args; - Message(QString str, UserList* users); + Message(QString str); ~Message(); }; diff --git a/module.cpp b/module.cpp new file mode 100644 index 0000000..f901cd2 --- /dev/null +++ b/module.cpp @@ -0,0 +1,73 @@ +#include "module.h" + +QString Module::getAnswer() +{ + return answer; +} + +bool Module::isEnabled() +{ + return enabled; +} + +void Module::setEnabled(bool newStatus) +{ + enabled = newStatus; +} + +QString getNick() +{ + return nick; +} + +QString getChan() +{ + return chan; +} + +void setNick(QString nick_) +{ + nick = nick_; +} + +void setChan(QString chan_) +{ + chan = chan_; +} + +// IRC COMMANDS + +QString Module::pong(QString target) +{ + return QString("PONG :%1\r\n").arg(target); +} + +QString Module::join(QString theChan) +{ + return QString("JOIN #%1\r\n").arg(theChan); +} + +QString Module::whois(QString nick) +{ + return QString("WHOIS %1\r\n").arg(nick); +} + +QString Module::say(QString str) +{ + return QString("PRIVMSG #%1 :%2\r\n").arg(chan).arg(str); +} + +QString Module::privateSay(QString str, QString target) +{ + return QString("PRIVMSG %1 :%2\r\n").arg(target).arg(str); +} + +QString Module::action(QString str) +{ + return QString("PRIVMSG #%1 :\001ACTION %2\001\r\n").arg(chan).arg(str); +} + +QString Module::quit(QString str) +{ + return QString("QUIT :%1\r\n").arg(str); +} diff --git a/module.h b/module.h new file mode 100644 index 0000000..a29d23e --- /dev/null +++ b/module.h @@ -0,0 +1,42 @@ +#ifndef MODULE_H +#define MODULE_H + +#include + +class Message; + +class Module +{ +private: + bool enabled; + QString nick; + QString chan; + +protected: + QString answer; + + QString pong(QString target); + QString join(QString theChan); + QString privateSay(QString str, QString target); + QString whois(QString nick); + QString say(QString str); + QString action(QString str); + QString quit(QString str); + +public: + Module() : enabled(true) {} + + virtual bool messageHandler(Message msg); + virtual QString getName(); + + QString getAnswer(); + bool isEnabled(); + void setEnabled(bool newStatus); + QString getNick(); + QString getChan(); + void setNick(QString nick_); + void setChan(QString chan_); + // TODO: add serialization methods +}; + +#endif // MODULE_H diff --git a/socketirc.cpp b/socketirc.cpp index bfcbddf..c75c439 100644 --- a/socketirc.cpp +++ b/socketirc.cpp @@ -15,7 +15,6 @@ SocketIRC::SocketIRC(QString server_, int port_) : server(server_), port(port_), void SocketIRC::sendMsg(QString msg) { - msg.append("\r\n"); sock.write(msg.toStdString().c_str()); sock.flush(); } diff --git a/ui_mainwindow.h b/ui_mainwindow.h deleted file mode 100644 index c283a1c..0000000 --- a/ui_mainwindow.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************** -** Form generated from reading UI file 'mainwindow.ui' -** -** Created by: Qt User Interface Compiler version 5.4.1 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ - -#ifndef UI_MAINWINDOW_H -#define UI_MAINWINDOW_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "prompt.h" - -QT_BEGIN_NAMESPACE - -class Ui_MainWindow -{ -public: - QWidget *centralWidget; - QGridLayout *gridLayout; - QTextBrowser *monitoringConsole; - Prompt *prompt; - - void setupUi(QMainWindow *MainWindow) - { - if (MainWindow->objectName().isEmpty()) - MainWindow->setObjectName(QStringLiteral("MainWindow")); - MainWindow->resize(374, 404); - centralWidget = new QWidget(MainWindow); - centralWidget->setObjectName(QStringLiteral("centralWidget")); - gridLayout = new QGridLayout(centralWidget); - gridLayout->setSpacing(6); - gridLayout->setContentsMargins(11, 11, 11, 11); - gridLayout->setObjectName(QStringLiteral("gridLayout")); - monitoringConsole = new QTextBrowser(centralWidget); - monitoringConsole->setObjectName(QStringLiteral("monitoringConsole")); - - gridLayout->addWidget(monitoringConsole, 1, 0, 1, 2); - - prompt = new Prompt(centralWidget); - prompt->setObjectName(QStringLiteral("prompt")); - - gridLayout->addWidget(prompt, 0, 0, 1, 2); - - MainWindow->setCentralWidget(centralWidget); - - retranslateUi(MainWindow); - - QMetaObject::connectSlotsByName(MainWindow); - } // setupUi - - void retranslateUi(QMainWindow *MainWindow) - { - MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0)); - } // retranslateUi - -}; - -namespace Ui { - class MainWindow: public Ui_MainWindow {}; -} // namespace Ui - -QT_END_NAMESPACE - -#endif // UI_MAINWINDOW_H