1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#pragma once
#include <functional>
#include <map>
#include <optional>
#include <sstream>
#include <string>
#include <vector>
#include "../utils/string.hpp"
namespace bot {
namespace irc {
enum MessageType { Privmsg, Ping, Notice };
std::optional<MessageType> define_message_type(const std::string &msg);
struct IRCMessage {
std::map<std::string, std::string> tags;
std::string prefix, nick, command;
std::vector<std::string> params;
static std::optional<IRCMessage> from_string(std::string msg);
};
struct MessageSender {
std::string login;
std::string display_name;
int id;
std::map<std::string, int> badges;
// More fields will be here
};
struct MessageSource {
std::string login;
int id;
};
template <MessageType T>
struct Message;
template <>
struct Message<MessageType::Privmsg> {
MessageSender sender;
MessageSource source;
std::string message;
};
template <MessageType T>
std::optional<Message<T>> parse_message(const std::string &msg) {
std::vector<std::string> parts = utils::string::split_text(msg, ' ');
if (T == MessageType::Privmsg) {
MessageSender sender;
MessageSource source;
Message<MessageType::Privmsg> message;
std::string tags = parts[0];
tags = tags.substr(1, tags.length());
parts.erase(parts.begin());
std::string user = parts[0];
user = user.substr(1, user.length());
std::vector<std::string> user_parts =
utils::string::split_text(user, '!');
sender.login = user_parts[0];
parts.erase(parts.begin(), parts.begin() + 2);
std::string channel_login = parts[0];
source.login = channel_login.substr(1, channel_login.length());
parts.erase(parts.begin());
std::string chat_message = utils::string::join_vector(parts, ' ');
message.message = chat_message.substr(1, chat_message.length());
std::vector<std::string> tags_parts =
utils::string::split_text(tags, ';');
for (const std::string &tag : tags_parts) {
std::istringstream iss(tag);
std::string key;
std::string value;
std::getline(iss, key, '=');
std::getline(iss, value);
if (key == "display-name") {
sender.display_name = value;
} else if (key == "room-id") {
source.id = std::stoi(value);
} else if (key == "user-id") {
sender.id = std::stoi(value);
} else if (key == "badges") {
std::vector<std::string> badges =
utils::string::split_text(value, ',');
std::map<std::string, int> map;
for (const auto &badge : badges) {
std::istringstream iss2(badge);
std::string name;
std::string value;
std::getline(iss2, name, '/');
std::getline(iss2, value);
map.insert({name, std::stoi(value)});
}
sender.badges = map;
}
}
message.sender = sender;
message.source = source;
return message;
}
return std::nullopt;
}
template <MessageType T>
struct MessageHandler;
template <>
struct MessageHandler<MessageType::Privmsg> {
using fn = std::function<void(Message<Privmsg> message)>;
};
}
}
|