2025-02-01 11:04:33 -08:00
|
|
|
#include "myirc/registration.hpp"
|
2023-11-25 09:22:55 -08:00
|
|
|
|
2025-02-01 11:04:33 -08:00
|
|
|
#include "myirc/connection.hpp"
|
|
|
|
#include "myirc/ircmsg.hpp"
|
2023-11-27 19:09:45 -08:00
|
|
|
|
2023-11-25 20:09:20 -08:00
|
|
|
#include <memory>
|
2025-01-27 09:30:09 -08:00
|
|
|
#include <random>
|
2023-11-25 20:09:20 -08:00
|
|
|
#include <unordered_map>
|
|
|
|
|
2025-02-01 11:04:33 -08:00
|
|
|
namespace myirc {
|
|
|
|
|
2025-01-26 19:35:56 -08:00
|
|
|
Registration::Registration(
|
2025-01-30 09:28:28 -08:00
|
|
|
Settings settings,
|
2025-01-27 09:30:09 -08:00
|
|
|
std::shared_ptr<Client> client
|
2023-11-25 09:22:55 -08:00
|
|
|
)
|
2025-01-30 09:28:28 -08:00
|
|
|
: settings_{std::move(settings)}
|
2025-01-27 09:30:09 -08:00
|
|
|
, 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 17:04:31 -08:00
|
|
|
auto &connection = client_->get_connection();
|
|
|
|
|
2025-01-27 11:08:16 -08:00
|
|
|
client_->list_caps();
|
|
|
|
caps_slot_ = client_->sig_cap_ls.connect([self = shared_from_this()](auto &caps) {
|
2025-01-27 17:04:31 -08:00
|
|
|
self->caps_slot_.disconnect();
|
2025-01-27 11:08:16 -08:00
|
|
|
self->on_cap_list(caps);
|
|
|
|
});
|
|
|
|
|
2025-01-27 17:04:31 -08:00
|
|
|
slot_ = connection.sig_ircmsg.connect(
|
2025-02-05 09:24:47 -08:00
|
|
|
[self = shared_from_this()](const auto cmd, auto &msg, auto)
|
2025-01-27 09:30:09 -08:00
|
|
|
{
|
|
|
|
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())
|
|
|
|
{
|
2025-02-05 09:24:47 -08:00
|
|
|
client_->send_pass(settings_.password);
|
2025-01-25 15:45:31 -08:00
|
|
|
}
|
2025-02-05 09:24:47 -08:00
|
|
|
client_->send_user(settings_.username, settings_.realname);
|
|
|
|
client_->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-31 09:36:08 -08:00
|
|
|
bool do_sasl = settings_.sasl_mechanism && caps.contains("sasl");
|
2025-01-27 11:08:16 -08:00
|
|
|
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
|
2025-02-05 09:24:47 -08:00
|
|
|
client_->send_cap_req(request);
|
2023-11-27 14:12:20 -08:00
|
|
|
}
|
2023-11-25 09:22:55 -08:00
|
|
|
|
2025-01-31 09:36:08 -08:00
|
|
|
if (do_sasl) {
|
|
|
|
client_->start_sasl(std::move(settings_.sasl_mechanism));
|
2025-01-27 11:08:16 -08:00
|
|
|
} else {
|
2025-02-05 09:24:47 -08:00
|
|
|
client_->send_cap_end();
|
2023-11-25 09:22:55 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-26 19:35:56 -08:00
|
|
|
auto Registration::start(
|
2025-01-30 09:28:28 -08:00
|
|
|
Settings settings,
|
2025-01-27 09:30:09 -08:00
|
|
|
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
|
|
|
{
|
2025-01-27 09:30:09 -08:00
|
|
|
const auto thread = std::make_shared<Registration>(std::move(settings), std::move(client));
|
2023-11-27 14:12:20 -08:00
|
|
|
|
2025-02-05 09:24:47 -08:00
|
|
|
thread->slot_ = thread->client_->get_connection().sig_connect.connect([thread](auto, auto, auto) {
|
2025-01-26 19:35:56 -08:00
|
|
|
thread->slot_.disconnect();
|
2023-11-27 14:12:20 -08:00
|
|
|
thread->on_connect();
|
|
|
|
});
|
|
|
|
|
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
2025-01-27 09:30:09 -08:00
|
|
|
auto Registration::randomize_nick() -> void
|
2023-11-27 14:12:20 -08:00
|
|
|
{
|
2025-01-27 09:30:09 -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);
|
|
|
|
}
|
|
|
|
|
2025-02-05 09:24:47 -08:00
|
|
|
client_->send_nick(new_nick);
|
2023-11-27 14:12:20 -08:00
|
|
|
}
|
|
|
|
|
2025-01-27 09:30:09 -08:00
|
|
|
auto Registration::on_ircmsg(const IrcCommand cmd, const IrcMsg &msg) -> void
|
2023-11-27 14:12:20 -08:00
|
|
|
{
|
2025-01-27 09:30:09 -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:
|
2025-01-27 09:30:09 -08:00
|
|
|
randomize_nick();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IrcCommand::RPL_WELCOME:
|
|
|
|
slot_.disconnect();
|
2025-01-27 11:08:16 -08:00
|
|
|
caps_slot_.disconnect();
|
2025-01-27 09:30:09 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IrcCommand::RPL_SASLSUCCESS:
|
|
|
|
case IrcCommand::ERR_SASLFAIL:
|
2025-02-05 09:24:47 -08:00
|
|
|
client_->send_cap_end();
|
2025-01-27 09:30:09 -08:00
|
|
|
break;
|
|
|
|
}
|
2023-11-25 09:22:55 -08:00
|
|
|
}
|
2025-02-01 11:04:33 -08:00
|
|
|
|
|
|
|
} // namespace myirc
|