From 4f8d1f3d1fabf2a18b31d7c07b066696adab87c7 Mon Sep 17 00:00:00 2001 From: Ladebeze66 Date: Thu, 30 May 2024 18:50:56 +0200 Subject: [PATCH] modif3005soir --- ft_irc3/includes/AdditionalCommands.hpp | 3 +- ft_irc3/includes/Channel.hpp | 8 +- ft_irc3/includes/InviteHandler.hpp | 5 +- ft_irc3/includes/Join.hpp | 3 +- ft_irc3/includes/ModeHandler.hpp | 5 +- ft_irc3/includes/RPL.hpp | 176 ++++++++-------- ft_irc3/includes/Server.hpp | 6 +- ft_irc3/includes/TopicHandler.hpp | 38 ++++ ft_irc3/includes/Welcome.hpp | 3 +- ft_irc3/src/AdditionalCommands.cpp | 25 ++- ft_irc3/src/Channel.cpp | 14 +- ft_irc3/src/CommandHandler.cpp | 10 +- ft_irc3/src/InviteHandler.cpp | 10 +- ft_irc3/src/Join.cpp | 3 +- ft_irc3/src/ModeHandler.cpp | 261 ++++++++++++++---------- ft_irc3/src/Server.cpp | 10 +- ft_irc3/src/TopicHandler.cpp | 84 ++++++++ ft_irc3/src/Welcome.cpp | 4 +- ft_irc3/src/Who.cpp | 12 +- 19 files changed, 436 insertions(+), 244 deletions(-) create mode 100644 ft_irc3/includes/TopicHandler.hpp create mode 100644 ft_irc3/src/TopicHandler.cpp diff --git a/ft_irc3/includes/AdditionalCommands.hpp b/ft_irc3/includes/AdditionalCommands.hpp index a442f2a..fa7e206 100644 --- a/ft_irc3/includes/AdditionalCommands.hpp +++ b/ft_irc3/includes/AdditionalCommands.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/21 18:09:05 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:10:51 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:10:18 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,6 +21,7 @@ #include "RPL.hpp" #include "Who.hpp" #include "InviteHandler.hpp" +#include "TopicHandler.hpp" #include #include diff --git a/ft_irc3/includes/Channel.hpp b/ft_irc3/includes/Channel.hpp index 275c8f3..0586c72 100644 --- a/ft_irc3/includes/Channel.hpp +++ b/ft_irc3/includes/Channel.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:41:35 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:09:11 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 18:32:18 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -39,6 +39,7 @@ public: const std::vector &getClients() const; void addOperator(Client *client); bool isOperator(Client *client) const; + void removeOperator(Client *client); // Ajouté bool hasClient(Client *client) const; void broadcast(const std::string &message, Client *_client, Server *_server); @@ -59,8 +60,10 @@ public: void setKey(const std::string &key); // Ajouté void setTopicProtection(bool protection); // Ajouté std::string getModes() const; // Ajouté + bool getTopicProtection() const; void addInvitedClient(Client* client); + private: std::string _name; std::vector _clients; @@ -74,7 +77,8 @@ private: size_t _clientLimit; bool _inviteOnly; bool _topicProtection; // Ajouté + + }; #endif // CHANNEL_HPP - diff --git a/ft_irc3/includes/InviteHandler.hpp b/ft_irc3/includes/InviteHandler.hpp index 3d97043..f1907d3 100644 --- a/ft_irc3/includes/InviteHandler.hpp +++ b/ft_irc3/includes/InviteHandler.hpp @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* InviteHanndler.hpp :+: :+: :+: */ +/* InviteHandler.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 13:01:50 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:03:04 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:48:41 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,6 +21,7 @@ #include "Client.hpp" #include "Channel.hpp" #include "RPL.hpp" +#include "Utils.hpp" class Server; class Client; diff --git a/ft_irc3/includes/Join.hpp b/ft_irc3/includes/Join.hpp index 49204ab..1a9ed96 100644 --- a/ft_irc3/includes/Join.hpp +++ b/ft_irc3/includes/Join.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/21 19:51:08 by fgras-ca #+# #+# */ -/* Updated: 2024/05/28 14:17:52 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:48:55 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,6 +18,7 @@ #include "Server.hpp" #include "Channel.hpp" #include "RPL.hpp" +#include "Utils.hpp" class JoinHandler { diff --git a/ft_irc3/includes/ModeHandler.hpp b/ft_irc3/includes/ModeHandler.hpp index 9d4e5f5..16655cd 100644 --- a/ft_irc3/includes/ModeHandler.hpp +++ b/ft_irc3/includes/ModeHandler.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 11:12:57 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 12:50:39 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 18:40:48 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,12 +41,13 @@ private: void handleUserMode(Client* client, const std::vector& tokens); void handleChannelMode(Client* client, const std::vector& tokens); - void setChannelMode(Channel* channel, const std::string& mode, bool adding, const std::string& argument); + void setChannelMode(Client *client, Channel* channel, const std::string& mode, bool adding, const std::string& argument); //void applyModeB(Channel* channel, bool adding, const std::string& argument); void applyModeL(Channel* channel, bool adding, const std::string& argument); void applyModeI(Channel* channel, bool adding); void applyModeK(Channel* channel, bool adding, const std::string& argument); void applyModeT(Channel* channel, bool adding); + void applyModeO(Client *client, Channel* channel, bool adding, const std::string& argument); }; #endif // MODEHANDLER_HPP diff --git a/ft_irc3/includes/RPL.hpp b/ft_irc3/includes/RPL.hpp index 186f608..3bad940 100644 --- a/ft_irc3/includes/RPL.hpp +++ b/ft_irc3/includes/RPL.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/19 15:12:47 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:27:52 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:49:15 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,11 +16,12 @@ #include #include #include "Client.hpp" +#include "Utils.hpp" #define SERVER_NAME "IRC_Server" #define SERVER_VERSION "1.0" -#define USER_MODES "+o" -#define CHANNEL_MODES "i/t/k/o/l" +#define USER_MODES "+o/-o" +#define CHANNEL_MODES "none" #define CHANNEL_MODES_WITH_PARAMS "None" @@ -43,21 +44,21 @@ inline std::string RPL_WELCOME(Client* client) { inline std::string RPL_YOURHOST(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 002 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 002 " << CLIENT_NICK(client) << " :Your host is " << SERVER_NAME << ", running version " << SERVER_VERSION << "\r\n"; return oss.str(); } inline std::string RPL_CREATED(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 003 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 003 " << CLIENT_NICK(client) << " :This server was created " << __DATE__ << "\r\n"; return oss.str(); } inline std::string RPL_MYINFO(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 004 " << CLIENT_FD(client) << " " + oss << ":" << SERVER_NAME << " 004 " << CLIENT_NICK(client) << " " << SERVER_NAME << " " << SERVER_VERSION << " " << USER_MODES << " " << CHANNEL_MODES << " " << CHANNEL_MODES_WITH_PARAMS << "\r\n"; @@ -66,111 +67,110 @@ inline std::string RPL_MYINFO(Client* client) { inline std::string RPL_ISUPPORT(Client* client, const std::string& tokens) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 005 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 005 " << CLIENT_NICK(client) << " " << tokens << " :are supported by this server\r\n"; return oss.str(); } -inline std::string RPL_UMODEIS(int clientFd, const std::string& modes) { +inline std::string RPL_UMODEIS(Client* client, const std::string& modes) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 221 " << clientFd << " :" << modes << "\r\n"; + oss << ":" << SERVER_NAME << " 221 " << CLIENT_NICK(client) << " :" << modes << "\r\n"; return oss.str(); } -inline std::string RPL_AWAY(int clientFd, const std::string& target, const std::string& message) { +inline std::string RPL_AWAY(Client *client, const std::string& target, const std::string& message) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 301 " << clientFd << " " << target << " :" << message << "\r\n"; + oss << ":" << SERVER_NAME << " 301 " << CLIENT_NICK(client) << " " << target << " :" << message << "\r\n"; return oss.str(); } // WHOIS Command RPLs -inline std::string RPL_WHOISUSER(int clientFd, Client* target) +inline std::string RPL_WHOISUSER(Client *client, Client* target) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 311 " << clientFd << " " << CLIENT_NICK(target) << " " + oss << ":" << SERVER_NAME << " 311 " << CLIENT_NICK(client) << " " << CLIENT_NICK(target) << " " << CLIENT_USER(target) << " " << CLIENT_HOST(target) << " * :" << CLIENT_REALNAME(target) << "\r\n"; return oss.str(); } -inline std::string RPL_WHOISSERVER(int clientFd, const std::string& targetNick, const std::string& serverInfo) +inline std::string RPL_WHOISSERVER(Client *client, const std::string& targetNick, const std::string& serverInfo) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 312 " << clientFd << " " << targetNick << " " << SERVER_NAME + oss << ":" << SERVER_NAME << " 312 " << CLIENT_NICK(client) << " " << targetNick << " " << SERVER_NAME << " :" << serverInfo << "\r\n"; return oss.str(); } -inline std::string RPL_ENDOFWHO(int clientFd, const std::string& channel) +inline std::string RPL_ENDOFWHO(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 315 " << clientFd << " " << channel << " :End of /WHO list.\r\n"; + oss << ":" << SERVER_NAME << " 315 " << CLIENT_NICK(client) << " " << channel << " :End of /WHO list.\r\n"; return oss.str(); } -inline std::string RPL_ENDOFWHOIS(int clientFd, const std::string& targetNick) +inline std::string RPL_ENDOFWHOIS(Client *client, const std::string& targetNick) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 318 " << clientFd << " " << targetNick << " :End of /WHOIS list.\r\n"; + oss << ":" << SERVER_NAME << " 318 " << CLIENT_NICK(client) << " " << targetNick << " :End of /WHOIS list.\r\n"; return oss.str(); } // RPL Channel List Messages -inline std::string RPL_LIST(int clientFd, const std::string& channel, int numVisible, const std::string& topic) +inline std::string RPL_LIST(Client *client, const std::string& channel, int numVisible, const std::string& topic) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 322 " << clientFd << " " << channel << " " << numVisible << " :" << topic << "\r\n"; + oss << ":" << SERVER_NAME << " 322 " << CLIENT_NICK(client) << " " << channel << " " << numVisible << " :" << topic << "\r\n"; return oss.str(); } -inline std::string RPL_LISTEND(int clientFd) +inline std::string RPL_LISTEND(Client *client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 323 " << clientFd << " :End of /LIST\r\n"; + oss << ":" << SERVER_NAME << " 323 " << CLIENT_NICK(client) << " :End of /LIST\r\n"; return oss.str(); } // RPL Mode Messages -inline std::string RPL_CHANNELMODEIS(int clientFd, const std::string& channel, const std::string& mode) +inline std::string RPL_CHANNELMODEIS(Client *client, const std::string& channel, const std::string& mode) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 324 " << clientFd << " " << channel << " " << mode << "\r\n"; + oss << ":" << SERVER_NAME << " 324 " << CLIENT_NICK(client) << " " << channel << " " << mode << "\r\n"; return oss.str(); } -inline std::string RPL_CREATIONTIME(int clientFd, const std::string& channel, time_t creationTime) { +inline std::string RPL_CREATIONTIME(Client *client, const std::string& channel, time_t creationTime) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 329 " << clientFd << " " << channel << " " << creationTime << "\r\n"; + oss << ":" << SERVER_NAME << " 329 " << CLIENT_NICK(client) << " " << channel << " " << creationTime << "\r\n"; return oss.str(); } inline std::string RPL_NOTOPIC(Client* client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 331 " << CLIENT_NICK(client) << " " << channel - << " :No topic is set\r\n"; + oss << ":" << SERVER_NAME << " 331 " << CLIENT_NICK(client) << " " << channel << " :No topic is set\r\n"; return oss.str(); } inline std::string RPL_TOPIC(Client* client, const std::string& channel, const std::string& topic) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 332 " << CLIENT_NICK(client) << " " << channel << " :" << topic << "\r\n"; - return oss.str(); + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 332 " << CLIENT_NICK(client) << " " << channel << " :" << topic << "\r\n"; + return oss.str(); } inline std::string RPL_TOPICWHOTIME(Client* client, const std::string& channel, const std::string& setter, time_t setTime) { + std::ostringstream oss; + oss << ":" << SERVER_NAME << " 333 " << CLIENT_NICK(client) << " " << channel << " " << setter << " " << setTime << "\r\n"; + return oss.str(); +} + +inline std::string RPL_INVITELIST(Client *client, const std::string& channel, const std::string& inviteMask) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 333 " << CLIENT_NICK(client) << " " << channel << " " << setter << " " << setTime << "\r\n"; + oss << ":" << SERVER_NAME << " 336 " << CLIENT_NICK(client) << " " << channel << " " << inviteMask << "\r\n"; return oss.str(); } -inline std::string RPL_INVITELIST(int clientFd, const std::string& channel, const std::string& inviteMask) { +inline std::string RPL_ENDOFINVITELIST(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 336 " << clientFd << " " << channel << " " << inviteMask << "\r\n"; - return oss.str(); -} - -inline std::string RPL_ENDOFINVITELIST(int clientFd, const std::string& channel) { - std::ostringstream oss; - oss << ":" << SERVER_NAME << " 337 " << clientFd << " " << channel << " :End of channel invite list\r\n"; + oss << ":" << SERVER_NAME << " 337 " << CLIENT_NICK(client) << " " << channel << " :End of channel invite list\r\n"; return oss.str(); } @@ -181,15 +181,15 @@ inline std::string RPL_INVITING(Client* client, const std::string& channel, cons return oss.str(); } -inline std::string RPL_EXCEPTLIST(int clientFd, const std::string& channel, const std::string& exceptionMask) { +inline std::string RPL_EXCEPTLIST(Client *client, const std::string& channel, const std::string& exceptionMask) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 348 " << clientFd << " " << channel << " " << exceptionMask << "\r\n"; + oss << ":" << SERVER_NAME << " 348 " << CLIENT_NICK(client) << " " << channel << " " << exceptionMask << "\r\n"; return oss.str(); } -inline std::string RPL_ENDOFEXCEPTLIST(int clientFd, const std::string& channel) { +inline std::string RPL_ENDOFEXCEPTLIST(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 349 " << clientFd << " " << channel << " :End of channel exception list\r\n"; + oss << ":" << SERVER_NAME << " 349 " << CLIENT_NICK(client) << " " << channel << " :End of channel exception list\r\n"; return oss.str(); } @@ -214,56 +214,56 @@ inline std::string RPL_ENDOFNAMES(Client* client, const std::string& channel) { return oss.str(); } -inline std::string RPL_BANLIST(int clientFd, const std::string& channel, const std::string& banMask) { +inline std::string RPL_BANLIST(Client *client, const std::string& channel, const std::string& banMask) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 367 " << clientFd << " " << channel << " " << banMask << "\r\n"; + oss << ":" << SERVER_NAME << " 367 " << CLIENT_NICK(client) << " " << channel << " " << banMask << "\r\n"; return oss.str(); } -inline std::string RPL_ENDOFBANLIST(int clientFd, const std::string& channel) { +inline std::string RPL_ENDOFBANLIST(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 368 " << clientFd << " " << channel << " :End of channel ban list\r\n"; + oss << ":" << SERVER_NAME << " 368 " << CLIENT_NICK(client) << " " << channel << " :End of channel ban list\r\n"; return oss.str(); } inline std::string RPL_MOTD(Client* client, const std::string& line) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 372 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 372 " << CLIENT_NICK(client) << " :- " << line << "\r\n"; return oss.str(); } inline std::string RPL_MOTDSTART(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 375 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 375 " << CLIENT_NICK(client) << " :- " << SERVER_NAME << " Message of the day - \r\n"; return oss.str(); } inline std::string RPL_ENDOFMOTD(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 376 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 376 " << CLIENT_NICK(client) << " :End of /MOTD command.\r\n"; return oss.str(); } -inline std::string ERR_NOSUCHNICK(int clientFd, const std::string& nick) +inline std::string ERR_NOSUCHNICK(Client *client, const std::string& nick) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 401 " << clientFd << " " << nick << " :No such nick/channel\r\n"; + oss << ":" << SERVER_NAME << " 401 " << CLIENT_NICK(client) << " " << nick << " :No such nick/channel\r\n"; return oss.str(); } -inline std::string ERR_NOSUCHCHANNEL(int clientFd, const std::string& channel) +inline std::string ERR_NOSUCHCHANNEL(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 403 " << clientFd << " " << channel << " :No such channel\r\n"; + oss << ":" << SERVER_NAME << " 403 " << CLIENT_NICK(client) << " " << channel << " :No such channel\r\n"; return oss.str(); } -inline std::string ERR_CANNOTSENDTOCHAN(int clientFd, const std::string& channel) { +inline std::string ERR_CANNOTSENDTOCHAN(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 404 " << clientFd << " " << channel << " :Cannot send to channel\r\n"; + oss << ":" << SERVER_NAME << " 404 " << CLIENT_NICK(client) << " " << channel << " :Cannot send to channel\r\n"; return oss.str(); } @@ -277,19 +277,19 @@ inline std::string ERR_TOOMANYCHANNELS(Client* client, const std::string& channe inline std::string ERR_NOORIGIN(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 409 " << CLIENT_FD(client) << " :No origin specified\r\n"; + oss << ":" << SERVER_NAME << " 409 " << CLIENT_NICK(client) << " :No origin specified\r\n"; return oss.str(); } -inline std::string ERR_NORECIPIENT(int clientFd, const std::string& command) { +inline std::string ERR_NORECIPIENT(Client *client, const std::string& command) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 411 " << clientFd << " :No recipient given (" << command << ")\r\n"; + oss << ":" << SERVER_NAME << " 411 " << CLIENT_NICK(client) << " :No recipient given (" << command << ")\r\n"; return oss.str(); } -inline std::string ERR_NOTEXTTOSEND(int clientFd) { +inline std::string ERR_NOTEXTTOSEND(Client *client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 412 " << clientFd << " :No text to send\r\n"; + oss << ":" << SERVER_NAME << " 412 " << CLIENT_NICK(client) << " :No text to send\r\n"; return oss.str(); } @@ -301,7 +301,7 @@ inline std::string ERR_UNKNOWNCOMMAND(Client* client, const std::string& command inline std::string ERR_NOMOTD(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 422 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 422 " << CLIENT_NICK(client) << " :MOTD File is missing\r\n"; return oss.str(); } @@ -309,34 +309,34 @@ inline std::string ERR_NOMOTD(Client* client) { inline std::string ERR_NONICKNAMEGIVEN(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 431 " << CLIENT_FD(client) << " :No nickname given\r\n"; + oss << ":" << SERVER_NAME << " 431 " << CLIENT_NICK(client) << " :No nickname given\r\n"; return oss.str(); } inline std::string ERR_ERRONEUSNICKNAME(Client* client, const std::string& nickname) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 432 " << CLIENT_FD(client) << " " << nickname << " :Erroneous nickname\r\n"; + oss << ":" << SERVER_NAME << " 432 " << CLIENT_NICK(client) << " " << nickname << " :Erroneous nickname\r\n"; return oss.str(); } inline std::string ERR_NICKNAMEINUSE(Client* client, const std::string& nickname) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 433 " << CLIENT_FD(client) << " " << nickname << " :Nickname is already in use\r\n"; + oss << ":" << SERVER_NAME << " 433 " << CLIENT_NICK(client) << " " << nickname << " :Nickname is already in use\r\n"; return oss.str(); } -inline std::string ERR_USERNOTINCHANNEL(int clientFd, const std::string& nick, const std::string& channel) { +inline std::string ERR_USERNOTINCHANNEL(Client *client, const std::string& nick, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 441 " << clientFd << " " << nick << " " << channel + oss << ":" << SERVER_NAME << " 441 " << CLIENT_NICK(client) << " " << nick << " " << channel << " :They aren't on that channel\r\n"; return oss.str(); } -inline std::string ERR_NOTONCHANNEL(int clientFd, const std::string& channel) { +inline std::string ERR_NOTONCHANNEL(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 442 " << clientFd << " " << channel << " :You're not on that channel\r\n"; + oss << ":" << SERVER_NAME << " 442 " << CLIENT_NICK(client) << " " << channel << " :You're not on that channel\r\n"; return oss.str(); } @@ -351,7 +351,7 @@ inline std::string ERR_USERONCHANNEL(Client* client, const std::string& nick, co inline std::string ERR_NOTREGISTERED(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 451 " << CLIENT_FD(client) << " :You have not registered\r\n"; + oss << ":" << SERVER_NAME << " 451 " << CLIENT_NICK(client) << " :You have not registered\r\n"; return oss.str(); } @@ -360,21 +360,21 @@ inline std::string ERR_NOTREGISTERED(Client* client) inline std::string ERR_NEEDMOREPARAMS(Client* client, const std::string& command) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 461 " << CLIENT_FD(client) << " " << command << " :Not enough parameters\r\n"; + oss << ":" << SERVER_NAME << " 461 " << CLIENT_NICK(client) << " " << command << " :Not enough parameters\r\n"; return oss.str(); } inline std::string ERR_ALREADYREGISTERED(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 462 " << CLIENT_FD(client) << " :You may not reregister\r\n"; + oss << ":" << SERVER_NAME << " 462 " << CLIENT_NICK(client) << " :You may not reregister\r\n"; return oss.str(); } inline std::string ERR_PASSWDMISMATCH(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 464 " << CLIENT_FD(client) << " :Password incorrect\r\n"; + oss << ":" << SERVER_NAME << " 464 " << CLIENT_NICK(client) << " :Password incorrect\r\n"; return oss.str(); } @@ -414,29 +414,29 @@ inline std::string ERR_BADCHANMASK(Client* client, const std::string& channel) { return oss.str(); } -inline std::string RPL_NOCHANMODES(int clientFd, const std::string& channel) +inline std::string RPL_NOCHANMODES(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 477 " << clientFd << " " << channel << " :Channel doesn't support modes\r\n"; + oss << ":" << SERVER_NAME << " 477 " << CLIENT_NICK(client) << " " << channel << " :Channel doesn't support modes\r\n"; return oss.str(); } -inline std::string ERR_CHANOPRIVSNEEDED(int clientFd, const std::string& channel) +inline std::string ERR_CHANOPRIVSNEEDED(Client *client, const std::string& channel) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 482 " << clientFd << " " << channel << " :You're not channel operator\r\n"; + oss << ":" << SERVER_NAME << " 482 " << CLIENT_NICK(client) << " " << channel << " :You're not channel operator\r\n"; return oss.str(); } -inline std::string ERR_UMODEUNKNOWNFLAG(int clientFd) { +inline std::string ERR_UMODEUNKNOWNFLAG(Client *client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 501 " << clientFd << " :Unknown MODE flag\r\n"; + oss << ":" << SERVER_NAME << " 501 " << CLIENT_NICK(client) << " :Unknown MODE flag\r\n"; return oss.str(); } -inline std::string ERR_USERSDONTMATCH(int clientFd) { +inline std::string ERR_USERSDONTMATCH(Client *client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 502 " << clientFd << " :Cannot change mode for other users\r\n"; + oss << ":" << SERVER_NAME << " 502 " << CLIENT_NICK(client) << " :Cannot change mode for other users\r\n"; return oss.str(); } @@ -449,26 +449,26 @@ inline std::string RPL_PONG(const std::string& token) } // CAP Command RPLs -inline std::string RPL_CAP(int clientFd, const std::string& subcommand, const std::string& capabilities) +inline std::string RPL_CAP(Client *client, const std::string& subcommand, const std::string& capabilities) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " CAP " << clientFd << " " << subcommand << " :" << capabilities << "\r\n"; + oss << ":" << SERVER_NAME << " CAP " << CLIENT_NICK(client) << " " << subcommand << " :" << capabilities << "\r\n"; return oss.str(); } inline std::string RPL_PASSACCEPTED(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " NOTICE " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " NOTICE " << CLIENT_NICK(client) << " :Password accepted!\r\n"; return oss.str(); } // Add this function to handle the CAP END response -inline std::string RPL_CAPEND(int clientFd) +inline std::string RPL_CAPEND(Client *client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " CAP " << clientFd << " END\r\n"; + oss << ":" << SERVER_NAME << " CAP " << CLIENT_NICK(client) << " END\r\n"; return oss.str(); } diff --git a/ft_irc3/includes/Server.hpp b/ft_irc3/includes/Server.hpp index 52981a8..dfa42d9 100644 --- a/ft_irc3/includes/Server.hpp +++ b/ft_irc3/includes/Server.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:15:13 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 12:20:53 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:13:41 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,6 +21,7 @@ #include "AdditionalCommands.hpp" #include "RPL.hpp" #include "ModeHandler.hpp" +#include "TopicHandler.hpp" #include #include @@ -41,6 +42,7 @@ class ClientManager; class CommandHandler; class AdditionalCommands; class ModeHandler; +class TopicHandler; class Server { @@ -74,10 +76,12 @@ protected: ClientManager *_clientManager; CommandHandler *_commandHandler; ModeHandler *_modeHandler; + TopicHandler *_topicHandler; friend class ClientManager; friend class CommandHandler; friend class ModeHandler; + friend class TopicHandler; private: void initServer(); diff --git a/ft_irc3/includes/TopicHandler.hpp b/ft_irc3/includes/TopicHandler.hpp new file mode 100644 index 0000000..aec098c --- /dev/null +++ b/ft_irc3/includes/TopicHandler.hpp @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* TopicHandler.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/30 17:04:33 by fgras-ca #+# #+# */ +/* Updated: 2024/05/30 17:47:56 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef TOPIC_HANDLER_HPP +#define TOPIC_HANDLER_HPP + +#include +#include +#include +#include "Server.hpp" +#include "Client.hpp" +#include "Channel.hpp" +#include "Utils.hpp" + + +class TopicHandler +{ +public: + TopicHandler(Server* server); + void handleTopicCommand(Client* client, const std::string& command); + +private: + void viewTopic(Client* client, Channel* channel); + void changeTopic(Client* client, Channel* channel, const std::string& topic); + + Server* _server; +}; + +#endif diff --git a/ft_irc3/includes/Welcome.hpp b/ft_irc3/includes/Welcome.hpp index 5e42c00..26c7082 100644 --- a/ft_irc3/includes/Welcome.hpp +++ b/ft_irc3/includes/Welcome.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/21 19:53:17 by fgras-ca #+# #+# */ -/* Updated: 2024/05/21 19:53:24 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:48:13 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,6 +15,7 @@ #include "Client.hpp" #include "Server.hpp" +#include "Utils.hpp" #include class WelcomeHandler diff --git a/ft_irc3/src/AdditionalCommands.cpp b/ft_irc3/src/AdditionalCommands.cpp index 2a2ccd5..a2aa3c0 100644 --- a/ft_irc3/src/AdditionalCommands.cpp +++ b/ft_irc3/src/AdditionalCommands.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/16 15:27:29 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:07:33 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:12:30 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -40,6 +40,11 @@ void AdditionalCommands::processCommand(Client *client, const std::string &comma InviteHandler inviteHandler(_server); inviteHandler.handleInviteCommand(client, command); } + else if (command.find("TOPIC") == 0) + { + TopicHandler topichandler(_server); + topichandler.handleTopicCommand(client, command); + } else if (command.find("LIST") == 0) { broadcastChannelList(client, _server); @@ -57,9 +62,9 @@ void AdditionalCommands::broadcastChannelList(Client *client, Server *server) std::map &channels = server->getChannels(); for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { - server->sendToClient(client->getFd(), RPL_LIST(client->getFd(), it->first, it->second->getClients().size(), "Existing channel")); + server->sendToClient(client->getFd(), RPL_LIST(client, it->first, it->second->getClients().size(), "Existing channel")); } - server->sendToClient(client->getFd(), RPL_LISTEND(client->getFd())); + server->sendToClient(client->getFd(), RPL_LISTEND(client)); } // Fonction pour gérer la commande PART @@ -80,13 +85,13 @@ void AdditionalCommands::handlePartCommand(Server *server, Client *client, const for (size_t i = 0; i < channels.size(); ++i) { std::string &channelName = channels[i]; if (channelMap.find(channelName) == channelMap.end()) { - server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client->getFd(), channelName)); + server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); continue; } Channel *channel = channelMap[channelName]; if (!channel->hasClient(client)) { - server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client->getFd(), channelName)); + server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); continue; } @@ -119,12 +124,12 @@ void AdditionalCommands::handlePrivmsgCommand(Server *server, Client *client, co message = message.substr(1); if (target.empty()) { - server->sendToClient(client->getFd(), ERR_NORECIPIENT(client->getFd(), "PRIVMSG")); + server->sendToClient(client->getFd(), ERR_NORECIPIENT(client, "PRIVMSG")); return; } if (message.empty()) { - server->sendToClient(client->getFd(), ERR_NOTEXTTOSEND(client->getFd())); + server->sendToClient(client->getFd(), ERR_NOTEXTTOSEND(client)); return; } @@ -138,7 +143,7 @@ void AdditionalCommands::handlePrivmsgCommand(Server *server, Client *client, co // Vérifier les conditions spéciales du canal (ex: ban, modération) if (channel->isBanned(client)) { - server->sendToClient(client->getFd(), ERR_CANNOTSENDTOCHAN(client->getFd(), target)); + server->sendToClient(client->getFd(), ERR_CANNOTSENDTOCHAN(client, target)); return; } @@ -167,13 +172,13 @@ void AdditionalCommands::handlePrivmsgCommand(Server *server, Client *client, co server->sendToClient(targetClient->getFd(), privMsg.str()); if (targetClient->isAway()) { - server->sendToClient(client->getFd(), RPL_AWAY(client->getFd(), targetClient->getNickname(), targetClient->getAwayMessage())); + server->sendToClient(client->getFd(), RPL_AWAY(client, targetClient->getNickname(), targetClient->getAwayMessage())); } } else { // Si la cible n'est ni un canal ni un utilisateur existant, envoyer un message d'erreur - server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client->getFd(), target)); + server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, target)); } } } diff --git a/ft_irc3/src/Channel.cpp b/ft_irc3/src/Channel.cpp index 6f0ef02..4519698 100644 --- a/ft_irc3/src/Channel.cpp +++ b/ft_irc3/src/Channel.cpp @@ -6,14 +6,14 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:42:57 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:09:45 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 18:33:19 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Channel.hpp" Channel::Channel(const std::string &name) - : _name(name), _clients(), _operators(), _bannedClients(), _invitedClients(), _key(""), _topic(""), _topicSetter(""), _topicTime(0), _clientLimit(50), _inviteOnly(false) {} + : _name(name), _clients(), _operators(), _bannedClients(), _invitedClients(), _key(""), _topic(""), _topicSetter(""), _topicTime(0), _clientLimit(50), _inviteOnly(false), _topicProtection(false) {} Channel::~Channel() {} @@ -52,6 +52,11 @@ bool Channel::isOperator(Client *client) const return std::find(_operators.begin(), _operators.end(), client) != _operators.end(); } +void Channel::removeOperator(Client *client) +{ + _operators.erase(std::remove(_operators.begin(), _operators.end(), client), _operators.end()); +} + bool Channel::hasClient(Client *client) const { return std::find(_clients.begin(), _clients.end(), client) != _clients.end(); @@ -148,3 +153,8 @@ std::string Channel::getModes() const { if (_topicProtection) modes += 't'; return modes; } + +bool Channel::getTopicProtection() const +{ + return _topicProtection; +} \ No newline at end of file diff --git a/ft_irc3/src/CommandHandler.cpp b/ft_irc3/src/CommandHandler.cpp index b196e8c..d2c9c6a 100644 --- a/ft_irc3/src/CommandHandler.cpp +++ b/ft_irc3/src/CommandHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:26:34 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 12:39:58 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 16:53:35 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -83,11 +83,11 @@ void CommandHandler::handleCapCommand(Client* client, const std::vectorsendToClient(client->getFd(), RPL_CAP(client->getFd(), "LS", capabilities)); + _server->sendToClient(client->getFd(), RPL_CAP(client, "LS", capabilities)); } else if (subcommand == "LIST") { - _server->sendToClient(client->getFd(), RPL_CAP(client->getFd(), "LIST", capabilities)); + _server->sendToClient(client->getFd(), RPL_CAP(client, "LIST", capabilities)); } else if (subcommand == "REQ") { @@ -98,11 +98,11 @@ void CommandHandler::handleCapCommand(Client* client, const std::vectorsendToClient(client->getFd(), RPL_CAP(client->getFd(), "ACK", requestedCapabilities)); + _server->sendToClient(client->getFd(), RPL_CAP(client, "ACK", requestedCapabilities)); } else if (subcommand == "END") { - _server->sendToClient(client->getFd(), RPL_CAPEND(client->getFd())); + _server->sendToClient(client->getFd(), RPL_CAPEND(client)); } else { diff --git a/ft_irc3/src/InviteHandler.cpp b/ft_irc3/src/InviteHandler.cpp index d2339bf..86800fa 100644 --- a/ft_irc3/src/InviteHandler.cpp +++ b/ft_irc3/src/InviteHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 13:02:09 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:08:33 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 16:53:59 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,23 +26,23 @@ void InviteHandler::handleInviteCommand(Client* client, const std::string& comma Channel* channel = _server->getChannelByName(channelName); if (!channel) { - _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client->getFd(), channelName)); + _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); return; } if (!channel->hasClient(client)) { - _server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client->getFd(), channelName)); + _server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); return; } if (!channel->isOperator(client) && channel->isInviteOnly()) { - _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client->getFd(), channelName)); + _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channelName)); return; } Client* targetClient = _server->getClientByName(nickname); if (!targetClient) { - _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client->getFd(), nickname)); + _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, nickname)); return; } diff --git a/ft_irc3/src/Join.cpp b/ft_irc3/src/Join.cpp index 2ac167d..1539118 100644 --- a/ft_irc3/src/Join.cpp +++ b/ft_irc3/src/Join.cpp @@ -113,7 +113,7 @@ void JoinHandler::handleJoinCommand(Client *client, const std::string &channelNa if (channelName[0] != '#' && channelName[0] != '&') { - server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client->getFd(), channelName)); + server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); return; } @@ -191,4 +191,3 @@ std::string JoinHandler::getUsersList(Channel *channel) oss << RPL_ENDOFNAMES(clients[0], channel->getName()); return oss.str(); } - diff --git a/ft_irc3/src/ModeHandler.cpp b/ft_irc3/src/ModeHandler.cpp index 85ce87e..adcbc34 100644 --- a/ft_irc3/src/ModeHandler.cpp +++ b/ft_irc3/src/ModeHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/30 11:13:08 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 13:33:36 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 18:46:37 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,141 +14,184 @@ ModeHandler::ModeHandler(Server* server) : _server(server) {} -void ModeHandler::handleModeCommand(Client* client, const std::string& command) { +void ModeHandler::handleModeCommand(Client* client, const std::string& command) +{ _server->log("Received MODE command: " + command, "\033[1;34m"); - std::vector tokens = split(command, " \n\r\t"); + std::vector tokens = split(command, " \n\r\t"); - if (tokens.size() < 2) { - _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "MODE")); + if (tokens.size() < 2) { + _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "MODE")); _server->log("MODE command error: Need more parameters", "\033[1;31m"); - return; - } + return; + } - std::string target = tokens[1]; - if (target[0] == '#' || target[0] == '&') { + std::string target = tokens[1]; + if (target[0] == '#' || target[0] == '&') { _server->log("Handling channel mode for target: " + target, "\033[1;34m"); - handleChannelMode(client, tokens); - } else { + handleChannelMode(client, tokens); + } else { _server->log("Handling user mode for target: " + target, "\033[1;34m"); - handleUserMode(client, tokens); - } + handleUserMode(client, tokens); + } } -void ModeHandler::handleUserMode(Client* client, const std::vector& tokens) { - std::string target = tokens[1]; - if (target != client->getNickname()) { - _server->sendToClient(client->getFd(), ERR_USERSDONTMATCH(client->getFd())); +void ModeHandler::handleUserMode(Client* client, const std::vector& tokens) +{ + _server->log("Entered handleUserMode", "\033[1;34m"); + std::string target = tokens[1]; + _server->log("User mode target: " + target, "\033[1;34m"); + if (target != client->getNickname()) { + _server->sendToClient(client->getFd(), ERR_USERSDONTMATCH(client)); _server->log("User mode error: Users don't match", "\033[1;31m"); - return; - } + return; + } - if (tokens.size() == 2) { - _server->sendToClient(client->getFd(), RPL_UMODEIS(client->getFd(), "")); // Ajout de la chaîne vide pour les modes utilisateur - _server->log("Sent user modes to client", "\033[1;32m"); - } else { - std::string modeString = tokens[2]; - // Gestion des modes utilisateur (ajout ou suppression) - // Par exemple, vous pouvez gérer l'ajout ou la suppression du mode invisible ici - _server->log("Updating user modes: " + modeString, "\033[1;34m"); - } + if (tokens.size() == 2) { + _server->sendToClient(client->getFd(), RPL_UMODEIS(client, "")); + _server->log("Sent user modes to client", "\033[1;32m"); + } else { + std::string modeString = tokens[2]; + _server->log("Updating user modes: " + modeString, "\033[1;34m"); + // Additional logging or mode handling logic can be added here + } } -void ModeHandler::handleChannelMode(Client* client, const std::vector& tokens) { - std::string channelName = tokens[1]; - Channel* channel = _server->getChannelByName(channelName); - if (!channel) { - _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client->getFd(), channelName)); +void ModeHandler::handleChannelMode(Client* client, const std::vector& tokens) +{ + _server->log("Entered handleChannelMode", "\033[1;34m"); + std::string channelName = tokens[1]; + _server->log("Channel mode target: " + channelName, "\033[1;34m"); + Channel* channel = _server->getChannelByName(channelName); + if (!channel) { + _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); _server->log("Channel mode error: No such channel " + channelName, "\033[1;31m"); - return; - } + return; + } - if (tokens.size() == 2) { - // Retourner les modes actuels du canal - std::ostringstream oss; - oss << RPL_CHANNELMODEIS(client->getFd(), channel->getName(), channel->getModes()); - oss << RPL_CREATIONTIME(client->getFd(), channel->getName(), channel->getTopicTime()); - _server->sendToClient(client->getFd(), oss.str()); - _server->log("Sent channel modes to client", "\033[1;32m"); - return; - } + if (tokens.size() == 2) { + std::ostringstream oss; + oss << RPL_CHANNELMODEIS(client, channel->getName(), channel->getModes()); + oss << RPL_CREATIONTIME(client, channel->getName(), channel->getTopicTime()); + _server->sendToClient(client->getFd(), oss.str()); + _server->log("Sent channel modes to client", "\033[1;32m"); + return; + } - if (!channel->isOperator(client)) { - _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client->getFd(), channelName)); + if (!channel->isOperator(client)) { + _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channelName)); _server->log("Channel mode error: Channel operator privileges needed for " + channelName, "\033[1;31m"); - return; - } + return; + } - std::string modeString = tokens[2]; - bool adding = true; - size_t argIndex = 3; + std::string modeString = tokens[2]; + bool adding = true; + size_t argIndex = 3; - for (size_t i = 0; i < modeString.length(); ++i) { - char mode = modeString[i]; - if (mode == '+') { - adding = true; - } else if (mode == '-') { - adding = false; - } else if (mode == 'b' || mode == 'l' || mode == 'i' || mode == 'k' || mode == 't') { - std::string argument; - if (argIndex < tokens.size()) { - argument = tokens[argIndex++]; - } - setChannelMode(channel, std::string(1, mode), adding, argument); - } else { - _server->sendToClient(client->getFd(), ERR_UNKNOWNMODE(client, mode, channelName)); - } - } + for (size_t i = 0; i < modeString.length(); ++i) { + char mode = modeString[i]; + if (mode == '+') { + adding = true; + _server->log("Adding mode: " + std::string(1, mode), "\033[1;34m"); + } else if (mode == '-') { + adding = false; + _server->log("Removing mode: " + std::string(1, mode), "\033[1;34m"); + } else if (mode == 'b' || mode == 'l' || mode == 'i' || mode == 'k' || mode == 't') { + std::string argument; + if (argIndex < tokens.size()) { + argument = tokens[argIndex++]; + } + setChannelMode(client, channel, std::string(1, mode), adding, argument); + } else { + _server->sendToClient(client->getFd(), ERR_UNKNOWNMODE(client, mode, channelName)); + _server->log("Unknown mode: " + std::string(1, mode), "\033[1;31m"); + } + } } -void ModeHandler::setChannelMode(Channel* channel, const std::string& mode, bool adding, const std::string& argument) { - /*if (mode == "b") { - applyModeB(channel, adding, argument); - }*/ - if (mode == "l") { - applyModeL(channel, adding, argument); - } else if (mode == "i") { - applyModeI(channel, adding); - } else if (mode == "k") { - applyModeK(channel, adding, argument); - } else if (mode == "t") { - applyModeT(channel, adding); - } +void ModeHandler::setChannelMode(Client *client, Channel* channel, const std::string& mode, bool adding, const std::string& argument) +{ + _server->log("Setting channel mode: " + mode + " Adding: " + (adding ? "true" : "false") + " Argument: " + argument, "\033[1;32m"); + if (mode == "l") + { + applyModeL(channel, adding, argument); + } + else if (mode == "i") + { + applyModeI(channel, adding); + } + else if (mode == "k") + { + applyModeK(channel, adding, argument); + } + else if (mode == "t") + { + applyModeT(channel, adding); + } + else if (mode == "o") + applyModeO(client, channel, adding, argument); } -/*void ModeHandler::applyModeB(Channel* channel, bool adding, const std::string& argument) { - // Implémentation de l'ajout ou de la suppression de bannissements - // Note : Vous pouvez ajouter des méthodes à la classe Channel pour gérer la liste des bannissements - if (adding) { - // Ajouter le masque à la liste des bannissements - // channel->banClient(argument); - } else { - // Supprimer le masque de la liste des bannissements - // channel->unbanClient(argument); - } -}*/ - -void ModeHandler::applyModeL(Channel* channel, bool adding, const std::string& argument) { - if (adding) { - int limit = std::atoi(argument.c_str()); - channel->setClientLimit(limit); - } else { - channel->setClientLimit(0); // Retirer la limite - } +void ModeHandler::applyModeL(Channel* channel, bool adding, const std::string& argument) +{ + if (adding) { + int limit = std::atoi(argument.c_str()); + std::ostringstream oss; + oss << limit; + _server->log("Applying mode L: Setting limit to " + oss.str(), "\033[1;32m"); + channel->setClientLimit(limit); + } else { + _server->log("Applying mode L: Removing limit", "\033[1;31m"); + channel->setClientLimit(0); + } } -void ModeHandler::applyModeI(Channel* channel, bool adding) { - channel->setInviteOnly(adding); +void ModeHandler::applyModeI(Channel* channel, bool adding) +{ + _server->log("Applying mode I: " + std::string(adding ? "Setting invite-only" : "Removing invite-only"), "\033[1;32m"); + channel->setInviteOnly(adding); } -void ModeHandler::applyModeK(Channel* channel, bool adding, const std::string& argument) { - if (adding) { - channel->setKey(argument); - } else { - channel->setKey(""); - } +void ModeHandler::applyModeK(Channel* channel, bool adding, const std::string& argument) +{ + if (adding) { + _server->log("Applying mode K: Setting key to " + argument, "\033[1;32m"); + channel->setKey(argument); + } else { + _server->log("Applying mode K: Removing key", "\033[1;31m"); + channel->setKey(""); + } } -void ModeHandler::applyModeT(Channel* channel, bool adding) { - channel->setTopicProtection(adding); +void ModeHandler::applyModeT(Channel* channel, bool adding) +{ + _server->log("Applying mode T: " + std::string(adding ? "Setting topic protection" : "Removing topic protection"), "\033[1;32m"); + channel->setTopicProtection(adding); } +void ModeHandler::applyModeO(Client* client, Channel* channel, bool adding, const std::string& argument) +{ + Client* targetClient = _server->getClientByName(argument); + if (!targetClient) { + _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, argument)); + _server->log("Mode o error: No such client " + argument, "\033[1;31m"); + return; + } + + if (!channel->hasClient(targetClient)) { + _server->sendToClient(client->getFd(), ERR_USERNOTINCHANNEL(client, argument, channel->getName())); + _server->log("Mode o error: Client " + argument + " not in channel " + channel->getName(), "\033[1;31m"); + return; + } + + if (adding) { + _server->log("Applying mode o: Adding operator " + argument, "\033[1;32m"); + channel->addOperator(targetClient); + std::string message = ":" + client->getNickname() + " MODE " + channel->getName() + " +o " + targetClient->getNickname() + "\r\n"; + channel->broadcast(message, NULL, _server); + } else { + _server->log("Applying mode o: Removing operator " + argument, "\033[1;31m"); + channel->removeOperator(targetClient); + std::string message = ":" + client->getNickname() + " MODE " + channel->getName() + " -o " + targetClient->getNickname() + "\r\n"; + channel->broadcast(message, NULL, _server); + } +} \ No newline at end of file diff --git a/ft_irc3/src/Server.cpp b/ft_irc3/src/Server.cpp index 31e4cce..aa31bf2 100644 --- a/ft_irc3/src/Server.cpp +++ b/ft_irc3/src/Server.cpp @@ -6,14 +6,14 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:17:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/30 12:18:40 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 17:14:19 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Server.hpp" Server::Server(int port, const std::string &password) - : _port(port), _password(password), _clientManager(new ClientManager(this)), _commandHandler(new CommandHandler(this)), _modeHandler(new ModeHandler(this)) + : _port(port), _password(password), _clientManager(new ClientManager(this)), _commandHandler(new CommandHandler(this)), _modeHandler(new ModeHandler(this)), _topicHandler(new TopicHandler(this)) { initServer(); } @@ -164,7 +164,7 @@ void Server::handleServerCommands() void Server::log(const std::string &message, const std::string &color) { - std::cout << color << message << "\033[0m" << std::endl; + std::cout << color << message << std::endl; } void Server::sendToClient(int client_fd, const std::string &message) @@ -221,9 +221,9 @@ void Server::sendChannelListToClient(Client *client) std::map &channels = getChannels(); for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { - sendToClient(client->getFd(), RPL_LIST(client->getFd(), it->first, it->second->getClients().size(), "Existing channel")); + sendToClient(client->getFd(), RPL_LIST(client, it->first, it->second->getClients().size(), "Existing channel")); } - sendToClient(client->getFd(), RPL_LISTEND(client->getFd())); + sendToClient(client->getFd(), RPL_LISTEND(client)); } bool Server::MatchFd(const pollfd& pfd, int clientFd) diff --git a/ft_irc3/src/TopicHandler.cpp b/ft_irc3/src/TopicHandler.cpp new file mode 100644 index 0000000..43bbdc9 --- /dev/null +++ b/ft_irc3/src/TopicHandler.cpp @@ -0,0 +1,84 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* TopicHandler.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/30 17:04:58 by fgras-ca #+# #+# */ +/* Updated: 2024/05/30 18:05:42 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "TopicHandler.hpp" + +TopicHandler::TopicHandler(Server* server) : _server(server) {} + +void TopicHandler::handleTopicCommand(Client* client, const std::string& command) +{ + _server->log("Received TOPIC command: " + command, "\033[1;34m"); + std::vector tokens = split(command, " \n\r\t"); + + if (tokens.size() < 2) { + _server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "TOPIC")); + _server->log("TOPIC command error: Need more parameters", "\033[1;31m"); + return; + } + + std::string channelName = tokens[1]; + Channel* channel = _server->getChannelByName(channelName); + if (!channel) { + _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client, channelName)); + _server->log("TOPIC command error: No such channel " + channelName, "\033[1;31m"); + return; + } + + if (!channel->hasClient(client)) { + _server->sendToClient(client->getFd(), ERR_NOTONCHANNEL(client, channelName)); + _server->log("TOPIC command error: Client not on channel " + channelName, "\033[1;31m"); + return; + } + + if (tokens.size() == 2) { + viewTopic(client, channel); + } else { + size_t topicStart = command.find(" :"); + std::string topic = (topicStart != std::string::npos) ? command.substr(topicStart + 2) : ""; + changeTopic(client, channel, topic); + } +} + +void TopicHandler::viewTopic(Client* client, Channel* channel) +{ + if (channel->getTopic().empty()) { + _server->sendToClient(client->getFd(), RPL_NOTOPIC(client, channel->getName())); + _server->log("No topic set for channel " + channel->getName(), "\033[1;32m"); + } else { + _server->sendToClient(client->getFd(), RPL_TOPIC(client, channel->getName(), channel->getTopic())); + _server->sendToClient(client->getFd(), RPL_TOPICWHOTIME(client, channel->getName(), channel->getTopicSetter(), channel->getTopicTime())); + _server->log("Sent topic info for channel " + channel->getName(), "\033[1;32m"); + } +} + +void TopicHandler::changeTopic(Client* client, Channel* channel, const std::string& topic) +{ + if (channel->getTopicProtection() && !channel->isOperator(client)) { + _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client, channel->getName())); + _server->log("TOPIC command error: Channel operator privileges needed for " + channel->getName(), "\033[1;31m"); + return; + } + + if (topic == channel->getTopic()) { + _server->sendToClient(client->getFd(), RPL_TOPIC(client, channel->getName(), channel->getTopic())); + _server->log("TOPIC unchanged for channel " + channel->getName(), "\033[1;32m"); + return; + } + + channel->setTopic(topic, client->getNickname()); + std::vector clients = channel->getClients(); + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + _server->sendToClient((*it)->getFd(), ":" + client->getNickname() + " TOPIC " + channel->getName() + " :" + topic + "\r\n"); + } + + _server->log("Changed topic for channel " + channel->getName() + " to: " + topic, GREEN); +} diff --git a/ft_irc3/src/Welcome.cpp b/ft_irc3/src/Welcome.cpp index e99839e..28cb40a 100644 --- a/ft_irc3/src/Welcome.cpp +++ b/ft_irc3/src/Welcome.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/21 17:53:52 by fgras-ca #+# #+# */ -/* Updated: 2024/05/21 19:54:48 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 16:43:14 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,7 +18,7 @@ void WelcomeHandler::sendWelcomeMessages(Client *client, Server *server) server->sendToClient(client->getFd(), RPL_YOURHOST(client)); server->sendToClient(client->getFd(), RPL_CREATED(client)); server->sendToClient(client->getFd(), RPL_MYINFO(client)); - server->sendToClient(client->getFd(), RPL_ISUPPORT(client, "MODES=EXAMPLE")); + server->sendToClient(client->getFd(), RPL_ISUPPORT(client, "i/t/k/o/l")); sendMotd(client, server); } diff --git a/ft_irc3/src/Who.cpp b/ft_irc3/src/Who.cpp index c785a45..34b22f6 100644 --- a/ft_irc3/src/Who.cpp +++ b/ft_irc3/src/Who.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/17 16:09:20 by fgras-ca #+# #+# */ -/* Updated: 2024/05/28 14:33:29 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/30 16:56:03 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -43,7 +43,7 @@ void WhoHandler::handleWhoCommand(Client *client, const std::string &command) } } - _server->sendToClient(client->getFd(), RPL_ENDOFWHO(client->getFd(), mask)); + _server->sendToClient(client->getFd(), RPL_ENDOFWHO(client, mask)); } void WhoHandler::handleWhoisCommand(Client *client, const std::string &command) @@ -61,11 +61,11 @@ void WhoHandler::handleWhoisCommand(Client *client, const std::string &command) Client *targetClient = _server->getClientByName(target); if (!targetClient) { - _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client->getFd(), target)); + _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client, target)); return; } - _server->sendToClient(client->getFd(), RPL_WHOISUSER(client->getFd(), targetClient)); - _server->sendToClient(client->getFd(), RPL_WHOISSERVER(client->getFd(), target, "IRC server info")); - _server->sendToClient(client->getFd(), RPL_ENDOFWHOIS(client->getFd(), target)); + _server->sendToClient(client->getFd(), RPL_WHOISUSER(client, targetClient)); + _server->sendToClient(client->getFd(), RPL_WHOISSERVER(client, target, "IRC server info")); + _server->sendToClient(client->getFd(), RPL_ENDOFWHOIS(client, target)); }