diff --git a/Makefile b/Makefile index 66f2804..914c321 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,8 @@ SRCS := $(SRCS_DIR)/main.cpp \ OBJ = $(SRCS:$(SRCS_DIR)/%.cpp=$(OBJ_DIR)/%.o) BONUS_SRCS := $(SRCS_DIR)/bot/BotMessageBuffer.cpp \ - $(SRCS_DIR)/bot/BotClient.cpp + $(SRCS_DIR)/bot/BotClient.cpp \ + $(SRCS_DIR)/bot/SixSevenBot.cpp OBJS := $(SRCS:$(SRCS_DIR)/%.cpp=$(OBJ_DIR)/%.o) OBJS_BONUS := $(SRCS:$(SRCS_DIR)/%.cpp=$(OBJ_DIR)/bonus/%.o) \ diff --git a/incs/bot/BotClient.hpp b/incs/bot/BotClient.hpp index 44bdf88..150d89b 100644 --- a/incs/bot/BotClient.hpp +++ b/incs/bot/BotClient.hpp @@ -1,5 +1,6 @@ #pragma once +#include "IChannel.hpp" #include "IClient.hpp" #include "IServer.hpp" #include "IChannel.hpp" @@ -9,14 +10,14 @@ class IBot; class BotClient : public IClient { private: - static int s_nextBotId; // Starts at -1, decrements - int m_id; // Negative FD - std::string m_nickname; - std::string m_username; - std::string m_realname; + static int s_nextBotId; // Starts at -1, decrements + int m_id; // Negative FD + std::string m_nickname; + std::string m_username; + std::string m_realname; std::string m_hostname; - IServer& m_server; - std::set m_channels; + IServer& m_server; + std::set< IChannel* > m_channels; BotMessageBuffer m_buffer; bool _passwordProvided; @@ -24,32 +25,32 @@ class BotClient : public IClient std::time_t m_lastPingSent; public: - BotClient(const std::string& nick, IServer& server); + BotClient(const std::string& nick, IServer& server); ~BotClient(); - int getFd() const; // Returns negative m_id + int getFd() const; // Returns negative m_id const std::string& getNickname() const; const std::string& getUsername() const; const std::string& getRealname() const; - const std::string& getHostname() const; // Returns "internal" + const std::string& getHostname() const; // Returns "internal" IServer* getServer() const; - std::string getPrefix() const; // "nick!bot@internal" + std::string getPrefix() const; // "nick!bot@internal" - bool isRegistered() const; // Always returns true - bool isPasswordProvided() const; // Always returns true + bool isRegistered() const; // Always returns true + bool isPasswordProvided() const; // Always returns true void setNickname(const std::string& nick); void setUsername(const std::string& user); void setRealname(const std::string& real); void setPasswordProvided(bool provided); void attemptRegistration(); - + void joinChannel(IChannel* channel); void leaveChannel(IChannel* channel); bool isInChannel(const std::string& channel) const; const std::set< IChannel* >& getChannels() const; // Buffer access - + std::time_t getLastActivity() const; void updateLastActivity(); std::time_t getLastPingSent() const; @@ -57,6 +58,5 @@ class BotClient : public IClient IMessageBuffer& getBuffer(); const IMessageBuffer& getBuffer() const; - void setBot(IBot* bot); // Links to bot handler - + void setBot(IBot* bot); // Links to bot handler }; diff --git a/incs/bot/BotMessageBuffer.hpp b/incs/bot/BotMessageBuffer.hpp index 0a587db..dc86085 100644 --- a/incs/bot/BotMessageBuffer.hpp +++ b/incs/bot/BotMessageBuffer.hpp @@ -6,6 +6,7 @@ #include "core/IMessageBuffer.hpp" #include "core/IServer.hpp" #include "bot/IBot.hpp" +#include "protocol/Message.hpp" class BotMessageBuffer : public IMessageBuffer @@ -17,12 +18,7 @@ class BotMessageBuffer : public IMessageBuffer std::string m_writeBuffer; void processIncomingMessage(const std::string& raw); - void parseAndDispatch(const std::string& prefix, - const std::string& command, - const std::vector& params); - - void setBot(IBot* bot); - void setBotClient(IClient* client); + void parseAndDispatch(const Message &message); public: BotMessageBuffer(IServer& server); @@ -38,4 +34,5 @@ class BotMessageBuffer : public IMessageBuffer const std::string& getWriteBuffer() const; void clearWriteBuffer(); + void setBot(IBot* bot); }; diff --git a/incs/bot/SixSevenBot.hpp b/incs/bot/SixSevenBot.hpp new file mode 100644 index 0000000..fc30543 --- /dev/null +++ b/incs/bot/SixSevenBot.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "IChannel.hpp" +#include "IClient.hpp" +#include "IServer.hpp" +#include "bot/BotClient.hpp" +#include "bot/IBot.hpp" + +class SixSevenBot : public IBot +{ +private: + IServer& m_server; + BotClient* m_client; + + void sendToChannel(IChannel* channel, const std::string& message); + +public: + SixSevenBot(IServer& server, const std::string& nick = "The67Kid"); + ~SixSevenBot(); + + void onPrivateMessage(IClient* sender, const std::string& message); + void onChannelMessage(IClient* sender, IChannel* channel, const std::string& message); + + IClient* getClient(); + + void joinChannel(const std::string& channelName); +}; diff --git a/srcs/bot/BotClient.cpp b/srcs/bot/BotClient.cpp index 2b80766..44d6c88 100644 --- a/srcs/bot/BotClient.cpp +++ b/srcs/bot/BotClient.cpp @@ -90,7 +90,8 @@ void BotClient::leaveChannel(IChannel* channel) bool BotClient::isInChannel(const std::string& channelName) const { - for (std::set< IChannel* >::const_iterator it = m_channels.begin(); it != m_channels.end(); ++it) + for (std::set< IChannel* >::const_iterator it = m_channels.begin(); it != m_channels.end(); + ++it) { if ((*it)->getName() == channelName) return true; @@ -158,5 +159,5 @@ std::string BotClient::getPrefix() const void BotClient::setBot(IBot* bot) { - (void) bot; + (void)bot; } diff --git a/srcs/bot/BotMessageBuffer.cpp b/srcs/bot/BotMessageBuffer.cpp index ec51fcf..b5917f3 100644 --- a/srcs/bot/BotMessageBuffer.cpp +++ b/srcs/bot/BotMessageBuffer.cpp @@ -1,6 +1,11 @@ #include "bot/BotMessageBuffer.hpp" +#include "CommandType.hpp" +#include "IClient.hpp" +#include "Logger.hpp" +#include "protocol/Message.hpp" +#include "protocol/MessageParser.hpp" -BotMessageBuffer::BotMessageBuffer(IServer& server) : m_server(server), m_readBuffer(), m_writeBuffer() +BotMessageBuffer::BotMessageBuffer(IServer& server) : m_server(server), m_bot(NULL) { } @@ -44,6 +49,7 @@ size_t BotMessageBuffer::getReadBufferSize() const void BotMessageBuffer::appendWrite(const std::string& data) { m_writeBuffer += data; + processIncomingMessage(data); } const std::string& BotMessageBuffer::getWriteBuffer() const @@ -64,16 +70,21 @@ void BotMessageBuffer::clearWriteBuffer() m_writeBuffer.clear(); } +void BotMessageBuffer::setBot(IBot *bot) +{ + m_bot = bot; +} -void BotMessageBuffer::parseAndDispatch(const std::string& prefix, const std::string& command, const std::vector& params) +void BotMessageBuffer::parseAndDispatch(const Message &message) { - if (command != "PRIVMSG" || params.size() < 2) + + if (message.m_command_type != irc::PRIVMSG) return; - std::string target = params[0]; - std::string text = params[1]; + std::string target = message.m_params[0]; + std::string text = message.m_params[1]; + std::string senderNick = message.m_prefix.substr(0, message.m_prefix.find('!')); - std::string senderNick = prefix.substr(0, prefix.find('!')); IClient* sender = m_server.getClientByNickname(senderNick); if (!sender) return; @@ -92,29 +103,11 @@ void BotMessageBuffer::parseAndDispatch(const std::string& prefix, const std::st void BotMessageBuffer::processIncomingMessage(const std::string& raw) { - std::string line = raw; - if (line.size() >= 2 && line.substr(line.size()-2) == "\r\n") - line = line.substr(0, line.size()-2); - //\r\n removed - - std::string prefix; - std::string command; - std::vector params; - - size_t pos = 0; - if (line[0] == ':') - { - pos = line.find(' '); - prefix = line.substr(1, pos - 1); - pos++; - } - //we've got the prefix - - size_t nextSpace = line.find(' ', pos); - command = line.substr(pos, nextSpace - pos); - //we've got the command + Message receivedMsg = MessageParser::parse(raw); + if (!receivedMsg.isValid()) + return ; - parseAndDispatch(prefix, command, params); + parseAndDispatch(receivedMsg); } -//:prefix COMMAND param1 param2 :trailing parameter with spaces \ No newline at end of file +//:prefix COMMAND param1 param2 :trailing parameter with spaces diff --git a/srcs/bot/SixSevenBot.cpp b/srcs/bot/SixSevenBot.cpp new file mode 100644 index 0000000..19dcedc --- /dev/null +++ b/srcs/bot/SixSevenBot.cpp @@ -0,0 +1,70 @@ +#include "bot/SixSevenBot.hpp" +#include "CommandType.hpp" +#include "Logger.hpp" +#include "bot/BotClient.hpp" +#include "bot/BotMessageBuffer.hpp" +#include "protocol/Message.hpp" +#include "protocol/MessageParser.hpp" + +SixSevenBot::SixSevenBot(IServer& server, const std::string& nick) : m_server(server) +{ + m_client = new BotClient(nick, server); + m_client->setBot(this); + BotMessageBuffer *bmb = dynamic_cast(&m_client->getBuffer()); + bmb->setBot(this); +} + +SixSevenBot::~SixSevenBot() +{ + delete m_client; +} + +void SixSevenBot::onChannelMessage(IClient* sender, IChannel* channel, const std::string& message) +{ + if (sender == m_client) + return; + + bool hasSix = message.find('6') != std::string::npos; + bool hasSeven = message.find('7') != std::string::npos; + bool isValidSixSeven = (hasSix && hasSeven) && message.find('6') < message.find('7'); + + if (isValidSixSeven) + sendToChannel(channel, "DID SOMEONE SAY... SIX SEVENNNNNNNN????"); +} + +void SixSevenBot::onPrivateMessage(IClient* sender, const std::string& message) +{ + if (sender == m_client) + return; + (void)message; +} + +void SixSevenBot::joinChannel(const std::string& channelName) +{ + IChannel* channel = m_server.getChannel(channelName); + if (!channel) + channel = m_server.createChannel(channelName, m_client); + if (!channel->hasMember(m_client)) + { + channel->addMember(m_client); + m_client->joinChannel(channel); + } +} + +void SixSevenBot::sendToChannel(IChannel* channel, const std::string& message) +{ + Message msg; + msg.m_prefix = m_client->getPrefix(); + msg.m_command = "PRIVMSG"; + msg.m_command_type = irc::PRIVMSG; + msg.m_params.push_back(channel->getName()); + msg.m_params.push_back(message); + + std::string serialized = MessageParser::serialize(msg); + channel->broadcast(serialized, m_client); +} + +IClient* SixSevenBot::getClient() +{ + return (m_client); +} diff --git a/srcs/core/Server.cpp b/srcs/core/Server.cpp index 916b610..2aae568 100644 --- a/srcs/core/Server.cpp +++ b/srcs/core/Server.cpp @@ -498,6 +498,9 @@ Server::~Server() delete it->second; m_channels.clear(); + for (std::vector ::iterator it = m_bots.begin(); it != m_bots.end(); it++) + delete *it; + if (m_listenFd != -1) close(m_listenFd); diff --git a/srcs/main.cpp b/srcs/main.cpp index 1abecd5..6d37ca6 100644 --- a/srcs/main.cpp +++ b/srcs/main.cpp @@ -1,4 +1,5 @@ #include "Logger.hpp" +#include "bot/SixSevenBot.hpp" #include "core/Server.hpp" #include #include @@ -26,6 +27,12 @@ int main(int argc, char** argv) { Config cfg = Config::checkArgs(argc, argv); Server srv(cfg); + + #ifdef BONUS + SixSevenBot *sixSevenBot = new SixSevenBot(srv); + srv.registerBot(sixSevenBot); + sixSevenBot->joinChannel("#eighty-nine"); + #endif srv.run(); return (0); }