From a57ababfece7c1e1b1fb12014d25c82c5a17ba66 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 May 2015 15:26:18 +0200 Subject: [PATCH] initial commit --- SparrowBot.pro | 28 +++++++++++++++ main.cpp | 45 ++++++++++++++++++++++++ mainwindow.cpp | 34 ++++++++++++++++++ mainwindow.h | 30 ++++++++++++++++ mainwindow.ui | 66 +++++++++++++++++++++++++++++++++++ message.cpp | 40 +++++++++++++++++++++ message.h | 18 ++++++++++ prompt.cpp | 8 +++++ prompt.h | 19 ++++++++++ socketirc.cpp | 61 ++++++++++++++++++++++++++++++++ socketirc.h | 37 ++++++++++++++++++++ sparrowbot.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ sparrowbot.h | 39 +++++++++++++++++++++ user.cpp | 15 ++++++++ user.h | 16 +++++++++ 15 files changed, 551 insertions(+) create mode 100644 SparrowBot.pro create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 message.cpp create mode 100644 message.h create mode 100644 prompt.cpp create mode 100644 prompt.h create mode 100644 socketirc.cpp create mode 100644 socketirc.h create mode 100644 sparrowbot.cpp create mode 100644 sparrowbot.h create mode 100644 user.cpp create mode 100644 user.h diff --git a/SparrowBot.pro b/SparrowBot.pro new file mode 100644 index 0000000..fa18909 --- /dev/null +++ b/SparrowBot.pro @@ -0,0 +1,28 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2015-05-13T11:07:00 +# +#------------------------------------------------- + +QT += core gui network widgets + +TARGET = SparrowBot +TEMPLATE = app +CONFIG += c++11 + +SOURCES += main.cpp\ + mainwindow.cpp \ + sparrowbot.cpp \ + socketirc.cpp \ + message.cpp \ + user.cpp \ + prompt.cpp + +HEADERS += mainwindow.h \ + sparrowbot.h \ + socketirc.h \ + message.h \ + user.h \ + prompt.h + +FORMS += mainwindow.ui diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..90f42fc --- /dev/null +++ b/main.cpp @@ -0,0 +1,45 @@ +#include "mainwindow.h" +#include "socketirc.h" +#include "sparrowbot.h" +#include + +int main(int argc, char *argv[]) +{ + // set up the socket + SocketIRC sock; + sock.setServer("irc.freenode.net"); + sock.setPort(6667); + + // set up the bot + SparrowBot* bot = new SparrowBot("SparrowBot", "#epicsparrow"); + QObject::connect(&sock, SIGNAL(receivedMsg(QString)), bot, SLOT(receiveMsg(QString))); + QObject::connect(bot, SIGNAL(sendMsg(QString)), &sock, SLOT(sendMsg(QString))); + QObject::connect(bot, SIGNAL(changeSocketStatus(int)), &sock, SLOT(setConnected(int))); + + // set up Qt + QApplication a(argc, argv); + bool nogui = a.arguments().contains("-nogui"); + MainWindow w; + + // set up UI + if(!nogui) + { + // bind signals to slots + QObject::connect(&sock, SIGNAL(receivedMsg(QString)), w.getConsole(), SLOT(append(QString))); + QObject::connect(&sock, SIGNAL(stateChanged(int)), w.getLed(), SLOT(setValue(int))); + QObject::connect(&sock, SIGNAL(stateChanged(int)), w.getSwitch(), SLOT(setValue(int))); + + QObject::connect(w.getPrompt(), SIGNAL(sendMsg(QString)), &sock, SLOT(sendMsg(QString))); + QObject::connect(w.getPrompt(), SIGNAL(returnPressed()), w.getPrompt(), SLOT(confirmationPerformed())); + + QObject::connect(w.getSwitch(), SIGNAL(valueChanged(int)), bot, SLOT(forceStatus(int))); + + // show window + w.show(); + } + + // run event loop on the main thread + if(nogui) + bot->forceStatus(1); + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..399f54e --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,34 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); +} + +QTextBrowser* MainWindow::getConsole() +{ + return this->ui->monitoringConsole; +} + +QSlider* MainWindow::getSwitch() +{ + return this->ui->connectSwitch; +} + +QProgressBar* MainWindow::getLed() +{ + return this->ui->statusLed; +} + +Prompt* MainWindow::getPrompt() +{ + return this->ui->prompt; +} + +MainWindow::~MainWindow() +{ + delete ui; +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..b518d61 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,30 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "prompt.h" +#include +#include +#include +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + + QTextBrowser* getConsole(); + QSlider* getSwitch(); + QProgressBar* getLed(); + Prompt* getPrompt(); +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..2cd4ba3 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,66 @@ + + + MainWindow + + + + 0 + 0 + 374 + 404 + + + + MainWindow + + + + + + + 1 + + + 1 + + + Qt::Horizontal + + + + + + + 1 + + + 0 + + + false + + + false + + + + + + + + + + + + + + + + Prompt + QLineEdit +
prompt.h
+
+
+ + +
diff --git a/message.cpp b/message.cpp new file mode 100644 index 0000000..773c08a --- /dev/null +++ b/message.cpp @@ -0,0 +1,40 @@ +#include "message.h" + +#include +#include + +using namespace std; + +Message::Message(QString str) +{ + if(str.startsWith("PING")) + { + command = "PING"; + target = "PING"; + src = str.right(str.size()-(str.indexOf(':')+1)); + args = str; + } + else + { + // remove the first char, which is ':' + str = str.remove(0, 1); + // locate the mid ':' separator + int mid = str.indexOf(':'); + // the arguments are after the separator + args = str.right(str.size()-(mid+1)); + // the interesting infos before the separator are separated by spaces + QStringList list = str.split(' '); + // source of the message + src = list.takeFirst(); + // command issued by the source + command = list.takeFirst(); + // target of the command + target = list.takeFirst(); + } +} + +Message::~Message() +{ + +} + diff --git a/message.h b/message.h new file mode 100644 index 0000000..032e5ca --- /dev/null +++ b/message.h @@ -0,0 +1,18 @@ +#ifndef MESSAGE_H +#define MESSAGE_H + +#include +#include + +class Message +{ +public: + QString src; + QString command; + QString target; + QString args; + Message(QString str); + ~Message(); +}; + +#endif // MESSAGE_H diff --git a/prompt.cpp b/prompt.cpp new file mode 100644 index 0000000..b3f8757 --- /dev/null +++ b/prompt.cpp @@ -0,0 +1,8 @@ +#include "prompt.h" + +void Prompt::confirmationPerformed() +{ + QString str = text(); + clear(); + emit sendMsg(str.append("\r\n")); +} diff --git a/prompt.h b/prompt.h new file mode 100644 index 0000000..c2671bd --- /dev/null +++ b/prompt.h @@ -0,0 +1,19 @@ +#ifndef PROMPT_H +#define PROMPT_H + +#include + +class Prompt : public QLineEdit +{ + Q_OBJECT +public: + Prompt(QWidget*& w) : QLineEdit(w) {} + +public slots: + void confirmationPerformed(); + +signals: + void sendMsg(QString); +}; + +#endif // PROMPT_H diff --git a/socketirc.cpp b/socketirc.cpp new file mode 100644 index 0000000..12d740c --- /dev/null +++ b/socketirc.cpp @@ -0,0 +1,61 @@ +#include "socketirc.h" +#include + +SocketIRC::SocketIRC() : server("irc.freenode.net"), port(6667), isConnected(false) +{ + connect(&sock, SIGNAL(readyRead()), this, SLOT(readMsg())); +} + +void SocketIRC::setServer(std::string server_) +{ + server = server_; +} + +void SocketIRC::setPort(int port_) +{ + port = port_; +} + +void SocketIRC::sendMsg(QString msg) +{ + if(isConnected) + { + sock.write(msg.toStdString().c_str()); + sock.flush(); + std::cout << msg.toStdString(); + } +} + +void SocketIRC::setConnected(int c) +{ + if(c != isConnected) + { + if(isConnected) + { + sock.close(); + isConnected = false; + emit stateChanged(isConnected); + } + else + { + sock.connectToHost(QString(server.c_str()), quint16(port)); + if(sock.waitForConnected(5000)) + isConnected = true; + else + std::cerr << "failed to connect : " << sock.errorString().toStdString() << std::endl; + emit stateChanged(isConnected); + } + } +} + +void SocketIRC::readMsg() +{ + char buffer[512]; + while(sock.canReadLine()) + { + int numbytes = sock.readLine(buffer, 512); + buffer[numbytes - 2] = '\0'; + std::cout << buffer << std::endl; + emit receivedMsg(QString(buffer)); + } +} diff --git a/socketirc.h b/socketirc.h new file mode 100644 index 0000000..31803ea --- /dev/null +++ b/socketirc.h @@ -0,0 +1,37 @@ +#ifndef SOCKETIRC_H +#define SOCKETIRC_H + +#include +#include +#include + +class SocketIRC : public QObject +{ + Q_OBJECT + +public: + + SocketIRC(); + void setServer(std::string server_); + void setPort(int port_); + +private: + + std::string server; + int port; + QTcpSocket sock; + bool isConnected; + +private slots: + void readMsg(); + +public slots: + void sendMsg(QString msg); + void setConnected(int c); + +signals: + void receivedMsg(QString msg); + void stateChanged(int newState); +}; + +#endif // SOCKETIRC_H diff --git a/sparrowbot.cpp b/sparrowbot.cpp new file mode 100644 index 0000000..85064b4 --- /dev/null +++ b/sparrowbot.cpp @@ -0,0 +1,95 @@ +#include "sparrowbot.h" +#include +#include +#include + +using namespace std; + +void SparrowBot::receiveMsg(QString msg) +{ + string str; + if(msg.contains("PING")) + { + str = "PONG\r\n"; + emit sendMsg(QString(str.c_str())); + } + switch(status) + { + case OFFLINE : + status = ONLINE; + sendRawMessage("NICK " + nick + "\r\nUSER " + nick + " 0 * " + nick + "\r\n"); + break; + case ONLINE : + status = ON_CHAN; + sendRawMessage("JOIN #" + chan + "\r\n"); + break; + case ON_CHAN : + handleMessage(Message(msg)); + break; + } +} + +void SparrowBot::forceStatus(int newStatus) +{ + emit changeSocketStatus(newStatus); + if(newStatus) + { + //status = ONLINE; + //sendRawMessage("NICK " + nick + "\r\nUSER " + nick + " 0 * " + nick + "\r\n"); + } + else + { + status = OFFLINE; + } +} + +void SparrowBot::handleMessage(Message msg) +{ + //char* str = msg.args.toStdString().c_str(); + if(msg.command.compare(QString("PRIVMSG"), Qt::CaseInsensitive) == 0) + { + // message + + + if(msg.args.compare("!destroy") == 0) + { + sendRawMessage("QUIT :i'll be back\r\n"); + status = OFFLINE; + emit changeSocketStatus(false); + } + if(msg.args.compare("!list") == 0) + { + string str = "Online users : "; + for(User u : users) + str += u.getNick().toStdString() + " "; + say(str); + } + } + + if(msg.command.compare(QString("353"), Qt::CaseInsensitive) == 0) + { + // names + QStringList names = msg.args.split(' '); + for(QString s : names) + { + User u = User(s); + users.push_back(u); + sendRawMessage("WHOIS "+u.getNick().toStdString()+"\r\n"); + } + } +} + +void SparrowBot::say(string str) +{ + sendRawMessage("PRIVMSG #" + chan + " :" + str + "\r\n"); +} + +void SparrowBot::action(string str) +{ + sendRawMessage("PRIVMSG #" + chan + " :ACTION " + str + "\r\n"); +} + +void SparrowBot::sendRawMessage(string str) +{ + emit sendMsg(QString(str.c_str())); +} diff --git a/sparrowbot.h b/sparrowbot.h new file mode 100644 index 0000000..dfe37f7 --- /dev/null +++ b/sparrowbot.h @@ -0,0 +1,39 @@ +#ifndef SPARROWBOT_H +#define SPARROWBOT_H + +#include "user.h" +#include "message.h" +#include +#include + +class SparrowBot : public QObject +{ + Q_OBJECT + + enum{OFFLINE, ONLINE, ON_CHAN}; + + std::string nick; + std::string chan; + int status; + + std::vector users; +public: + SparrowBot() : nick("SparrowBot"), chan("epicsparrow"), status(OFFLINE) {} + SparrowBot(std::string nick_, std::string chan_) : nick(nick_), chan(chan_), status(OFFLINE) {} + +private: + void handleMessage(Message msg); + void say(std::string str); + void action(std::string str); + void sendRawMessage(std::string str); + +public slots: + void receiveMsg(QString msg); + void forceStatus(int newStatus); + +signals: + void sendMsg(QString msg); + void changeSocketStatus(int newStatus); +}; + +#endif // SPARROWBOT_H diff --git a/user.cpp b/user.cpp new file mode 100644 index 0000000..a2b51f2 --- /dev/null +++ b/user.cpp @@ -0,0 +1,15 @@ +#include "user.h" + +User::User(QString str) +{ + isOp = (str.at(0) == '@'); + if(isOp) + str = str.remove(0, 1); + nick = str; +} + +QString User::getNick() +{ + return nick; +} + diff --git a/user.h b/user.h new file mode 100644 index 0000000..ef6f981 --- /dev/null +++ b/user.h @@ -0,0 +1,16 @@ +#ifndef USER_H +#define USER_H + +#include + +class User +{ + QString nick; + bool isOp; + +public: + User(QString str); + QString getNick(); +}; + +#endif // USER_H