From d426297b2aed5843387c818fe81a8bcf0f889adf Mon Sep 17 00:00:00 2001 From: Danny Jonker Date: Sat, 3 Aug 2024 21:04:44 +0200 Subject: [PATCH] bla --- Cap.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ Cap.hpp | 22 ++++++++++++++++ Invite.cpp | 33 ++++++++++++++++++++++++ Invite.hpp | 19 ++++++++++++++ Join.cpp | 52 ++++++++++++++++++++++++++++++++++++++ Join.hpp | 20 +++++++++++++++ Kick.cpp | 45 +++++++++++++++++++++++++++++++++ Kick.hpp | 20 +++++++++++++++ Mode.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Mode.hpp | 23 +++++++++++++++++ Nick.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++ Nick.hpp | 22 ++++++++++++++++ Part.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++ Part.hpp | 20 +++++++++++++++ Ping.cpp | 26 +++++++++++++++++++ Ping.hpp | 20 +++++++++++++++ Privmsg.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++ Privmsg.hpp | 22 ++++++++++++++++ Quit.cpp | 39 ++++++++++++++++++++++++++++ Quit.hpp | 20 +++++++++++++++ Topic.cpp | 45 +++++++++++++++++++++++++++++++++ Topic.hpp | 19 ++++++++++++++ UserCMD.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ UserCMD.hpp | 22 ++++++++++++++++ Utils.cpp | 11 ++++++++ Who.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++ Who.hpp | 18 +++++++++++++ 27 files changed, 975 insertions(+) create mode 100644 Cap.cpp create mode 100644 Cap.hpp create mode 100644 Invite.cpp create mode 100644 Invite.hpp create mode 100644 Join.cpp create mode 100644 Join.hpp create mode 100644 Kick.cpp create mode 100644 Kick.hpp create mode 100644 Mode.cpp create mode 100644 Mode.hpp create mode 100644 Nick.cpp create mode 100644 Nick.hpp create mode 100644 Part.cpp create mode 100644 Part.hpp create mode 100644 Ping.cpp create mode 100644 Ping.hpp create mode 100644 Privmsg.cpp create mode 100644 Privmsg.hpp create mode 100644 Quit.cpp create mode 100644 Quit.hpp create mode 100644 Topic.cpp create mode 100644 Topic.hpp create mode 100644 UserCMD.cpp create mode 100644 UserCMD.hpp create mode 100644 Utils.cpp create mode 100644 Who.cpp create mode 100644 Who.hpp diff --git a/Cap.cpp b/Cap.cpp new file mode 100644 index 0000000..be9cf2a --- /dev/null +++ b/Cap.cpp @@ -0,0 +1,67 @@ +#include "Cap.hpp" +#include "../IRC.hpp" +#include + +bool Cap::validate(const User &user, const std::string &msg) +{ + std::istringstream iss(msg); + std::string word; + iss >> word; // should be CAP + iss >> word; // should be the mode + if (word == "LS") + { + this->mode = 1; // In this mode run will print the capabilities of the server + iss >> word; // Should be a code + this->code = word; // Not sure if we need it but if we do we have it. + return (true); + } + if (word == "REQ") + { + this->mode = 2; // in this mode run will acknowledge the capabilities sent by the client + size_t pos; + size_t leng; + iss >> word; // Should be a all the capabilities with a : in front of them + leng = word.length(); + pos = word.find(":") + 1; + this->capabilities = word.substr(pos, leng - pos); // remove the : + return (true); + } + std::cout << "Command without mode match" << word << std::endl; + return (false); +} + +int Cap::run(User &user, IRC::t_send_f &send) +{ + if (this->mode == 1) // Mode is LS + { + send(this->targetUser, IRCManager::getHostName + " CAP * LS :" + IRCManager::getCapabilities(); + return (0); + } + if (this->mode == 2) // mode is REQ + { + std::istringstream serverCap(IRCManager::getCapabilities); + std::istringstream clientCap; + std::string server; + std::string client; + std::string matches; + serverCap >> server; + while server[0]) + { + clientCap(this->capabilities); + clientCap >> client + while (client[0]) + { + if (client == server) + { + matches = matches + client + " "; + break; + } + clientCap >> client + } + serverCap >> server; + } + send(this->targetUser, IRCManager::getHostName + " CAP " + user.getNickName() + " ACK :" + matches; + return (0); + } + return (0); +} diff --git a/Cap.hpp b/Cap.hpp new file mode 100644 index 0000000..dfc78ea --- /dev/null +++ b/Cap.hpp @@ -0,0 +1,22 @@ +#ifndef CAP_HPP +#define CAP_HPP + +#include "../ICommand.hpp" +#include + +class Cap : public ICommand +{ + private: + int mode; + std::string lsCode; + User *targetUser; + Channel *targetChannel; + std::string *capabilities; + public: + Cap(); + ~Cap(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif diff --git a/Invite.cpp b/Invite.cpp new file mode 100644 index 0000000..ea9c711 --- /dev/null +++ b/Invite.cpp @@ -0,0 +1,33 @@ +#include "Invite.hpp" +#include "../IRC.hpp" +#include + +bool Invite::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + std::istringstream iss(msg); + std::string word; + iss >> word; // should be INVITE + iss >> word; // should be the user you want to invite + this->targetUser = IRCManager::getUserByName(word); + iss >> word; // should be the channel you want to invite to + this->targetChannel = IRCManager::getChannelByName(word); + if (this->targetChannel) // Check if the channel exists + { + if (this->targetUser) // Check if the user exists + { + return (true); + } + return (false); + } + return (true); +} + +int Invite::run(User &user, IRC::t_send_f &send) +{ + this->targetChannel->inviteUser(this->targetUser); + send(this->targetUser, user.getNickName() + "!~" + user.getUserName() + "@" + user.getHostName() + " INVITE " + this->targetUser->getNickName() + " :" + this->targetChannel->getChannelName()); + return (0); +} diff --git a/Invite.hpp b/Invite.hpp new file mode 100644 index 0000000..620085b --- /dev/null +++ b/Invite.hpp @@ -0,0 +1,19 @@ +#ifndef INVITE_HPP +#define INVITE_HPP + +#include "../ICommand.hpp" +#include + +class Invite : public ICommand +{ + private: + User *targetUser; + Channel *targetChannel; + public: + Invite(); + ~Invite(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif diff --git a/Join.cpp b/Join.cpp new file mode 100644 index 0000000..9757f3f --- /dev/null +++ b/Join.cpp @@ -0,0 +1,52 @@ +#include "Join.hpp" +#include "../IRC.hpp" +#include + +bool Join::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + leng = msg.length(); + pos = msg.find(" "); + name = msg.substr(pos + 1, leng - pos); + this->channel = IRCManager::getChannel(name); + if (this->channel) // Check if the channel exists + { + if (this->channel->getInviteStatus()) // If it exists do we need an invite? + { + if (this->channel->checkUserInvite(user)) // Does the user have the invite to join this chat? + { + return (true); + } + return (false); + } + } + else // The Channel doesn't exist yet + return (true); +} + +int Join::run(User &user, IRC::t_send_f &send) +{ + if (!this->channel) // Check if the channel exists + { + IRCManager::addChannel(name); // create the channel + this->channel = IRCManager::getChannel(name); + this->channel->AddUser(user); + IRCManager::makeOper(user, this->channel); + } + else // Channel exists + { + this->channel->AddUser(user); + } + std::istringstream iss(this->channel->getUserList()); + std::string target; + iss >> target; + while (target[0]) + { + send(IRCManager::getUserFromName(target), user.getNickName() + "!~" + user.getUserName() + "@" + user.getHostName() + " JOIN " + this->targetChannel->getChannelName() + " * :" + user->getRealName()); + iss >> target; + } + std::cout << user.getUserName() + " Joined " + this->channel->getChannelName(); + return (0); +} diff --git a/Join.hpp b/Join.hpp new file mode 100644 index 0000000..05f7d8a --- /dev/null +++ b/Join.hpp @@ -0,0 +1,20 @@ +#ifndef JOIN_HPP +#define JOIN_HPP + +#include "../ICommand.hpp" +#include + +class Join : public ICommand +{ + private: + Channel *channel; + std::string name; + public: + Join(); + ~Join(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif + diff --git a/Kick.cpp b/Kick.cpp new file mode 100644 index 0000000..f10f312 --- /dev/null +++ b/Kick.cpp @@ -0,0 +1,45 @@ +#include "Kick.hpp" +#include "../IRC.hpp" +#include + +bool Kick::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + leng = msg.length(); + pos = msg.find(":"); + this->reason = msg.substr(pos, leng - pos); + if (!this->reason[0]) + this->reason = " :" + this->targetUser->getNickName(); + std::istringstream iss(msg); + std::string word; + iss >> word; // should be KICK + iss >> word; // should be the channel you want to kick from + this->targetChannel = IRCManager::getChannelByName(word); + iss >> word; // should be the user you want to kick + this->targetUser = IRCManager::getUserByName(word); + if (this->targetChannel) // Check if the channel exists + { + if (this->targetUser) // Check if the user exists + { + if (this->targetChannel->checkOper(user)) // Check if we have operator permissions in the channel + return (true); + } + } + return (false); +} + +int Kick::run(User &user, IRC::t_send_f &send) +{ + std::istringstream iss(this->targetChannel->getUserList()); + std::string target; + iss >> target; + while (target[0]) + { + send(this->targetUser, user.getNickName() + "!~" + user.getUserName() + "@" + user.getHostName() + " KICK " + this->targetChannel->getChannelName() + " " + this->targetUser->getNickName() + " :" + this->reason); + iss >> target; + } + this->targetChannel->removeUser(this->targetUser); + return (0); +} diff --git a/Kick.hpp b/Kick.hpp new file mode 100644 index 0000000..2a1d42c --- /dev/null +++ b/Kick.hpp @@ -0,0 +1,20 @@ +#ifndef KICK_HPP +#define KICK_HPP + +#include "../ICommand.hpp" +#include + +class Kick : public ICommand +{ + private: + User *targetUser; + Channel *targetChannel; + std::string reason; + public: + Kick(); + ~Kick(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif diff --git a/Mode.cpp b/Mode.cpp new file mode 100644 index 0000000..56e49f8 --- /dev/null +++ b/Mode.cpp @@ -0,0 +1,73 @@ +#include "Mode.hpp" +#include "../IRC.hpp" +#include + +bool Mode::validate(const User &user, const std::string &msg) +{ + std::istringstream iss(msg); + std::string word; + std::string permissions; + iss >> word; // should be MODE + iss >> word; // should be the channel you want to adjust permissions to + this->targetChannel = IRCManager::getChannelByName(word); + iss >> word; // should be the permissions to adjust + permissions = word; + iss >> word; // should be the user that gets affected + this->targetUser = IRCManager::getUserByName(word); + if (this->targetChannel) // Check if the channel exists + { + if (this->targetUser) // Check if the user exists + { + if (this->targetChannel->checkOper(user)) // Check if we have operator permissions in the channel + { + if (permissions.find("+") != permissions.npos()) // we are going to give a mode + { + if (permissions.find("v") != permissions.npos()) // we are going to give voice + this->voice = 1; + else if (permissions.find("b") != permissions.npos()) // we are going to give ban + this->ban = 1; + else if (permissions.find("o") != permissions.npos()) // we are going to give oper + this->oper = 1; + } + else if (permissions.find("-") != permissions.npos()) // we are going to take a mode + { + if (permissions.find("v") != permissions.npos()) // we are going to take voice + this->voice = 2; + else if (permissions.find("b") != permissions.npos()) // we are going to take ban + this->ban = 2; + else if (permissions.find("o") != permissions.npos()) // we are going to take oper + this->oper = 2; + } + if (this->voice || this->ban || this->oper) // if we need to change anything + return (true); + } + } + } + return (false); +} + +int Mode::run(User &user, IRC::t_send_f &send) +{ + if (this->voice) + { + if (this->voice == 1) + this->targetChannel->giveVoice(this->targetUser); + if (this->voice == 2) + this->targetChannel->takeVoice(this->targetUser); + } + if (this->ban) + { + if (this->ban == 1) + this->targetChannel->giveBan(this->targetUser); + if (this->ban == 2) + this->targetChannel->takeBan(this->targetUser); + } + if (this->oper) + { + if (this->oper == 1) + this->targetChannel->giveOper(this->targetUser); + if (this->oper == 2) + this->targetChannel->takeOper(this->targetUser); + } + return (0); +} diff --git a/Mode.hpp b/Mode.hpp new file mode 100644 index 0000000..aa884a8 --- /dev/null +++ b/Mode.hpp @@ -0,0 +1,23 @@ +#ifndef MODE_HPP +#define MODE_HPP + +#include "../ICommand.hpp" +#include + +class Mode : public ICommand +{ + private: + User *targetUser; + Channel *targetChannel; + int voice; + int oper; + int ban; + + public: + Mode(); + ~Mode(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif diff --git a/Nick.cpp b/Nick.cpp new file mode 100644 index 0000000..a89e518 --- /dev/null +++ b/Nick.cpp @@ -0,0 +1,65 @@ +#include "Nick.hpp" +#include "../IRC.hpp" +#include + +Nick::Nick() {} + +Nick::~Nick() {} + +bool Nick::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + leng = msg.length(); + pos = msg.find(" "); + this->nickName = msg.substr(pos + 1, leng - pos); + // probably need to check for length and illegal characters + return true; +} + +bool Nick::validate(const Connection &conn, const std::string &msg) +{ + size_t pos; + size_t leng; + + leng = msg.length(); + pos = msg.find(" "); + this->nickName = msg.substr(pos, leng - pos); + // probably need to check for length and illegal characters + return true; +} + +int Nick::run(User &user, IRC::t_send_f &send) +{ + user->setNickName(this->nickName); + std::istringstream issc(user->getChannelList()); + std::string targetchannel; + issc >> targetchannel; + while (targetchannel[0]) + { + std::istringstream issu(IRCManager::getChannelFromName(targetchannel)->getUserList()); + std::string targetuser; + iss >> targetuser; + while (targetuser[0]) + { + send(IRCManager::getUserFromName(targetuser), user.getNickName() + "!~" + user.getUserName() + "@" + user.getHostName() + " NICK " + " :" + user->getNickName()); + issu >> targetuser; + } + issc >> targetchannel; + } + return (0); +} + +int Nick::run(Connection &conn, IRC::t_send_f &send) // second run function with Connection argument is for when user is not created yet +{ + if (conn->getNickName()) // User was called before and we will create the user here + { + IRCManager::addUser(conn, conn->getUserName(), conn->getRealName(), this->nickName()); + } + else // Nick was called before User and User will be created in User + { + conn->setNickName(this->nickName); + } + return (0); +} diff --git a/Nick.hpp b/Nick.hpp new file mode 100644 index 0000000..34b7f3a --- /dev/null +++ b/Nick.hpp @@ -0,0 +1,22 @@ +#ifndef NICK_HPP +#define NICK_HPP + +#include "../ICommand.hpp" +#include "../IRC.hpp" +#include + +class Nick : public ICommand +{ + private: + std::string nickName; + public: + Nick(); + ~Nick(); + bool validate(const User &user, const std::string &msg); + bool validate(const Connection &conn, const std::string &message); + int run(User &user, IRC::t_send_f &send); + int run(Connection &conn, IRC::t_send_f &send); +}; + +#endif + diff --git a/Part.cpp b/Part.cpp new file mode 100644 index 0000000..a0d7ae3 --- /dev/null +++ b/Part.cpp @@ -0,0 +1,61 @@ +#include "Part.hpp" +#include "../IRC.hpp" +#include +#include + +Part::Part() {} + +Part::~Part() {} + +bool Part::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + std::istringstream iss(msg); + std::string iter; + + iss >> iter; //iter will be PART, which we already know + iss >> iter; //iter will be The channel that the user is leaving + if (iter[0] == '#') // If the string starts with a # it is a channel + { + this->targetChannel = IRCManager::getChannelByName(iter); // identify channel + if (!this->targetChannel) + { + std::cout << "Channel " + iter + " Does not exist, maybe we should send something back?"; // Not sure what is the proper response here, for now we print + return false; // return false to Dmitry + } + else // The channel exists + { + if (!IRCManager::checkChannelMember(user, iter)) // check if the user is part of the channel + { + std::cout << user.getUserName() + " is not a member of " + iter + " So we would be leaving nothing"; + return false; + } + } + } + else + { + std::cout << "You can't part with a user, you can only part with channels" << std::endl; + return (false); + } + + leng = msg.length(); // get the length of the message + pos = msg.find(":") + 1; // get position of the reason + this->reason = msg.substr(pos, leng - pos); // store the reason + return true; +} + +int Part::run(User &user, IRC::t_send_f &send) +{ + std::istringstream iss(targetChannel->getUserList()); + std::string target; + + iss >> target; + while (target[0]) + { + send(IRCManager::getUserFromName(target), user.getNickName() + user.getHostName() + " PART " + this->targetChannel->getChannelName() + " " + this->reason); + iss >> target; + } + this->targetChannel->removeUser(user); + return (0); +} diff --git a/Part.hpp b/Part.hpp new file mode 100644 index 0000000..f5a5915 --- /dev/null +++ b/Part.hpp @@ -0,0 +1,20 @@ +#ifndef PART_HPP +#define PART_HPP + +#include "../ICommand.hpp" +#include + + +class Part : public ICommand +{ + private: + std::string reason; + Channel *targetChannel; + public: + Part(); + ~Part(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif diff --git a/Ping.cpp b/Ping.cpp new file mode 100644 index 0000000..1ab31f2 --- /dev/null +++ b/Ping.cpp @@ -0,0 +1,26 @@ +#include "Ping.hpp" +#include "../IRC.hpp" +#include + + +Ping::Ping() : pingID("") {} + +Ping::~Ping() {} + +bool Ping::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + leng = msg.length(); // get the length of the message + pos = msg.find(" ") + 1; // get position of start of PingID + this->pingID = msg.substr(pos, leng - pos); // set PingID + return true; +} + +int Ping::run(User &user, IRC::t_send_f &send) +{ + send(user, "PONG " + this->pingID); + std::cout << "PONG " + this->pingID << " Sent to " << user.getUserName() << std::endl; + return (0); +} diff --git a/Ping.hpp b/Ping.hpp new file mode 100644 index 0000000..70c2f84 --- /dev/null +++ b/Ping.hpp @@ -0,0 +1,20 @@ +#ifndef PING_HPP +#define PING_HPP + +#include "../ICommand.hpp" +#include "../IRC.hpp" +#include + +class Ping : public ICommand +{ + private: + std::string pingID; + public: + Ping(); + ~Ping(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif + diff --git a/Privmsg.cpp b/Privmsg.cpp new file mode 100644 index 0000000..c92895a --- /dev/null +++ b/Privmsg.cpp @@ -0,0 +1,64 @@ +#include "Privmsg.hpp" +#include "../IRC.hpp" +#include +#include + +Privmsg::Privmsg() {} + +Privmsg::~Privmsg() {} + +bool Privmsg::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + std::istringstream iss(message); + std::string iter; + iss >> iter; + + if (iter[0] == '#') // If the string starts with a # it is a channel + { + this->targetChannel = IRCManager::getChannelByName(iter); // identify channel + if (!this->targetChannel) + { + std::cout << "Channel " + iter + " Does not exist, maybe we should send something back?"; // Not sure what is the proper response here, for now we print + return false; // return false to Dmitry + } + else // The channel exists + { + if (!IRCManager::checkChannelMember(user, iter)) // check if the user is part of the channel + { + std::cout << user.getUserName() + " is not a member of " + iter; + return false; + } + } + } + else // else it is a user + { + this->targetUser = IRCManager::getUserByName(iter); // identify user + if (!this->targetUser) + { + std::cout << "User " + iter + " Does not exist, maybe we should send something back?"; // Not sure what is the proper response here, for now we print + return false; // return false to Dmitry + } + } + while (iter[0]) // put the rest of the string in the message + { + iss >> iter; + message = message + " " + iter; + } + return true; +} + +int Privmsg::run(User &user, IRC::t_send_f &send) +{ + if (this->targetUser) + { + send(user, user.getNickName() + user.getHostName() + " PRIVMSG " + this->targetUser->getUserName() + " " + this->message); + std::cout << user.getUserName() + " sent a message to " + this->targetUser.getUserName(); + } + else + send(user, user.getNickName() + user.getHostName() + " PRIVMSG " + this->targetChannel->getChannelName() + " " + this->message); + std::cout << user.getUserName() + " sent a message to " + this->targetChannel.getChannelName(); + return (0); +} diff --git a/Privmsg.hpp b/Privmsg.hpp new file mode 100644 index 0000000..ea927a0 --- /dev/null +++ b/Privmsg.hpp @@ -0,0 +1,22 @@ +#ifndef PRIVMSG_HPP +#define PRIVMSG_HPP + +#include "../ICommand.hpp" +#include "../User.hpp" +#include + + +class Privmsg : public ICommand +{ + private: + User *targetUser; + Channel *targetChannel; + std::string message; + public: + Privmsg(); + ~Privmsg(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif diff --git a/Quit.cpp b/Quit.cpp new file mode 100644 index 0000000..bc9986b --- /dev/null +++ b/Quit.cpp @@ -0,0 +1,39 @@ +#include "Quit.hpp" +#include "../IRC.hpp" +#include +#include + + +Quit::Quit() {} + +Quit::~Quit() {} + +bool Quit::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + leng = msg.length(); + pos = msg.find(" "); + this->reason = msg.substr(pos, leng - pos); + return true; +} + +int Quit::run(User &user, IRC::t_send_f &send) +{ + std::istringstream iss(user->getChannelList()); + std::string target; + + iss >> target; + while (target[0]) + { + send(IRCManager::getChannelFromName(target), user.getNickName() + user.getHostName() + " Quit " + this->reason); + iss >> target; + if (!user->getRegistered()) + IRCManager::removeUserFromChannel(user, IRCManager::getChannelFromName(target)); + } + if (!user->getRegistered()) + { + IRCManager::delUser(user); + } +} diff --git a/Quit.hpp b/Quit.hpp new file mode 100644 index 0000000..b07bbb3 --- /dev/null +++ b/Quit.hpp @@ -0,0 +1,20 @@ +#ifndef QUIT_HPP +#define QUIT_HPP + +#include "../ICommand.hpp" +#include + + +class Quit : public ICommand +{ + private: + std::string reason; + public: + Quit(); + ~Quit(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif + diff --git a/Topic.cpp b/Topic.cpp new file mode 100644 index 0000000..c30dd8f --- /dev/null +++ b/Topic.cpp @@ -0,0 +1,45 @@ +#include "Topic.hpp" +#include "../IRC.hpp" +#include + +bool Topic::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + + leng = msg.length(); + pos = msg.find(":") + 1; + std::istringstream iss(msg); + std::string word; + + this->topic = msg.substr(pos, leng - pos); + iss >> word; // should be TOPIC + iss >> word; // should be the Channel you want to change + this->targetChannel = IRCManager::getChannelByName(word); + if (this->targetChannel) // Check if the channel exists + { + if (this->targetChannel->getUserChangeTopic()) // Check if a user has permission to change the topic + return (true); + if (this->targetChannel->checkOperator(user)) // Check if we have operator permissions in the channel + return (true); + } + return (false); +} + +int Topic::run(User &user, IRC::t_send_f &send) +{ + this->targetChannel->setTopic(this->topic); + std::istringstream iss(this->targetChannel->getUserList()); + std::string target; + iss >> target; + while (target[0]) + { + send(IRCManager::getUserFromName(target), user.getNickName() + "!~" + user.getUserName() + "@" + user.getHostName() + " TOPIC " + this->targetChannel->getChannelName() + " * :" + this->topic; + iss >> target; + } + return (0); +} + +//TOPIC #testtesttest :test123 + +//@time=2024-07-22T14:57:54.693Z :HoutwormNick!~HoutwormU@84-86-79-218.fixed.kpn.net TOPIC #testtesttest :test123 diff --git a/Topic.hpp b/Topic.hpp new file mode 100644 index 0000000..487eb94 --- /dev/null +++ b/Topic.hpp @@ -0,0 +1,19 @@ +#ifndef TOPIC_HPP +#define TOPIC_HPP + +#include "../ICommand.hpp" +#include + +class Topic : public ICommand +{ + private: + std::string topic; + Channel *targetChannel; + public: + Topic(); + ~Topic(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif diff --git a/UserCMD.cpp b/UserCMD.cpp new file mode 100644 index 0000000..f1ef0e1 --- /dev/null +++ b/UserCMD.cpp @@ -0,0 +1,67 @@ +#include "User.hpp" +#include "../User.hpp" +#include "../Connection.hpp" +#include "../IRC.hpp" +#include + + +UserCMD::UserCMD() {} + +UserCMD::~UserCMD() {} + +bool UserCMD::validate(const User &user, const std::string &msg) +{ + size_t pos; + size_t leng; + std::istringstream iss(msg); + std::string word; + + leng = msg.length(); + pos = msg.find(":") + 1; + this->realName = msg.substr(pos, leng - pos); + iss >> word; // should be USER + iss >> word; // should be the Nickname + this->nickName = word; + // perhaps we should check the real and username on length and illegal characters + return true; +} + +bool UserCMD::validate(const Connection &conn, const std::string &msg) +{ + size_t pos; + size_t leng; + std::istringstream iss(msg); + std::string word; + + leng = msg.length(); + pos = msg.find(":") + 1; + this->realName = msg.substr(pos, leng - pos); + iss >> word; // should be USER + iss >> word; // should be the Nickname + this->nickName = word; + return true; + // perhaps we should check the real and username on length and illegal characters +} + +int UserCMD::run(User &user, IRC::t_send_f &send) +{ + user->setUserName(this->userName); + user->setRealName(this->realName); + return (0); +} + +int UserCMD::run(Connection &conn, IRC::t_send_f &send) +{ + if (conn->getNickName()) // Nick was called before and we will create the user here + { + user = IRCManager::addUser(conn, this->userName, this->realName, conn->getNickName()); + user->setUserName(this->userName); + user->setRealName(this->realName); + } + else // User was called before Nick and User will be created in Nick + { + user->setUserName(this->userName); + user->setRealName(this->realName); + } + return (0); +} diff --git a/UserCMD.hpp b/UserCMD.hpp new file mode 100644 index 0000000..8c559bf --- /dev/null +++ b/UserCMD.hpp @@ -0,0 +1,22 @@ +#ifndef USERCMD_HPP +#define USERCMD_HPP + +#include "../ICommand.hpp" +#include "../IRC.hpp" +#include + +class UserCMD : public ICommand +{ + private: + std::string userName; + std::string realName; + public: + UserCMD(); + ~UserCMD(); + bool validate(const User &user, const std::string &msg); + bool validate(const Connection &conn, const std::string &message); + int run(User &user, IRC::t_send_f &send); + int run(Connection &conn, IRC::t_send_f &send); +}; + +#endif diff --git a/Utils.cpp b/Utils.cpp new file mode 100644 index 0000000..7fa51fa --- /dev/null +++ b/Utils.cpp @@ -0,0 +1,11 @@ +#include +#include +#include + +int main(void) +{ + std::time_t t = std::time(0); + std::tm* now = std::localtime(&t); + std::cout << std::setfill('0') << "@time=" << (now->tm_year + 1900) + "-" + std::setw(2) + (now->tm_mon + 1) + "-" + std::setw(2) + now->tm_mday + "T" + std::setw(2) + now->tm_hour + ":" + std::setw(2) + now->tm_min + ":" + std::setw(2) + now->tm_sec + "." + std::setw(3) + now->tm_msec + "Z"; + return(0); +} diff --git a/Who.cpp b/Who.cpp new file mode 100644 index 0000000..914ba1b --- /dev/null +++ b/Who.cpp @@ -0,0 +1,60 @@ +#include "Who.hpp" +#include "../IRC.hpp" +#include + +bool Who::validate(const User &user, const std::string &msg) +{ + std::istringstream iss(msg); + std::string word; + std::string current; + + iss >> word; // should be WHO + iss >> word; // should be the channel we want the userlist for + this->targetChannel = IRCManager::getChannelFromName(word); + if (this->targetChannel) + { + std::istringstream userList(this->targetChannel->getUserList()); + userList >> current; + while (current[0]) + { + if (user->getNickName() == current) + return (true); + userList >> current; + } + } + return (false); +} + +int Who::run(User &user, IRC::t_send_f &send) +{ + std::istringstream userList(this->targetChannel->getUserList()); + std::string current; + User userObj; + + send(user, ":" + IRCManager::getHostName() + " 324 " user->getNickName() + this->targetChannel->getChannelName() + "need to extract modes"; // better do this when I get Channel.hpp + send(user, ":" + IRCManager::getHostName() + " 329 " user->getNickName() + this->targetChannel->getChannelName() + "1621432263"; // not sure what this code is for, Maybe the age of the channel or something + userList >> current; + while (current[0]) + { + userObj = IRCManager::getUserFromName(current); + send(user, ":" + IRCManager::getHostName() + " 354 " user->getNickName() + " 152 " + this->targetChannel->getChannelName() + " ~" userObj->getUserName() + " " + userObj->getHostName() + " " + IRCManager::getHostName() + " " + userObj->getNickName " H 0 :" userObj->getRealName(); + userList >> current; + } + return (0); +} + + +//+n Disallows external messages. +//+t Only op/hops can set the topic. +//+p Sets the channel as invisible in /list. +//+s Sets the channel as invisible in /list and /whois. +//+i Sets the channel as closed unless the person was invited. +//+k [pass] Sets a password for the channel which users must enter to join. +//+l [number] Sets a limit on the number of users who are allowed in the channel at the same time. +//+m Prevents users who are not opped/hopped/voiced from talking. +//+R Sets the channel so only registered nicks are allowed in. +//+M Sets the channel so only registered nicks are allowed to talk. +//+S Strips formatting from messages, rendering them as plaintext. +//+c Blocks messages containing color codes. +//+i A user must be invited to join the channel. +//+N No nick changes permitted in the channel. diff --git a/Who.hpp b/Who.hpp new file mode 100644 index 0000000..4e3b055 --- /dev/null +++ b/Who.hpp @@ -0,0 +1,18 @@ +#ifndef WHO_HPP +#define WHO_HPP + +#include "../ICommand.hpp" +#include + +class Who : public ICommand +{ + private: + Channel *targetChannel; + public: + Who(); + ~Who(); + bool validate(const User &user, const std::string &msg); + int run(User &user, IRC::t_send_f &send); +}; + +#endif