Skip to content

Commit

Permalink
Merge pull request #54 from ArthanIRC/bot-registration
Browse files Browse the repository at this point in the history
feat: implement bot registration server side
  • Loading branch information
Thibrac authored Sep 13, 2024
2 parents ccef75d + a2eed61 commit d212988
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 28 deletions.
3 changes: 3 additions & 0 deletions include/Client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Client {
bool _invisible;
bool _away;
bool _awayNotify;
bool _bot;
std::string _awayMsg;

public:
Expand All @@ -49,12 +50,14 @@ class Client {
bool isAway();
bool isAwayNotify();
bool isInvisible();
bool isBot();
bool hasCapEndedEarly();
State getState() const;
void setState(State newState);
void setInvisible(bool state);
void setAway(bool state, std::string message);
void setAwayNotify(bool state);
void setBot(bool state);
void setCapEndedEarly();
void setNickname(std::string& nick);
void setUsername(std::string& username);
Expand Down
15 changes: 15 additions & 0 deletions include/Commands/BotCommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include "Command.hpp"

class BotCommand : public Command {
private:
std::string _key;

public:
BotCommand(std::string source, std::vector<std::string> params,
Client* client);
~BotCommand();

void run();
};
2 changes: 1 addition & 1 deletion include/Commands/KickCommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class KickCommand : public Command {
private:
Channel* _channel;
std::string _comment;
std::string _targetNickname;
Client* _target;
void checkParams(Client* client, std::vector<std::string> params);

public:
Expand Down
2 changes: 2 additions & 0 deletions include/Commands/ModeCommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class ModeCommand : public Command {
static modeMap initMap() {
modeMap m;
m['b'] = &ModeCommand::banMode;
m['B'] = &ModeCommand::botMode;
m['l'] = &ModeCommand::limitMode;
m['i'] = &ModeCommand::iModeDispatcher;
m['k'] = &ModeCommand::keyMode;
Expand All @@ -34,6 +35,7 @@ class ModeCommand : public Command {
void executeMode();
void invisibleMode(bool oper, size_t& p);
void banMode(bool oper, size_t& p);
void botMode(bool oper, size_t& p);
void limitMode(bool oper, size_t& p);
void inviteMode(bool oper, size_t& p);
void keyMode(bool oper, size_t& p);
Expand Down
3 changes: 3 additions & 0 deletions include/Replies.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,7 @@ class Replies : public Message {
static std::string RPL_SASLMECHS();
static std::string ERR_REGFAILED();
static std::string ERR_QUIT();
static std::string ERR_INVALIDBOTKEY(Client* client);
static std::string RPL_YOUREPRIVBOT(Client* client);
static std::string RPL_NEWCHAN(Client* client, std::string chanName);
};
2 changes: 2 additions & 0 deletions include/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Server {
std::string getChannelModes() const;
std::string getRplSupport1() const;
std::string getRplSupport2() const;
std::string getBotKey() const;
size_t getMaxClients() const;
std::set<Client*> getClientsSet(std::map<std::string, Channel*> channels,
Client* sender);
Expand All @@ -76,6 +77,7 @@ class Server {
Client* sender);
void sendMessageIfAway(std::map<std::string, Channel*> channels,
std::string message, Client* sender);
void notifyPrivBot(std::string chanName);

static Server& getInstance();

Expand Down
1 change: 1 addition & 0 deletions make/sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ SOURCES += ./src/Server.cpp
SOURCES += ./src/ServerSocket.cpp
SOURCES += ./src/Socket.cpp
SOURCES += ./src/Commands/AwayCommand.cpp
SOURCES += ./src/Commands/BotCommand.cpp
SOURCES += ./src/Commands/CapCommand.cpp
SOURCES += ./src/Commands/InviteCommand.cpp
SOURCES += ./src/Commands/JoinCommand.cpp
Expand Down
4 changes: 2 additions & 2 deletions src/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ bool Channel::isInChannel(Client* client) const {
}

bool Channel::isInvited(Client* client) const {
return isOnList(_inviteList, client);
return isOnList(_inviteList, client) || client->isServerOperator();
}

bool Channel::isBanned(Client* client) const {
return isOnList(_banList, client);
return isOnList(_banList, client) && !client->isServerOperator();
}

bool Channel::isOperator(Client* client) const {
Expand Down
6 changes: 6 additions & 0 deletions src/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ bool Client::isAwayNotify() { return this->_awayNotify; }

bool Client::isInvisible() { return this->_invisible; }

bool Client::isBot() { return this->_bot; }

void Client::setCapEndedEarly() { this->_capEndedEarly = true; }

void Client::setAway(bool state, string message) {
Expand All @@ -64,6 +66,8 @@ void Client::setAwayNotify(bool state) { this->_awayNotify = state; }

void Client::setInvisible(bool state) { this->_invisible = state; }

void Client::setBot(bool state) { this->_bot = state; }

void Client::setNickname(string& nick) { this->_nickname = nick; }

void Client::setUsername(string& username) { this->_username = username; }
Expand All @@ -81,6 +85,8 @@ string Client::getModes() {
modes += "o";
if (isInvisible())
modes += "i";
if (isBot())
modes += "B";
return modes;
}

Expand Down
3 changes: 3 additions & 0 deletions src/Command.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <string>

#include "AwayCommand.hpp"
#include "BotCommand.hpp"
#include "CapCommand.hpp"
#include "Command.hpp"
#include "InviteCommand.hpp"
Expand Down Expand Up @@ -32,6 +33,8 @@ Command* Command::create(string& data, Client* client) {

if (command == "AWAY")
return new AwayCommand(source, params, client);
else if (command == "BOT")
return new BotCommand(source, params, client);
else if (command == "CAP")
return new CapCommand(source, params, client);
else if (command == "INVITE")
Expand Down
57 changes: 57 additions & 0 deletions src/Commands/BotCommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "BotCommand.hpp"
#include "Client.hpp"
#include "Exception.hpp"
#include "JoinCommand.hpp"
#include <vector>

using std::map;
using std::string;
using std::vector;

BotCommand::BotCommand(string source, vector<string> params, Client* client) {
if (!client->isRegistered()) {
client->sendMessage(Replies::ERR_NOTREGISTERED());
throw ClientException();
}

if (params.empty()) {
client->sendMessage(Replies::ERR_NEEDMOREPARAMS(client, "BOT"));
throw ClientException();
}

this->_source = source;
this->_params = params;
this->_client = client;
this->_key = params[0];
}

BotCommand::~BotCommand() {}

void BotCommand::run() {
if (Server::getInstance().getBotKey() != _key) {
_client->sendMessage(Replies::ERR_INVALIDBOTKEY(_client));
return;
}

_client->setState(OPERATOR);
_client->setBot(true);
_client->sendMessage(Replies::RPL_YOUREOPER(_client));
string reply = ":" + Server::getInstance().getSource() + " MODE " +
_client->getNickname() + " +Bo";
_client->sendMessage(Message::create(reply));
_client->sendMessage(Replies::RPL_YOUREPRIVBOT(_client));

map<string, Channel*> channels = Server::getInstance().getChannels();
string chansToJoin;
for (map<string, Channel*>::iterator it = channels.begin();
it != channels.end(); it++) {
if (!chansToJoin.empty())
chansToJoin += ",";
chansToJoin += it->first;
}

vector<string> tmp;
tmp.push_back(chansToJoin);
JoinCommand j("", tmp, _client);
j.run();
}
3 changes: 2 additions & 1 deletion src/Commands/JoinCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ void JoinCommand::parseParams() {
} catch (Channel::WrongSyntaxChannelName&) {
break;
}
Server::getInstance().notifyPrivBot(chanName);
}
i++;
}
Expand Down Expand Up @@ -117,7 +118,7 @@ void JoinCommand::run() {
parseParams();

for (size_t i = 0; i < _channels.size(); i++) {
if (_channels[i]->isKeyed()) {
if (_channels[i]->isKeyed() && !_channels[i]->isOperator(_client)) {
if (i >= _keys.size() || _keys[i] != _channels[i]->getKey()) {
_client->sendMessage(
Replies::ERR_BADCHANNELKEY(_client, _channels[i]));
Expand Down
32 changes: 14 additions & 18 deletions src/Commands/KickCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void KickCommand::checkParams(Client* client, vector<string> params) {
}

Channel* chan;
this->_targetNickname = toLowerCase(params[1]);
string targetNickName = toLowerCase(params[1]);
string chanName = toLowerCase(params[0]);

try {
Expand All @@ -46,14 +46,21 @@ void KickCommand::checkParams(Client* client, vector<string> params) {
throw ClientException();
}

if (!chan->isOperator(client)) {
try {
this->_target = Server::getInstance().findClient(targetNickName);
} catch (Server::ClientNotFoundException&) {
_client->sendMessage(Replies::ERR_NOSUCHNICK(_client, targetNickName));
return;
}

if (!chan->isOperator(client) || chan->isOperator(_target)) {
client->sendMessage(Replies::ERR_CHANOPRIVSNEEDED(client, chan));
throw ClientException();
}

if (!chan->isInChannel(_targetNickname)) {
if (!chan->isInChannel(_target)) {
client->sendMessage(
Replies::ERR_USERNOTINCHANNEL(_client, _targetNickname, _channel));
Replies::ERR_USERNOTINCHANNEL(_client, targetNickName, _channel));
throw ClientException();
}

Expand All @@ -66,21 +73,10 @@ void KickCommand::checkParams(Client* client, vector<string> params) {
void KickCommand::run() {
string reply;
reply = ":" + _client->getSource() + " KICK " + _channel->getName() + " " +
_targetNickname + " " + _comment;
_target->getNickname() + " " + _comment;
Message::create(reply);
Client* target;

try {
target = Server::getInstance().findClient(_targetNickname);
} catch (Server::ClientNotFoundException&) {
_client->sendMessage(Replies::ERR_NOSUCHNICK(_client, _targetNickname));
return;
}

_channel->removeClient(target);
if (_channel->isOperator(target))
_channel->removeOperator(target);

target->sendMessage(reply);
_channel->removeClient(_target);
_target->sendMessage(reply);
Server::getInstance().sendMessage(_channel, reply, NULL);
}
9 changes: 9 additions & 0 deletions src/Commands/ModeCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ void ModeCommand::banMode(bool oper, size_t& p) {
addResult(oper, "b", param);
}

void ModeCommand::botMode(bool oper, size_t& p) {
_client->setBot(oper);
(void)p;
addResult(oper, "B", "");
}

void ModeCommand::limitMode(bool oper, size_t& p) {
if (!oper) {
_channel->setMaxClients(0);
Expand Down Expand Up @@ -267,6 +273,9 @@ void ModeCommand::executeMode() {
if (unknownFlag)
_client->sendMessage(Replies::ERR_UMODEUNKNOWNFLAG(_client));

if (_modeResult.empty())
return;

string message = ":" + _client->getNickname() + " MODE " + _params[0];
message += " " + _modeResult + _paramResult;
if (_isChan)
Expand Down
23 changes: 22 additions & 1 deletion src/Replies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ string Replies::RPL_WHOREPLY(Client* client, Client* target, Channel* channel) {
flags += "G";
else
flags += "H";
if (target->isBot())
flags += "B";
if (target->isServerOperator())
flags += "*";
if (channel) {
Expand Down Expand Up @@ -833,8 +835,27 @@ string Replies::ERR_REGFAILED() {
return Message::create(reply);
}

std::string Replies::ERR_QUIT() {
string Replies::ERR_QUIT() {
std::string reply;
reply = "ERROR :No hard feelings, goodbye.";
return Message::create(reply);
}

string Replies::ERR_INVALIDBOTKEY(Client* client) {
string reply;
reply = "909 " + client->getNickname() + " :Bot key is invalid";
return Message::create(reply);
}

string Replies::RPL_YOUREPRIVBOT(Client* client) {
string reply;
reply = "910 " + client->getNickname() + " :You are now a privileged bot";
return Message::create(reply);
}

string Replies::RPL_NEWCHAN(Client* client, string chanName) {
string reply;
reply =
"911 " + client->getNickname() + " " + chanName + " :has been created";
return Message::create(reply);
}
Loading

0 comments on commit d212988

Please sign in to comment.