#include "self_thread.hpp" #include #include "connection.hpp" #include "ircmsg.hpp" #include "irc_parse_thread.hpp" auto SelfThread::start(Connection& connection) -> std::shared_ptr { auto thread = std::make_shared(connection); connection.add_listener([thread](IrcMsgEvent& event) { switch (event.command) { // Learn nickname from 001 case IrcCommand::RPL_WELCOME: if (event.irc.args.size() < 1) { BOOST_LOG_TRIVIAL(debug) << "RPL_WELCOME has too few arguments"; break; } thread->nickname_ = event.irc.args[0]; break; // Track changes to our nickname case IrcCommand::NICK: { if (event.irc.args.size() < 1) { BOOST_LOG_TRIVIAL(debug) << "NICK has too few arguments"; break; } if (thread->is_my_mask(event.irc.source)) { thread->nickname_ = event.irc.args[0]; } break; } // Re-establish user modes case IrcCommand::RPL_UMODEIS: if (event.irc.args.size() < 1) { BOOST_LOG_TRIVIAL(debug) << "RPL_UMODEIS has too few arguments"; break; } thread->mode_ = event.irc.args[1]; break; case IrcCommand::JOIN: { if (event.irc.args.size() < 1) { BOOST_LOG_TRIVIAL(debug) << "JOIN has too few arguments"; break; } if (thread->is_my_mask(event.irc.source)) { thread->channels_.insert(std::string{event.irc.args[0]}); } break; } case IrcCommand::KICK: { if (event.irc.args.size() < 2) { BOOST_LOG_TRIVIAL(debug) << "PART has too few arguments"; break; } if (thread->is_my_nick(event.irc.args[1])) { thread->channels_.erase(std::string{event.irc.args[0]}); } break; } case IrcCommand::PART: { if (event.irc.args.size() < 1) { BOOST_LOG_TRIVIAL(debug) << "PART has too few arguments"; break; } if (thread->is_my_mask(event.irc.source)) { thread->channels_.erase(std::string{event.irc.args[0]}); } break; } // Interpret self mode changes case IrcCommand::MODE: if (event.irc.args.size() < 2) { BOOST_LOG_TRIVIAL(debug) << "MODE has too few arguments"; break; } if (thread->is_my_nick(event.irc.args[0])) { auto polarity = true; for (char const c : event.irc.args[1]) { switch (c) { case '+': polarity = true; break; case '-': polarity = false; break; default: if (polarity) { thread->mode_ += c; } else { auto const ix = thread->mode_.find(c); if (ix != std::string::npos) { thread->mode_.erase(ix, 1); } } break; } } } default: break; } }); return thread; } auto SelfThread::get_my_nickname() const -> std::string const& { return nickname_; } auto SelfThread::get_my_mode() const -> std::string const& { return mode_; } auto SelfThread::get_my_channels() const -> std::unordered_set const& { return channels_; } auto SelfThread::is_my_nick(std::string_view nick) const -> bool { return nick == nickname_; } auto SelfThread::is_my_mask(std::string_view mask) const -> bool { auto const bang = mask.find('!'); return bang != std::string_view::npos && nickname_ == mask.substr(0, bang); }