xbot/registration.cpp

147 lines
3.5 KiB
C++
Raw Normal View History

2025-01-26 19:35:56 -08:00
#include "registration.hpp"
2023-11-25 09:22:55 -08:00
2023-11-27 19:09:45 -08:00
#include "connection.hpp"
#include "ircmsg.hpp"
2025-01-25 12:25:38 -08:00
#include "sasl_mechanism.hpp"
2023-11-27 19:09:45 -08:00
2023-11-25 20:09:20 -08:00
#include <memory>
#include <random>
2023-11-25 20:09:20 -08:00
#include <unordered_map>
2025-01-26 19:35:56 -08:00
Registration::Registration(
2025-01-25 12:25:38 -08:00
const Settings &settings,
std::shared_ptr<Client> client
2023-11-25 09:22:55 -08:00
)
: settings_{settings}
, client_{std::move(client)}
2023-11-27 14:12:20 -08:00
{
}
2023-11-25 09:22:55 -08:00
2025-01-26 19:35:56 -08:00
auto Registration::on_connect() -> void
2023-11-25 09:22:55 -08:00
{
2025-01-27 11:08:16 -08:00
client_->list_caps();
caps_slot_ = client_->sig_cap_ls.connect([self = shared_from_this()](auto &caps) {
self->on_cap_list(caps);
});
slot_ = client_->get_connection().sig_ircmsg.connect(
[self = shared_from_this()](const auto cmd, auto &msg)
{
self->on_ircmsg(cmd, msg);
}
);
2025-01-26 19:35:56 -08:00
2025-01-25 15:45:31 -08:00
if (not settings_.password.empty())
{
client_->get_connection().send_pass(settings_.password);
2025-01-25 15:45:31 -08:00
}
client_->get_connection().send_user(settings_.username, settings_.realname);
client_->get_connection().send_nick(settings_.nickname);
2023-11-25 09:22:55 -08:00
}
2025-01-27 11:08:16 -08:00
auto Registration::on_cap_list(const std::unordered_map<std::string, std::string> &caps) -> void
2023-11-25 09:22:55 -08:00
{
std::string request;
2025-01-27 11:08:16 -08:00
static const char * const want [] {
2023-11-25 20:09:20 -08:00
"account-notify",
2023-11-29 13:54:34 -08:00
"account-tag",
2023-11-25 20:09:20 -08:00
"batch",
"chghost",
2023-11-29 13:54:34 -08:00
"draft/chathistory",
"extended-join",
"invite-notify",
"server-time",
2023-11-25 20:09:20 -08:00
"setname",
2023-11-29 13:54:34 -08:00
"soju.im/no-implicit-names",
2023-11-25 20:09:20 -08:00
"solanum.chat/identify-msg",
2023-11-29 13:54:34 -08:00
"solanum.chat/oper",
2023-11-25 20:09:20 -08:00
"solanum.chat/realhost",
};
2025-01-25 15:45:31 -08:00
for (const auto cap : want)
2023-11-25 09:22:55 -08:00
{
if (caps.contains(cap))
{
request.append(cap);
request.push_back(' ');
}
}
2025-01-22 23:49:48 -08:00
2025-01-27 11:08:16 -08:00
bool do_sasl = not settings_.sasl_mechanism.empty() && caps.contains("sasl");
if (do_sasl) {
request.append("sasl ");
2023-11-25 09:22:55 -08:00
}
2023-11-27 14:12:20 -08:00
2025-01-27 11:08:16 -08:00
if (not request.empty())
2023-11-27 14:12:20 -08:00
{
2025-01-27 11:08:16 -08:00
request.pop_back(); // trailing space
client_->get_connection().send_cap_req(request);
2023-11-27 14:12:20 -08:00
}
2023-11-25 09:22:55 -08:00
2025-01-27 11:08:16 -08:00
if (do_sasl) {
client_->start_sasl(
std::make_unique<SaslPlain>(
settings_.sasl_authcid,
settings_.sasl_authzid,
settings_.sasl_password));
} else {
client_->get_connection().send_cap_end();
2023-11-25 09:22:55 -08:00
}
}
2025-01-26 19:35:56 -08:00
auto Registration::start(
2025-01-25 12:25:38 -08:00
const Settings &settings,
std::shared_ptr<Client> client
2025-01-26 19:35:56 -08:00
) -> std::shared_ptr<Registration>
2023-11-25 09:22:55 -08:00
{
const auto thread = std::make_shared<Registration>(std::move(settings), std::move(client));
2023-11-27 14:12:20 -08:00
thread->slot_ = thread->client_->get_connection().sig_connect.connect([thread]() {
2025-01-26 19:35:56 -08:00
thread->slot_.disconnect();
2023-11-27 14:12:20 -08:00
thread->on_connect();
});
return thread;
}
auto Registration::randomize_nick() -> void
2023-11-27 14:12:20 -08:00
{
std::string new_nick;
new_nick += settings_.nickname.substr(0, 8);
std::random_device rd;
std::mt19937 gen{rd()};
std::uniform_int_distribution<> distrib(0, 35);
for (int i = 0; i < 8; ++i) {
const auto x = distrib(gen);
new_nick += x < 10 ? '0' + x : 'A' + (x-10);
}
client_->get_connection().send_nick(new_nick);
2023-11-27 14:12:20 -08:00
}
auto Registration::on_ircmsg(const IrcCommand cmd, const IrcMsg &msg) -> void
2023-11-27 14:12:20 -08:00
{
switch (cmd)
{
default: break;
case IrcCommand::ERR_NICKNAMEINUSE:
2025-01-27 11:08:16 -08:00
case IrcCommand::ERR_ERRONEUSNICKNAME:
case IrcCommand::ERR_UNAVAILRESOURCE:
randomize_nick();
break;
case IrcCommand::RPL_WELCOME:
slot_.disconnect();
2025-01-27 11:08:16 -08:00
caps_slot_.disconnect();
break;
case IrcCommand::RPL_SASLSUCCESS:
case IrcCommand::ERR_SASLFAIL:
client_->get_connection().send_cap_end();
break;
}
2023-11-25 09:22:55 -08:00
}