From e39d90442dfd6fb136cda23b0d013da98fb089e9 Mon Sep 17 00:00:00 2001 From: ilotterytea Date: Sat, 5 Jul 2025 18:12:43 +0500 Subject: feat: parse irc messages fully --- bot/src/irc/message.cpp | 78 ++++++++++++++++++++++++++++++++++++------------ bot/src/irc/message.hpp | 8 +++++ bot/src/utils/string.cpp | 14 +++++++++ bot/src/utils/string.hpp | 4 +++ 4 files changed, 85 insertions(+), 19 deletions(-) (limited to 'bot') diff --git a/bot/src/irc/message.cpp b/bot/src/irc/message.cpp index 038df83..43590e5 100644 --- a/bot/src/irc/message.cpp +++ b/bot/src/irc/message.cpp @@ -4,29 +4,69 @@ #include #include -namespace bot { - namespace irc { - std::optional define_message_type(const std::string &msg) { - std::vector parts = utils::string::split_text(msg, ' '); - int i; - - if (msg[0] == '@') { - i = 2; - } else if (msg[0] == ':') { - i = 1; - } else { - return std::nullopt; +namespace bot::irc { + std::optional define_message_type(const std::string &msg) { + std::vector parts = utils::string::split_text(msg, ' '); + int i; + + if (msg[0] == '@') { + i = 2; + } else if (msg[0] == ':') { + i = 1; + } else { + return std::nullopt; + } + + if (parts[i] == "NOTICE") { + return MessageType::Notice; + } else if (parts[i] == "PRIVMSG") { + return MessageType::Privmsg; + } else if (parts[i] == "PING") { + return MessageType::Ping; + } + + return std::nullopt; + } + + std::optional IRCMessage::from_string(std::string msg) { + IRCMessage m; + + if (msg[0] == '@') { + int end = msg.find(' '); + std::string raw_tags = msg.substr(1, end); + for (const std::string tag : utils::string::split_text(raw_tags, ';')) { + auto splitted_tag = utils::string::split_text_n(tag, "=", 1); + m.tags.insert_or_assign(splitted_tag[0], splitted_tag[1]); } + msg = msg.substr(end + 1); + } - if (parts[i] == "NOTICE") { - return MessageType::Notice; - } else if (parts[i] == "PRIVMSG") { - return MessageType::Privmsg; - } else if (parts[i] == "PING") { - return MessageType::Ping; + if (msg[0] == ':') { + int end = msg.find(' '); + m.prefix = msg.substr(1, end); + int bang = msg.find('!'); + if (bang != std::string::npos) { + m.nick = m.prefix.substr(0, bang - 1); } + msg = msg.substr(end + 1); + } - return std::nullopt; + std::vector parts = utils::string::split_text(msg, ' '); + + m.command = parts.front(); + parts.erase(parts.begin()); + + for (int i = 0; i < parts.size(); i++) { + if (parts[i][0] == ':') { + parts = std::vector(parts.begin() + i, parts.end()); + m.params.push_back(utils::string::join_vector(parts, ' ').substr(1)); + break; + } + if (!parts[i].empty()) { + m.params.push_back(parts[i]); + } } + + return m; } } diff --git a/bot/src/irc/message.hpp b/bot/src/irc/message.hpp index 54b911b..ae903ba 100644 --- a/bot/src/irc/message.hpp +++ b/bot/src/irc/message.hpp @@ -14,6 +14,14 @@ namespace bot { enum MessageType { Privmsg, Ping, Notice }; std::optional define_message_type(const std::string &msg); + struct IRCMessage { + std::map tags; + std::string prefix, nick, command; + std::vector params; + + static std::optional from_string(std::string msg); + }; + struct MessageSender { std::string login; std::string display_name; diff --git a/bot/src/utils/string.cpp b/bot/src/utils/string.cpp index 38087dc..0dd79dd 100644 --- a/bot/src/utils/string.cpp +++ b/bot/src/utils/string.cpp @@ -113,6 +113,20 @@ namespace bot { return lines; } + + std::vector split_text_n(std::string value, + const std::string &separator, + const int &n) { + std::vector v; + int fi, i = 0; + while ((fi = value.find(separator)) != std::string::npos && i < n) { + v.push_back(value.substr(0, fi)); + value = value.substr(fi + separator.size()); + i++; + } + v.push_back(value); + return v; + } } } } diff --git a/bot/src/utils/string.hpp b/bot/src/utils/string.hpp index 18d4f9a..f46b608 100644 --- a/bot/src/utils/string.hpp +++ b/bot/src/utils/string.hpp @@ -35,6 +35,10 @@ namespace bot { const std::string &base, const std::vector &values, const std::string &prefix, const std::string &separator, const long long &max_length); + + std::vector split_text_n(std::string value, + const std::string &separator, + const int &n); } } } -- cgit v1.2.3