#119 IRCv3 message tags.

master
Tomatix 4 years ago
parent 02e09bccb6
commit 12158d9f10
  1. 7
      IRCClient/IRCBasePriv.h
  2. 35
      IRCClient/IRCMessage.cpp
  3. 4
      IRCClient/IRCMessage.h
  4. 12
      IRCClient/Private/parseIncoming.cpp

@ -33,10 +33,11 @@ const std::vector<std::string> V3Support {
"away-notify",
"invite-notify",
"multi-prefix",
"userhost-in-names"/*,
"userhost-in-names",
"message-tags",
"server-time",
"batch"
*/
//"batch"
/*
* TODO https://ircv3.net/irc/
* chghost

@ -19,30 +19,49 @@ IRCMessage::IRCMessage(const IRCPrefix& defaultSender, const std::string& messag
return;
enum class S {
IRCv3Tags,
Prefix,
Command,
Argument,
Message
} parseState = S::Prefix;
} parseState = S::IRCv3Tags;
auto it = message.begin() + 1;
if (message[0] != ':') {
if (message[0] != '@') {
parseState = S::Prefix;
}
if (message[0] != ':' && message[0] != '@') {
// Set up parser for the format: "cmd arg :msg"
it = message.begin();
parseState = S::Command;
}
/*
* Tokenize the message. Two formats may occur:
* Tokenize the message. Three formats may occur:
* :server.addr cmd arg :msg
* @IRCv3Tag;tag2;tag3 :server.addr cmd arg :msg
* cmd arg :msg
*/
while (it != message.end()) {
auto next = std::find(it, message.end(), ' ');
switch (parseState) {
case S::IRCv3Tags:
{
std::string tagstr;
std::copy(it, next, std::back_inserter(tagstr));
parseIRCv3Tags(tagstr);
parseState = S::Prefix;
break;
}
case S::Prefix:
/* This condition happens if parseState started on IRCv3Tags. */
if (*it == ':')
++it;
m_sender = IRCPrefix(std::string(it, next));
parseState = S::Command;
break;
@ -82,3 +101,13 @@ const std::string& IRCMessage::operator[](int idx) const
else
return m_args[idx];
}
void IRCMessage::parseIRCv3Tags(const std::string& tagstr)
{
auto it = tagstr.begin();
while (it != tagstr.end()) {
auto next = std::find(it, tagstr.end(), ';');
m_tags.emplace_back(it, next);
it = (next == tagstr.end()) ? next : next + 1;
}
}

@ -19,6 +19,7 @@ class IRCMessage
public:
IRCMessage(const IRCPrefix& defaultSender, const std::string& message);
const std::vector<std::string>& getTags() const { return m_tags; }
const IRCPrefix& getSender() const { return m_sender; }
const std::string& getCommand() const { return m_command; }
const std::vector<std::string>& getArgs() const { return m_args; }
@ -34,6 +35,7 @@ public:
private:
using SystemClock = std::chrono::system_clock;
std::vector<std::string> m_tags; //!< IRCv3 tags
IRCPrefix m_sender; //!< Sender prefix
std::string m_command; //!< Command name
std::vector<std::string> m_args; //!< Arguments to command
@ -41,6 +43,8 @@ private:
std::string m_batchId; //!< Set if this is part of a batch
SystemClock::time_point m_timestamp; //!< When message occurred.
void parseIRCv3Tags(const std::string& tagstr);
};
#endif // IRCMESSAGE_H

@ -19,8 +19,18 @@ void IRCBasePriv::parseIncoming(const std::string& line)
IRCMessage ircmessage(IRCPrefix(hostname), line);
if constexpr (DumpReadData) {
std::cout << fmt::format(R"([RCV] from="{}" cmd="{}" msg="{}" argc={} )", ircmessage.getSender().composite(), ircmessage.getCommand(), ircmessage.getMessage(), ircmessage.getArgs().size());
std::cout << "[RCV] ";
std::cout << fmt::format("tagc={} ", ircmessage.getTags().size());
int c = 0;
for (const auto& tag : ircmessage.getTags()) {
std::cout << fmt::format("tag({})=\"{}\" ", c, tag);
++c;
}
std::cout << fmt::format(R"(from="{}" cmd="{}" msg="{}" argc={} )", ircmessage.getSender().composite(), ircmessage.getCommand(), ircmessage.getMessage(), ircmessage.getArgs().size());
c = 0;
for (const auto& arg : ircmessage.getArgs()) {
std::cout << fmt::format("arg({})=\"{}\" ", c, arg);
++c;

Loading…
Cancel
Save