diff --git a/CMakeLists.txt b/CMakeLists.txt index 75b2506..789f6f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,6 @@ add_executable(xbot main.cpp irc_commands.inc ircmsg.cpp settings.cpp connection.cpp thread.cpp snote_thread.cpp watchdog_thread.cpp write_irc.cpp ping_thread.cpp irc_parse_thread.cpp registration_thread.cpp - self_thread.cpp) + self_thread.cpp command_thread.cpp) target_include_directories(xbot PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(xbot PRIVATE Boost::headers tomlplusplus_tomlplusplus eventpp) diff --git a/command_thread.cpp b/command_thread.cpp new file mode 100644 index 0000000..5b2999e --- /dev/null +++ b/command_thread.cpp @@ -0,0 +1,52 @@ +#include "command_thread.hpp" + +#include "connection.hpp" +#include "irc_parse_thread.hpp" +#include +auto CommandThread::start(Connection& connection) -> void +{ + connection.add_listener([&connection](IrcMsgEvent& event) + { + if (IrcCommand::PRIVMSG != event.command) return; + auto const message = event.irc.args[1]; + if (message.empty()) return; + if ('!' != message.front()) return; + + CommandEvent command_event; + + { + auto const cmdend = message.find(' '); + if (std::string_view::npos == cmdend) + { + command_event.command = message.substr(1); + } + else + { + command_event.command = message.substr(1, cmdend - 1); + command_event.arg = message.substr(cmdend + 1); + } + } + + { + auto const nickend = event.irc.source.find('!'); + if (std::string_view::npos != nickend) + { + command_event.nick = event.irc.source.substr(0, nickend); + } + } + + for (auto const& [k,v] : event.irc.tags) + { + if ("solanum.chat/oper" == k) + { + command_event.oper = v; + } + else if ("account" == k) + { + command_event.account = v; + } + } + + connection.dispatch(command_event); + }); +} diff --git a/command_thread.hpp b/command_thread.hpp new file mode 100644 index 0000000..1a9569e --- /dev/null +++ b/command_thread.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "thread.hpp" + +#include + +class Connection; + +struct CommandEvent : Event +{ + std::string_view oper; + std::string_view account; + std::string_view nick; + std::string_view command; + std::string_view arg; +}; + +struct CommandThread +{ + static auto start(Connection&) -> void; +}; \ No newline at end of file diff --git a/connection.cpp b/connection.cpp index 16299a2..dae0625 100644 --- a/connection.cpp +++ b/connection.cpp @@ -88,8 +88,9 @@ auto Connection::connect( make_event(); } -auto Connection::write_raw(std::string message) -> void +auto Connection::write_line(std::string message) -> void { + message += "\r\n"; auto const need_cancel = write_strings_.empty(); write_strings_.push_back(std::move(message)); if (need_cancel) diff --git a/connection.hpp b/connection.hpp index 83ab78d..a735224 100644 --- a/connection.hpp +++ b/connection.hpp @@ -97,7 +97,7 @@ public: } /// Write bytes into the socket. Messages should be properly newline terminated. - auto write_raw(std::string message) -> void; + auto write_line(std::string message) -> void; auto connect( boost::asio::io_context & io, diff --git a/irc_commands.hpp b/irc_commands.hpp new file mode 100644 index 0000000..15bbb0e --- /dev/null +++ b/irc_commands.hpp @@ -0,0 +1,857 @@ +/* C++ code produced by gperf version 3.1 */ +/* Command-line: /usr/local/bin/gperf -IC -Z IrcCommandHash -K text -L C++ --output-file irc_commands.hpp -t irc_commands.gperf */ +/* Computed positions: -k'1-3' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "irc_commands.gperf" +struct RecognizedCommand { + char * text; + IrcCommand command; +}; +#include + +#define TOTAL_KEYWORDS 270 +#define MIN_WORD_LENGTH 3 +#define MAX_WORD_LENGTH 12 +#define MIN_HASH_VALUE 4 +#define MAX_HASH_VALUE 906 +/* maximum key range = 903, duplicates = 0 */ + +class IrcCommandHash +{ +private: + static inline unsigned int hash (const char *str, size_t len); +public: + static const struct RecognizedCommand *in_word_set (const char *str, size_t len); +}; + +inline unsigned int +IrcCommandHash::hash (const char *str, size_t len) +{ + static const unsigned short asso_values[] = + { + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 55, 235, + 203, 333, 93, 388, 35, 51, 15, 5, 0, 205, + 20, 85, 98, 10, 100, 3, 435, 165, 500, 106, + 493, 211, 30, 0, 907, 0, 907, 907, 907, 0, + 20, 5, 5, 10, 0, 25, 0, 0, 907, 907, + 0, 907, 0, 907, 0, 907, 0, 907, 20, 0, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, + 907, 907, 907, 907, 907, 907, 907, 907, 907, 907 + }; + return len + asso_values[static_cast(str[2]+14)] + asso_values[static_cast(str[1])] + asso_values[static_cast(str[0]+6)]; +} + +const struct RecognizedCommand * +IrcCommandHash::in_word_set (const char *str, size_t len) +{ + static const struct RecognizedCommand wordlist[] = + { + {""}, {""}, {""}, {""}, +#line 272 "irc_commands.gperf" + {"PING", IrcCommand::PING}, +#line 275 "irc_commands.gperf" + {"TOPIC", IrcCommand::TOPIC}, +#line 264 "irc_commands.gperf" + {"CAP", IrcCommand::CAP}, +#line 271 "irc_commands.gperf" + {"PART", IrcCommand::PART}, + {""}, +#line 269 "irc_commands.gperf" + {"NICK", IrcCommand::NICK}, +#line 265 "irc_commands.gperf" + {"ERROR", IrcCommand::ERROR}, + {""}, +#line 273 "irc_commands.gperf" + {"PRIVMSG", IrcCommand::PRIVMSG}, + {""}, +#line 267 "irc_commands.gperf" + {"KICK", IrcCommand::KICK}, + {""}, +#line 133 "irc_commands.gperf" + {"393", IrcCommand::RPL_USERS}, + {""}, +#line 199 "irc_commands.gperf" + {"491", IrcCommand::ERR_NOOPERHOST}, +#line 268 "irc_commands.gperf" + {"MODE", IrcCommand::MODE}, + {""}, +#line 194 "irc_commands.gperf" + {"483", IrcCommand::ERR_CANTKILLSERVER}, + {""}, +#line 131 "irc_commands.gperf" + {"391", IrcCommand::RPL_TIME}, +#line 266 "irc_commands.gperf" + {"JOIN", IrcCommand::JOIN}, + {""}, +#line 270 "irc_commands.gperf" + {"NOTICE", IrcCommand::NOTICE}, + {""}, +#line 192 "irc_commands.gperf" + {"481", IrcCommand::ERR_NOPRIVILEGES}, +#line 274 "irc_commands.gperf" + {"QUIT", IrcCommand::QUIT}, + {""}, {""}, {""}, +#line 126 "irc_commands.gperf" + {"381", IrcCommand::RPL_YOUREOPER}, + {""}, {""}, {""}, +#line 263 "irc_commands.gperf" + {"BOUNCER", IrcCommand::BOUNCER}, +#line 211 "irc_commands.gperf" + {"691", IrcCommand::ERR_STARTTLS}, + {""}, {""}, +#line 176 "irc_commands.gperf" + {"463", IrcCommand::ERR_NOPERMFORHOST}, + {""}, +#line 66 "irc_commands.gperf" + {"281", IrcCommand::RPL_ACCEPTLIST}, + {""}, {""}, +#line 114 "irc_commands.gperf" + {"363", IrcCommand::RPL_CLOSEEND}, + {""}, +#line 174 "irc_commands.gperf" + {"461", IrcCommand::ERR_NEEDMOREPARAMS}, + {""}, {""}, {""}, {""}, +#line 112 "irc_commands.gperf" + {"361", IrcCommand::RPL_KILLDONE}, + {""}, {""}, +#line 61 "irc_commands.gperf" + {"263", IrcCommand::RPL_LOAD2HI}, +#line 184 "irc_commands.gperf" + {"473", IrcCommand::ERR_INVITEONLYCHAN}, +#line 262 "irc_commands.gperf" + {"BATCH", IrcCommand::BATCH}, + {""}, {""}, +#line 139 "irc_commands.gperf" + {"403", IrcCommand::ERR_NOSUCHCHANNEL}, +#line 121 "irc_commands.gperf" + {"373", IrcCommand::RPL_INFOSTART}, +#line 59 "irc_commands.gperf" + {"261", IrcCommand::RPL_TRACELOG}, +#line 182 "irc_commands.gperf" + {"471", IrcCommand::ERR_CHANNELISFULL}, + {""}, +#line 71 "irc_commands.gperf" + {"303", IrcCommand::RPL_ISON}, + {""}, +#line 137 "irc_commands.gperf" + {"401", IrcCommand::ERR_NOSUCHNICK}, +#line 119 "irc_commands.gperf" + {"371", IrcCommand::RPL_INFO}, + {""}, +#line 254 "irc_commands.gperf" + {"903", IrcCommand::RPL_SASLSUCCESS}, + {""}, +#line 69 "irc_commands.gperf" + {"301", IrcCommand::RPL_AWAY}, + {""}, {""}, +#line 20 "irc_commands.gperf" + {"203", IrcCommand::RPL_TRACEUNKNOWN}, + {""}, +#line 252 "irc_commands.gperf" + {"901", IrcCommand::RPL_LOGGEDOUT}, + {""}, {""}, {""}, {""}, +#line 18 "irc_commands.gperf" + {"201", IrcCommand::RPL_TRACECONNECTING}, +#line 210 "irc_commands.gperf" + {"671", IrcCommand::RPL_WHOISSECURE}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, +#line 8 "irc_commands.gperf" + {"003", IrcCommand::RPL_CREATED}, + {""}, {""}, +#line 166 "irc_commands.gperf" + {"443", IrcCommand::ERR_USERONCHANNEL}, + {""}, {""}, {""}, +#line 6 "irc_commands.gperf" + {"001", IrcCommand::RPL_WELCOME}, + {""}, {""}, +#line 164 "irc_commands.gperf" + {"441", IrcCommand::ERR_USERNOTINCHANNEL}, + {""}, +#line 200 "irc_commands.gperf" + {"492", IrcCommand::ERR_CANNOTSENDTOUSER}, + {""}, {""}, +#line 99 "irc_commands.gperf" + {"341", IrcCommand::RPL_INVITING}, + {""}, +#line 132 "irc_commands.gperf" + {"392", IrcCommand::RPL_USERSSTART}, +#line 43 "irc_commands.gperf" + {"243", IrcCommand::RPL_STATSOLINE}, + {""}, +#line 191 "irc_commands.gperf" + {"480", IrcCommand::ERR_THROTTLE}, + {""}, +#line 193 "irc_commands.gperf" + {"482", IrcCommand::ERR_CHANOPRIVSNEEDED}, + {""}, {""}, +#line 41 "irc_commands.gperf" + {"241", IrcCommand::RPL_STATSLLINE}, + {""}, +#line 127 "irc_commands.gperf" + {"382", IrcCommand::RPL_REHASHING}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 67 "irc_commands.gperf" + {"282", IrcCommand::RPL_ENDOFACCEPT}, +#line 16 "irc_commands.gperf" + {"043", IrcCommand::RPL_SAVENICK}, + {""}, {""}, {""}, +#line 175 "irc_commands.gperf" + {"462", IrcCommand::ERR_ALREADYREGISTRED}, + {""}, {""}, +#line 110 "irc_commands.gperf" + {"360", IrcCommand::RPL_WHOWASREAL}, + {""}, +#line 113 "irc_commands.gperf" + {"362", IrcCommand::RPL_CLOSING}, +#line 180 "irc_commands.gperf" + {"467", IrcCommand::ERR_KEYSET}, + {""}, +#line 213 "irc_commands.gperf" + {"703", IrcCommand::RPL_ENDOFMODLIST}, + {""}, {""}, +#line 117 "irc_commands.gperf" + {"367", IrcCommand::RPL_BANLIST}, + {""}, {""}, +#line 181 "irc_commands.gperf" + {"470", IrcCommand::ERR_LINKCHANNEL}, +#line 60 "irc_commands.gperf" + {"262", IrcCommand::RPL_ENDOFTRACE}, +#line 183 "irc_commands.gperf" + {"472", IrcCommand::ERR_UNKNOWNMODE}, + {""}, {""}, {""}, +#line 138 "irc_commands.gperf" + {"402", IrcCommand::ERR_NOSUCHSERVER}, +#line 120 "irc_commands.gperf" + {"372", IrcCommand::RPL_MOTD}, +#line 188 "irc_commands.gperf" + {"477", IrcCommand::ERR_NEEDREGGEDNICK}, +#line 68 "irc_commands.gperf" + {"300", IrcCommand::RPL_NONE}, + {""}, +#line 70 "irc_commands.gperf" + {"302", IrcCommand::RPL_USERHOST}, +#line 143 "irc_commands.gperf" + {"407", IrcCommand::ERR_TOOMANYTARGETS}, + {""}, +#line 251 "irc_commands.gperf" + {"900", IrcCommand::RPL_LOGGEDIN}, +#line 64 "irc_commands.gperf" + {"270", IrcCommand::RPL_PRIVS}, +#line 253 "irc_commands.gperf" + {"902", IrcCommand::ERR_NICKLOCKED}, + {""}, {""}, +#line 17 "irc_commands.gperf" + {"200", IrcCommand::RPL_TRACELINK}, +#line 209 "irc_commands.gperf" + {"670", IrcCommand::RPL_STARTTLS}, +#line 19 "irc_commands.gperf" + {"202", IrcCommand::RPL_TRACEHANDSHAKE}, +#line 258 "irc_commands.gperf" + {"907", IrcCommand::ERR_SASLALREADY}, + {""}, {""}, {""}, +#line 135 "irc_commands.gperf" + {"395", IrcCommand::RPL_NOUSERS}, + {""}, {""}, {""}, {""}, +#line 196 "irc_commands.gperf" + {"485", IrcCommand::ERR_BANNEDNICK}, +#line 247 "irc_commands.gperf" + {"743", IrcCommand::ERR_INVALIDBAN}, + {""}, {""}, {""}, +#line 129 "irc_commands.gperf" + {"385", IrcCommand::RPL_NOTOPERANYMORE}, + {""}, {""}, +#line 245 "irc_commands.gperf" + {"741", IrcCommand::RPL_ENDOFRSACHALLENGE2}, + {""}, +#line 7 "irc_commands.gperf" + {"002", IrcCommand::RPL_YOURHOST}, +#line 163 "irc_commands.gperf" + {"440", IrcCommand::ERR_SERVICESDOWN}, + {""}, +#line 165 "irc_commands.gperf" + {"442", IrcCommand::ERR_NOTONCHANNEL}, + {""}, {""}, {""}, {""}, +#line 100 "irc_commands.gperf" + {"342", IrcCommand::RPL_SUMMONING}, + {""}, +#line 178 "irc_commands.gperf" + {"465", IrcCommand::ERR_YOUREBANNEDCREEP}, + {""}, {""}, {""}, +#line 102 "irc_commands.gperf" + {"347", IrcCommand::RPL_ENDOFINVITELIST}, +#line 116 "irc_commands.gperf" + {"365", IrcCommand::RPL_ENDOFLINKS}, +#line 154 "irc_commands.gperf" + {"423", IrcCommand::ERR_NOADMININFO}, + {""}, +#line 42 "irc_commands.gperf" + {"242", IrcCommand::RPL_STATSUPTIME}, + {""}, {""}, +#line 88 "irc_commands.gperf" + {"323", IrcCommand::RPL_LISTEND}, +#line 261 "irc_commands.gperf" + {"AWAY", IrcCommand::AWAY}, +#line 152 "irc_commands.gperf" + {"421", IrcCommand::ERR_UNKNOWNCOMMAND}, +#line 46 "irc_commands.gperf" + {"247", IrcCommand::RPL_STATSXLINE}, +#line 62 "irc_commands.gperf" + {"265", IrcCommand::RPL_LOCALUSERS}, +#line 186 "irc_commands.gperf" + {"475", IrcCommand::ERR_BADCHANNELKEY}, + {""}, +#line 86 "irc_commands.gperf" + {"321", IrcCommand::RPL_LISTSTART}, + {""}, +#line 141 "irc_commands.gperf" + {"405", IrcCommand::ERR_TOOMANYCHANNELS}, +#line 123 "irc_commands.gperf" + {"375", IrcCommand::RPL_MOTDSTART}, + {""}, {""}, {""}, +#line 73 "irc_commands.gperf" + {"305", IrcCommand::RPL_UNAWAY}, +#line 198 "irc_commands.gperf" + {"489", IrcCommand::ERR_VOICENEEDED}, + {""}, +#line 36 "irc_commands.gperf" + {"221", IrcCommand::RPL_UMODEIS}, + {""}, +#line 256 "irc_commands.gperf" + {"905", IrcCommand::ERR_SASLTOOLONG}, + {""}, {""}, {""}, {""}, +#line 22 "irc_commands.gperf" + {"205", IrcCommand::RPL_TRACEUSER}, + {""}, {""}, +#line 148 "irc_commands.gperf" + {"413", IrcCommand::ERR_NOTOPLEVEL}, + {""}, +#line 212 "irc_commands.gperf" + {"702", IrcCommand::RPL_MODLIST}, + {""}, {""}, +#line 78 "irc_commands.gperf" + {"313", IrcCommand::RPL_WHOISOPERATOR}, + {""}, +#line 146 "irc_commands.gperf" + {"411", IrcCommand::ERR_NORECIPIENT}, +#line 217 "irc_commands.gperf" + {"707", IrcCommand::ERR_TARGCHANGE}, + {""}, {""}, {""}, +#line 76 "irc_commands.gperf" + {"311", IrcCommand::RPL_WHOISUSER}, +#line 80 "irc_commands.gperf" + {"369", IrcCommand::RPL_ENDOFWHOWAS}, + {""}, +#line 28 "irc_commands.gperf" + {"213", IrcCommand::RPL_STATSCLINE}, + {""}, +#line 10 "irc_commands.gperf" + {"005", IrcCommand::RPL_ISUPPORT}, + {""}, {""}, +#line 168 "irc_commands.gperf" + {"445", IrcCommand::ERR_SUMMONDISABLED}, + {""}, +#line 26 "irc_commands.gperf" + {"211", IrcCommand::RPL_STATSLINKINFO}, + {""}, +#line 190 "irc_commands.gperf" + {"479", IrcCommand::ERR_BADCHANNAME}, +#line 204 "irc_commands.gperf" + {"503", IrcCommand::ERR_GHOSTEDCLIENT}, + {""}, +#line 260 "irc_commands.gperf" + {"AUTHENTICATE", IrcCommand::AUTHENTICATE}, +#line 144 "irc_commands.gperf" + {"409", IrcCommand::ERR_NOORIGIN}, + {""}, {""}, {""}, +#line 202 "irc_commands.gperf" + {"501", IrcCommand::ERR_UMODEUNKNOWNFLAG}, + {""}, {""}, +#line 45 "irc_commands.gperf" + {"245", IrcCommand::RPL_STATSSLINE}, + {""}, {""}, +#line 244 "irc_commands.gperf" + {"740", IrcCommand::RPL_RSACHALLENGE2}, + {""}, +#line 246 "irc_commands.gperf" + {"742", IrcCommand::ERR_MLOCKRESTRICTE}, + {""}, {""}, +#line 25 "irc_commands.gperf" + {"209", IrcCommand::RPL_TRACECLASS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 232 "irc_commands.gperf" + {"723", IrcCommand::ERR_NOPRIVS}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 230 "irc_commands.gperf" + {"721", IrcCommand::RPL_OMOTD}, + {""}, {""}, {""}, {""}, +#line 153 "irc_commands.gperf" + {"422", IrcCommand::ERR_NOMOTD}, + {""}, +#line 215 "irc_commands.gperf" + {"705", IrcCommand::RPL_HELPTXT}, +#line 85 "irc_commands.gperf" + {"320", IrcCommand::RPL_WHOISSPECIAL}, + {""}, +#line 87 "irc_commands.gperf" + {"322", IrcCommand::RPL_LIST}, +#line 104 "irc_commands.gperf" + {"349", IrcCommand::RPL_ENDOFEXCEPTLIST}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 35 "irc_commands.gperf" + {"220", IrcCommand::RPL_STATSPLINE}, + {""}, {""}, +#line 48 "irc_commands.gperf" + {"249", IrcCommand::RPL_STATSDEBUG}, + {""}, {""}, {""}, +#line 223 "irc_commands.gperf" + {"713", IrcCommand::ERR_CHANOPEN}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 221 "irc_commands.gperf" + {"711", IrcCommand::RPL_KNOCKDLVR}, + {""}, {""}, +#line 145 "irc_commands.gperf" + {"410", IrcCommand::ERR_INVALIDCAPCMD}, + {""}, +#line 147 "irc_commands.gperf" + {"412", IrcCommand::ERR_NOTEXTTOSEND}, +#line 158 "irc_commands.gperf" + {"433", IrcCommand::ERR_NICKNAMEINUSE}, + {""}, +#line 75 "irc_commands.gperf" + {"310", IrcCommand::RPL_WHOISHELPOP}, + {""}, +#line 77 "irc_commands.gperf" + {"312", IrcCommand::RPL_WHOISSERVER}, +#line 96 "irc_commands.gperf" + {"333", IrcCommand::RPL_TOPICWHOTIME}, + {""}, +#line 156 "irc_commands.gperf" + {"431", IrcCommand::ERR_NONICKNAMEGIVEN}, + {""}, {""}, +#line 82 "irc_commands.gperf" + {"317", IrcCommand::RPL_WHOISIDLE}, + {""}, +#line 94 "irc_commands.gperf" + {"331", IrcCommand::RPL_NOTOPIC}, + {""}, +#line 27 "irc_commands.gperf" + {"212", IrcCommand::RPL_STATSCOMMANDS}, +#line 219 "irc_commands.gperf" + {"709", IrcCommand::RPL_ETRACE}, + {""}, {""}, {""}, {""}, +#line 32 "irc_commands.gperf" + {"217", IrcCommand::RPL_STATSQLINE}, + {""}, {""}, {""}, +#line 203 "irc_commands.gperf" + {"502", IrcCommand::ERR_USERSDONTMATCH}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 12 "irc_commands.gperf" + {"010", IrcCommand::RPL_REDIR}, + {""}, {""}, {""}, {""}, +#line 90 "irc_commands.gperf" + {"325", IrcCommand::RPL_CHANNELMLOCK}, + {""}, {""}, +#line 15 "irc_commands.gperf" + {"017", IrcCommand::RPL_MAPEND}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 38 "irc_commands.gperf" + {"225", IrcCommand::RPL_STATSDLINE}, + {""}, {""}, +#line 229 "irc_commands.gperf" + {"720", IrcCommand::RPL_OMOTDSTART}, + {""}, +#line 231 "irc_commands.gperf" + {"722", IrcCommand::RPL_ENDOFOMOTD}, + {""}, {""}, {""}, {""}, {""}, +#line 236 "irc_commands.gperf" + {"727", IrcCommand::RPL_TESTMASKGECO}, + {""}, +#line 109 "irc_commands.gperf" + {"353", IrcCommand::RPL_NAMREPLY}, + {""}, +#line 170 "irc_commands.gperf" + {"451", IrcCommand::ERR_NOTREGISTERED}, + {""}, +#line 150 "irc_commands.gperf" + {"415", IrcCommand::ERR_MSGNEEDREGGEDNICK}, + {""}, {""}, +#line 105 "irc_commands.gperf" + {"351", IrcCommand::RPL_VERSION}, + {""}, +#line 108 "irc_commands.gperf" + {"315", IrcCommand::RPL_ENDOFWHO}, +#line 52 "irc_commands.gperf" + {"253", IrcCommand::RPL_LUSERUNKNOWN}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 50 "irc_commands.gperf" + {"251", IrcCommand::RPL_LUSERCLIENT}, + {""}, +#line 30 "irc_commands.gperf" + {"215", IrcCommand::RPL_STATSILINE}, + {""}, {""}, +#line 220 "irc_commands.gperf" + {"710", IrcCommand::RPL_KNOCK}, +#line 92 "irc_commands.gperf" + {"329", IrcCommand::RPL_CREATIONTIME}, +#line 222 "irc_commands.gperf" + {"712", IrcCommand::ERR_TOOMANYKNOCK}, +#line 242 "irc_commands.gperf" + {"733", IrcCommand::RPL_ENDOFMONLIS}, + {""}, {""}, {""}, {""}, +#line 227 "irc_commands.gperf" + {"717", IrcCommand::RPL_TARGNOTIFY}, + {""}, +#line 240 "irc_commands.gperf" + {"731", IrcCommand::RPL_MONOFFLINE}, + {""}, {""}, {""}, {""}, +#line 157 "irc_commands.gperf" + {"432", IrcCommand::ERR_ERRONEUSNICKNAME}, + {""}, +#line 13 "irc_commands.gperf" + {"015", IrcCommand::RPL_MAP}, +#line 93 "irc_commands.gperf" + {"330", IrcCommand::RPL_WHOISLOGGEDIN}, + {""}, +#line 95 "irc_commands.gperf" + {"332", IrcCommand::RPL_TOPIC}, +#line 161 "irc_commands.gperf" + {"437", IrcCommand::ERR_UNAVAILRESOURCE}, +#line 201 "irc_commands.gperf" + {"494", IrcCommand::ERR_OWNMODE}, + {""}, {""}, +#line 206 "irc_commands.gperf" + {"513", IrcCommand::ERR_WRONGPONG}, +#line 97 "irc_commands.gperf" + {"337", IrcCommand::RPL_WHOISTEXT}, +#line 134 "irc_commands.gperf" + {"394", IrcCommand::RPL_ENDOFUSERS}, + {""}, {""}, {""}, {""}, +#line 195 "irc_commands.gperf" + {"484", IrcCommand::ERR_ISCHANSERVICE}, +#line 84 "irc_commands.gperf" + {"319", IrcCommand::RPL_WHOISCHANNELS}, + {""}, +#line 234 "irc_commands.gperf" + {"725", IrcCommand::RPL_TESTLINE}, + {""}, +#line 128 "irc_commands.gperf" + {"384", IrcCommand::RPL_MYPORTIS}, + {""}, {""}, {""}, {""}, {""}, +#line 34 "irc_commands.gperf" + {"219", IrcCommand::RPL_ENDOFSTATS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 177 "irc_commands.gperf" + {"464", IrcCommand::ERR_PASSWDMISMATCH}, + {""}, {""}, {""}, {""}, +#line 115 "irc_commands.gperf" + {"364", IrcCommand::RPL_LINKS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 250 "irc_commands.gperf" + {"751", IrcCommand::RPL_SCANUMODES}, + {""}, +#line 225 "irc_commands.gperf" + {"715", IrcCommand::ERR_KNOCKDISABLED}, +#line 185 "irc_commands.gperf" + {"474", IrcCommand::ERR_BANNEDFROMCHAN}, + {""}, {""}, {""}, +#line 140 "irc_commands.gperf" + {"404", IrcCommand::ERR_CANNOTSENDTOCHAN}, +#line 122 "irc_commands.gperf" + {"374", IrcCommand::RPL_ENDOFINFO}, + {""}, +#line 106 "irc_commands.gperf" + {"352", IrcCommand::RPL_WHOREPLY}, +#line 172 "irc_commands.gperf" + {"457", IrcCommand::ERR_ACCEPTEXIST}, +#line 72 "irc_commands.gperf" + {"304", IrcCommand::RPL_TEXT}, + {""}, {""}, +#line 159 "irc_commands.gperf" + {"435", IrcCommand::ERR_BANNICKCHANGE}, +#line 238 "irc_commands.gperf" + {"729", IrcCommand::RPL_ENDOFQUIETLIS}, +#line 255 "irc_commands.gperf" + {"904", IrcCommand::ERR_SASLFAIL}, +#line 49 "irc_commands.gperf" + {"250", IrcCommand::RPL_STATSCONN}, + {""}, +#line 51 "irc_commands.gperf" + {"252", IrcCommand::RPL_LUSEROP}, + {""}, +#line 21 "irc_commands.gperf" + {"204", IrcCommand::RPL_TRACEOPERATOR}, + {""}, {""}, {""}, +#line 56 "irc_commands.gperf" + {"257", IrcCommand::RPL_ADMINLOC1}, +#line 136 "irc_commands.gperf" + {"396", IrcCommand::RPL_HOSTHIDDEN}, + {""}, {""}, +#line 40 "irc_commands.gperf" + {"235", IrcCommand::RPL_SERVLISTEND}, + {""}, +#line 197 "irc_commands.gperf" + {"486", IrcCommand::ERR_NONONREG}, +#line 239 "irc_commands.gperf" + {"730", IrcCommand::RPL_MONONLINE}, + {""}, +#line 241 "irc_commands.gperf" + {"732", IrcCommand::RPL_MONLIST}, + {""}, +#line 130 "irc_commands.gperf" + {"386", IrcCommand::RPL_RSACHALLENGE}, + {""}, {""}, {""}, {""}, +#line 9 "irc_commands.gperf" + {"004", IrcCommand::RPL_MYINFO}, + {""}, {""}, +#line 167 "irc_commands.gperf" + {"444", IrcCommand::ERR_NOLOGIN}, + {""}, {""}, {""}, {""}, +#line 118 "irc_commands.gperf" + {"368", IrcCommand::RPL_ENDOFBANLIST}, + {""}, +#line 179 "irc_commands.gperf" + {"466", IrcCommand::ERR_YOUWILLBEBANNED}, + {""}, {""}, {""}, {""}, +#line 111 "irc_commands.gperf" + {"366", IrcCommand::RPL_ENDOFNAMES}, + {""}, {""}, +#line 44 "irc_commands.gperf" + {"244", IrcCommand::RPL_STATSHLINE}, +#line 189 "irc_commands.gperf" + {"478", IrcCommand::ERR_BANLISTFULL}, + {""}, +#line 207 "irc_commands.gperf" + {"517", IrcCommand::ERR_DISABLED}, + {""}, {""}, +#line 125 "irc_commands.gperf" + {"378", IrcCommand::RPL_WHOISHOST}, +#line 63 "irc_commands.gperf" + {"266", IrcCommand::RPL_GLOBALUSERS}, +#line 187 "irc_commands.gperf" + {"476", IrcCommand::ERR_BADCHANMASK}, + {""}, {""}, {""}, +#line 142 "irc_commands.gperf" + {"406", IrcCommand::ERR_WASNOSUCHNICK}, +#line 124 "irc_commands.gperf" + {"376", IrcCommand::RPL_ENDOFMOTD}, + {""}, +#line 259 "irc_commands.gperf" + {"908", IrcCommand::RPL_SASLMECHS}, + {""}, +#line 74 "irc_commands.gperf" + {"306", IrcCommand::RPL_NOWAWAY}, + {""}, {""}, +#line 24 "irc_commands.gperf" + {"208", IrcCommand::RPL_TRACENEWTYPE}, + {""}, +#line 257 "irc_commands.gperf" + {"906", IrcCommand::ERR_SASLABORTED}, +#line 65 "irc_commands.gperf" + {"276", IrcCommand::RPL_WHOISCERTFP}, + {""}, +#line 54 "irc_commands.gperf" + {"255", IrcCommand::RPL_LUSERME}, + {""}, +#line 23 "irc_commands.gperf" + {"206", IrcCommand::RPL_TRACESERVER}, +#line 249 "irc_commands.gperf" + {"750", IrcCommand::RPL_SCANMATCHED}, + {""}, {""}, {""}, +#line 214 "irc_commands.gperf" + {"704", IrcCommand::RPL_HELPSTART}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 11 "irc_commands.gperf" + {"008", IrcCommand::RPL_SNOMASK}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 103 "irc_commands.gperf" + {"348", IrcCommand::RPL_EXCEPTLIST}, + {""}, +#line 169 "irc_commands.gperf" + {"446", IrcCommand::ERR_USERSDISABLED}, + {""}, {""}, {""}, {""}, +#line 101 "irc_commands.gperf" + {"346", IrcCommand::RPL_INVITELIST}, + {""}, {""}, +#line 47 "irc_commands.gperf" + {"248", IrcCommand::RPL_STATSULINE}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, +#line 248 "irc_commands.gperf" + {"744", IrcCommand::ERR_TOPICLOCK}, +#line 58 "irc_commands.gperf" + {"259", IrcCommand::RPL_ADMINEMAIL}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 218 "irc_commands.gperf" + {"708", IrcCommand::RPL_ETRACEFULL}, + {""}, {""}, {""}, {""}, +#line 155 "irc_commands.gperf" + {"424", IrcCommand::ERR_FILEERROR}, + {""}, +#line 216 "irc_commands.gperf" + {"706", IrcCommand::RPL_ENDOFHELP}, + {""}, {""}, +#line 89 "irc_commands.gperf" + {"324", IrcCommand::RPL_CHANNELMODEIS}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 37 "irc_commands.gperf" + {"224", IrcCommand::RPL_STATSFLINE}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 149 "irc_commands.gperf" + {"414", IrcCommand::ERR_WILDTOPLEVEL}, + {""}, {""}, {""}, {""}, +#line 79 "irc_commands.gperf" + {"314", IrcCommand::RPL_WHOWASUSER}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 29 "irc_commands.gperf" + {"214", IrcCommand::RPL_STATSNLINE}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 205 "irc_commands.gperf" + {"504", IrcCommand::ERR_USERNOTONSERV}, + {""}, {""}, {""}, {""}, {""}, +#line 91 "irc_commands.gperf" + {"328", IrcCommand::RPL_CHANNELURL}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, +#line 233 "irc_commands.gperf" + {"724", IrcCommand::RPL_TESTMASK}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 83 "irc_commands.gperf" + {"318", IrcCommand::RPL_ENDOFWHOIS}, + {""}, +#line 151 "irc_commands.gperf" + {"416", IrcCommand::ERR_TOOMANYMATCHES}, + {""}, {""}, {""}, {""}, +#line 81 "irc_commands.gperf" + {"316", IrcCommand::RPL_WHOISCHANOP}, + {""}, {""}, +#line 33 "irc_commands.gperf" + {"218", IrcCommand::RPL_STATSYLINE}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 31 "irc_commands.gperf" + {"216", IrcCommand::RPL_STATSKLINE}, + {""}, {""}, {""}, {""}, +#line 224 "irc_commands.gperf" + {"714", IrcCommand::ERR_KNOCKONCHAN}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, +#line 14 "irc_commands.gperf" + {"016", IrcCommand::RPL_MAPMORE}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, +#line 237 "irc_commands.gperf" + {"728", IrcCommand::RPL_QUIETLIST}, + {""}, +#line 39 "irc_commands.gperf" + {"234", IrcCommand::RPL_SERVLIST}, + {""}, {""}, {""}, {""}, +#line 235 "irc_commands.gperf" + {"726", IrcCommand::RPL_NOTESTLINE}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 228 "irc_commands.gperf" + {"718", IrcCommand::RPL_UMODEGMSG}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 226 "irc_commands.gperf" + {"716", IrcCommand::ERR_TARGUMODEG}, + {""}, {""}, {""}, {""}, {""}, +#line 162 "irc_commands.gperf" + {"438", IrcCommand::ERR_NICKTOOFAST}, + {""}, +#line 107 "irc_commands.gperf" + {"354", IrcCommand::RPL_WHOSPCRPL}, + {""}, {""}, +#line 98 "irc_commands.gperf" + {"338", IrcCommand::RPL_WHOISACTUALLY}, + {""}, +#line 160 "irc_commands.gperf" + {"436", IrcCommand::ERR_NICKCOLLISION}, + {""}, {""}, {""}, {""}, +#line 53 "irc_commands.gperf" + {"254", IrcCommand::RPL_LUSERCHANNELS}, + {""}, {""}, {""}, {""}, +#line 208 "irc_commands.gperf" + {"524", IrcCommand::ERR_HELPNOTFOUND}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 243 "irc_commands.gperf" + {"734", IrcCommand::ERR_MONLISTFULL}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 173 "irc_commands.gperf" + {"458", IrcCommand::ERR_ACCEPTNOT}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 171 "irc_commands.gperf" + {"456", IrcCommand::ERR_ACCEPTFULL}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 57 "irc_commands.gperf" + {"258", IrcCommand::RPL_ADMINLOC2}, + {""}, {""}, {""}, {""}, {""}, {""}, +#line 55 "irc_commands.gperf" + {"256", IrcCommand::RPL_ADMINME} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + unsigned int key = hash (str, len); + + if (key <= MAX_HASH_VALUE) + { + const char *s = wordlist[key].text; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &wordlist[key]; + } + } + return 0; +} diff --git a/main.cpp b/main.cpp index d449981..8369b5b 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,7 @@ #include "watchdog_thread.hpp" #include "snote_thread.hpp" #include "self_thread.hpp" +#include "command_thread.hpp" #include #include @@ -52,25 +53,17 @@ auto unhandled_message_thread(Connection& connection) -> void auto echo_thread(Connection& connection) -> void { - connection.add_listener([&connection](IrcMsgEvent& event) + connection.add_listener([&connection](CommandEvent& event) { - if (IrcCommand::PRIVMSG == event.command) + if ("raw" == event.command + and "glguy" == event.oper + and "glguy" == event.account) { - auto const msg = event.irc.args[1]; - if (msg.starts_with("!raw ")) - { - for (auto const& tag : event.irc.tags) - { - if ("account" == tag.key && "glguy" == tag.val) - { - auto txt = std::string{event.irc.args[1].substr(5)}; - txt += "\r\n"; - connection.write_raw(std::move(txt)); - event.handled_ = true; - return; - } - } - } + auto txt = std::string{event.arg}; + txt += "\r\n"; + connection.write_line(std::move(txt)); + event.handled_ = true; + send_notice(connection, event.nick, "ack"); } }); } @@ -85,6 +78,7 @@ auto start(boost::asio::io_context & io, Settings const& settings) -> void auto const self_thread = SelfThread::start(*connection); registration_thread(*connection, settings.password, settings.username, settings.realname, settings.nickname); snote_thread(*connection); + CommandThread::start(*connection); echo_thread(*connection); unhandled_message_thread(*connection); diff --git a/write_irc.cpp b/write_irc.cpp index 4387b29..dbab73b 100644 --- a/write_irc.cpp +++ b/write_irc.cpp @@ -4,8 +4,7 @@ namespace { auto write_irc(Connection& connection, std::string message) -> void { - message += "\r\n"; - connection.write_raw(std::move(message)); + connection.write_line(std::move(message)); } auto is_invalid_last(char x) -> bool @@ -87,3 +86,12 @@ auto send_cap_req(Connection& connection, std::string_view caps) -> void write_irc(connection, "CAP", "REQ", caps); } +auto send_privmsg(Connection& connection, std::string_view target, std::string_view message) -> void +{ + write_irc(connection, "PRIVMSG", target, message); +} + +auto send_notice(Connection& connection, std::string_view target, std::string_view message) -> void +{ + write_irc(connection, "NOTICE", target, message); +} diff --git a/write_irc.hpp b/write_irc.hpp index a4efbf5..537771e 100644 --- a/write_irc.hpp +++ b/write_irc.hpp @@ -10,3 +10,5 @@ auto send_nick(Connection&, std::string_view) -> void; auto send_cap_ls(Connection&) -> void; auto send_cap_end(Connection&) -> void; auto send_cap_req(Connection&, std::string_view) -> void; +auto send_privmsg(Connection&, std::string_view, std::string_view) -> void; +auto send_notice(Connection&, std::string_view, std::string_view) -> void;