A basic twitch chat viewer for windows written in C++20. It streams chat from the twitch IRC server using sockets, and uses SDL2 and SDL2_ttf to render.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.3 KiB

#include <string>
#include <vector>
#include <istream>
#include <sstream>
#include <iostream>
#include <deque>
#include <optional>
#include "irc.h"
#include <SDL.h> // for SDL_GetTicks();
enum class ircommand parse_command(const std::string& command) {
if (!command.compare("PRIVMSG")) {
return ircommand::PRIVMSG;
}
if (!command.compare("JOIN")) {
return ircommand::JOIN;
}
if (!command.compare("QUIT")) {
return ircommand::QUIT;
}
if (!command.compare("PING")) {
return ircommand::PING;
}
return ircommand::UNKNOWN;
}
/*
https://datatracker.ietf.org/doc/html/rfc1459.html#section-2.3.1
*/
std::optional<msg>
parse_chat_message(const std::string &message)
{
// :nightbot!nightbot@nightbot.tmi.twitch.tv PRIVMSG #ironmouse :If you would like to support ironmouse donations are not required but greatly appreciated: https://www.streamlabs.com/ironmouse
struct msg m {};
int start = 0;
int end = 0;
if (message[0] == ':') {
// prefix
// parse user from prefix
start = message.find("!", start);
end = message.find("@", start);
if (start != std::string::npos && end != std::string::npos && start < end) {
start++;
m.user = message.substr(start, end - start);
end = message.find(" ", end);
} else {
start = 1;
end = message.find(" ", start);
m.user = message.substr(start, end - start);
}
}
// command
start = message.find_first_not_of(" ", end);
end = message.find(" ", start);
if (start == std::string::npos || end == std::string::npos) {
return {};
}
auto command = message.substr(start, end - start);
m.cmd = parse_command(command);
if (m.cmd == ircommand::PRIVMSG) {
// channel
start = message.find("#");
end = message.find(" ", start);
start++;
m.channel = message.substr(start, end - start);
}
start = message.find(":", end); // end of command params
start++;
// message
m.message = message.substr(start, message.size() - start);
m.complete_message = message;
return m;
}
void parse_chat_messages(const std::string& messages,
std::deque<msg> &message_queue) {
// parse some input from server
int start = 0;
std::vector<std::string> tokens{};
std::istringstream iss(messages);
std::string s;
while (std::getline(iss, s)) {
auto msg = parse_chat_message(s);
msg->received_at = SDL_GetTicks();
if (msg) {
message_queue.push_back(*msg);
}
}
}