Public Access
lib/irc: IrcMessage parse/serialize, base64, ReconnectPolicy (5 s .. 5 min), IrcConfig (validated, persisted) and IrcSession: registration with SASL PLAIN or NickServ, nick fallback, PING, Buffers capped at 50 lines with unread counts, Mentions, CTCP ACTION/VERSION, topics, /names on request only, others' join/part/quit hidden, user commands, and rejoining after a pause. No networking: the session returns lines to send, Log entries and Notifications. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
44 lines
1.3 KiB
C++
44 lines
1.3 KiB
C++
#include "irc_message.h"
|
|
|
|
namespace roro {
|
|
|
|
IrcMessage IrcMessage::parse(const std::string& raw) {
|
|
IrcMessage m;
|
|
std::string line = raw;
|
|
while (!line.empty() && (line.back() == '\r' || line.back() == '\n')) line.pop_back();
|
|
|
|
size_t pos = 0;
|
|
auto word = [&]() {
|
|
size_t end = line.find(' ', pos);
|
|
std::string w = line.substr(pos, end == std::string::npos ? std::string::npos : end - pos);
|
|
pos = end == std::string::npos ? line.size() : end + 1;
|
|
while (pos < line.size() && line[pos] == ' ') pos++;
|
|
return w;
|
|
};
|
|
if (pos < line.size() && line[pos] == '@') word();
|
|
if (pos < line.size() && line[pos] == ':') m.prefix = word().substr(1);
|
|
m.command = word();
|
|
while (pos < line.size()) {
|
|
if (line[pos] == ':') {
|
|
m.params.push_back(line.substr(pos + 1));
|
|
break;
|
|
}
|
|
m.params.push_back(word());
|
|
}
|
|
return m;
|
|
}
|
|
|
|
std::string IrcMessage::serialize(const std::string& command, std::initializer_list<std::string> params) {
|
|
std::string out = command;
|
|
size_t i = 0;
|
|
for (auto& p : params) {
|
|
bool last = ++i == params.size();
|
|
out += ' ';
|
|
if (last && (p.empty() || p[0] == ':' || p.find(' ') != std::string::npos)) out += ':';
|
|
out += p;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
} // namespace roro
|