179 lines
4.2 KiB
C++
179 lines
4.2 KiB
C++
#include "registration_thread.hpp"
|
|
|
|
#include <memory>
|
|
#include <unordered_set>
|
|
#include <unordered_map>
|
|
|
|
RegistrationThread::RegistrationThread(
|
|
Connection& connection,
|
|
std::string password,
|
|
std::string username,
|
|
std::string realname,
|
|
std::string nickname
|
|
)
|
|
: connection_{connection}
|
|
, password_{password}
|
|
, username_{username}
|
|
, realname_{realname}
|
|
, nickname_{nickname}
|
|
{
|
|
}
|
|
|
|
auto RegistrationThread::on_connect() -> void
|
|
{
|
|
send_cap_ls(connection_);
|
|
send_pass(connection_, password_);
|
|
send_user(connection_, username_, realname_);
|
|
send_nick(connection_, nickname_);
|
|
|
|
connection_.remove_listener(connect_handle_);
|
|
}
|
|
|
|
auto RegistrationThread::send_req() -> void
|
|
{
|
|
std::string request;
|
|
char const* const want[] = {
|
|
"extended-join",
|
|
"account-notify",
|
|
"draft/chathistory",
|
|
"batch",
|
|
"soju.im/no-implicit-names",
|
|
"chghost",
|
|
"setname",
|
|
"account-tag",
|
|
"solanum.chat/oper",
|
|
"solanum.chat/identify-msg",
|
|
"solanum.chat/realhost",
|
|
"server-time",
|
|
"invite-notify",
|
|
"extended-join"
|
|
};
|
|
|
|
for (auto cap : want)
|
|
{
|
|
if (caps.contains(cap))
|
|
{
|
|
request.append(cap);
|
|
request.push_back(' ');
|
|
outstanding.insert(cap);
|
|
}
|
|
}
|
|
|
|
connection_.remove_listener(message_handle_);
|
|
|
|
if (not outstanding.empty())
|
|
{
|
|
request.pop_back();
|
|
send_cap_req(connection_, request);
|
|
|
|
listen_for_cap_ack();
|
|
}
|
|
else
|
|
{
|
|
send_cap_end(connection_);
|
|
}
|
|
}
|
|
|
|
auto RegistrationThread::on_msg_cap_ack(IrcMsg const& msg) -> void
|
|
{
|
|
auto in = std::istringstream{std::string{msg.args[2]}};
|
|
std::for_each(
|
|
std::istream_iterator<std::string>{in},
|
|
std::istream_iterator<std::string>{},
|
|
[this](std::string x) {
|
|
outstanding.erase(x);
|
|
}
|
|
);
|
|
if (outstanding.empty())
|
|
{
|
|
send_cap_end(connection_);
|
|
connection_.remove_listener(message_handle_);
|
|
}
|
|
}
|
|
|
|
auto RegistrationThread::on_msg_cap_ls(IrcMsg const& msg) -> void
|
|
{
|
|
std::string_view const* kvs;
|
|
bool last;
|
|
|
|
if (3 == msg.args.size())
|
|
{
|
|
kvs = &msg.args[2];
|
|
last = true;
|
|
}
|
|
else if (4 == msg.args.size() && "*" == msg.args[2])
|
|
{
|
|
kvs = &msg.args[3];
|
|
last = false;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto in = std::istringstream{std::string{*kvs}};
|
|
|
|
std::for_each(
|
|
std::istream_iterator<std::string>{in},
|
|
std::istream_iterator<std::string>{},
|
|
[this](std::string x) {
|
|
auto const eq = x.find('=');
|
|
if (eq == x.npos)
|
|
{
|
|
caps.emplace(x, std::string{});
|
|
}
|
|
else
|
|
{
|
|
caps.emplace(std::string{x, 0, eq}, std::string{x, eq+1, x.npos});
|
|
}
|
|
}
|
|
);
|
|
|
|
if (last)
|
|
{
|
|
send_req();
|
|
}
|
|
}
|
|
|
|
auto RegistrationThread::start(
|
|
Connection& connection,
|
|
std::string password,
|
|
std::string username,
|
|
std::string realname,
|
|
std::string nickname
|
|
) -> std::shared_ptr<RegistrationThread>
|
|
{
|
|
auto const thread = std::make_shared<RegistrationThread>(connection, password, username, realname, nickname);
|
|
|
|
thread->listen_for_cap_ls();
|
|
|
|
thread->connect_handle_ = connection.add_listener<ConnectEvent>([thread](ConnectEvent const&)
|
|
{
|
|
thread->on_connect();
|
|
});
|
|
|
|
return thread;
|
|
}
|
|
|
|
auto RegistrationThread::listen_for_cap_ack() -> void
|
|
{
|
|
message_handle_ = connection_.add_listener<IrcMsgEvent>([thread = shared_from_this()](IrcMsgEvent const& event)
|
|
{
|
|
if (IrcCommand::CAP == event.command && event.irc.args.size() >= 2 && "*" == event.irc.args[0] && "ACK" == event.irc.args[1])
|
|
{
|
|
thread->on_msg_cap_ack(event.irc);
|
|
}
|
|
});
|
|
}
|
|
|
|
auto RegistrationThread::listen_for_cap_ls() -> void
|
|
{
|
|
message_handle_ = connection_.add_listener<IrcMsgEvent>([thread = shared_from_this()](IrcMsgEvent const& event)
|
|
{
|
|
if (IrcCommand::CAP == event.command && event.irc.args.size() >= 2 && "*" == event.irc.args[0] && "LS" == event.irc.args[1])
|
|
{
|
|
thread->on_msg_cap_ls(event.irc);
|
|
}
|
|
});
|
|
}
|