mirror of
https://gitlab.com/niansa/asbots.git
synced 2025-03-06 20:48:25 +01:00
(Almost) fully implemented modes
This commit is contained in:
parent
36717eb59c
commit
f689535382
2 changed files with 110 additions and 5 deletions
99
instance.cpp
99
instance.cpp
|
@ -73,12 +73,17 @@ void Command::parse(std::string_view str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<bool channelModes>
|
||||||
void ModeSet::parse(std::string_view in, NetworkInfo &netInfo) {
|
void ModeSet::parse(std::string_view in, NetworkInfo &netInfo) {
|
||||||
enum {
|
enum {
|
||||||
ADDING,
|
ADDING,
|
||||||
REMOVING
|
REMOVING
|
||||||
} op;
|
} op;
|
||||||
for (const auto character : in) {
|
// Split up
|
||||||
|
auto split = strSplit(in, ' ');
|
||||||
|
auto paramIt = split.begin() + 1;
|
||||||
|
// Iterate through mode characters
|
||||||
|
for (const char character : split[0]) {
|
||||||
if (character == '+') {
|
if (character == '+') {
|
||||||
op = ADDING;
|
op = ADDING;
|
||||||
} else if (character == '-') {
|
} else if (character == '-') {
|
||||||
|
@ -87,11 +92,41 @@ void ModeSet::parse(std::string_view in, NetworkInfo &netInfo) {
|
||||||
if (op == ADDING) {
|
if (op == ADDING) {
|
||||||
if (str.find(character) == str.npos) {
|
if (str.find(character) == str.npos) {
|
||||||
str.push_back(character);
|
str.push_back(character);
|
||||||
|
if constexpr(channelModes) {
|
||||||
|
if (netInfo.channelModes.takesParamOnSet(character)) {
|
||||||
|
if (paramIt == split.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
params.push_back({character, std::string(*(paramIt++))});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw DesyncError();
|
||||||
}
|
}
|
||||||
} else if (op == REMOVING) {
|
} else if (op == REMOVING) {
|
||||||
auto res = str.find(character);
|
auto res = str.find(character);
|
||||||
if (res != str.npos) {
|
if (res != str.npos) {
|
||||||
str.erase(res);
|
str.erase(res);
|
||||||
|
if constexpr(channelModes) {
|
||||||
|
if (netInfo.channelModes.takesParamOnUnset(character)) {
|
||||||
|
if (paramIt == split.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
for (auto it = params.begin(); ; it++) {
|
||||||
|
if (it == params.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
auto &[c, d] = *it;
|
||||||
|
if (c == character && (d == *paramIt || *paramIt == "*")) {
|
||||||
|
params.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paramIt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw DesyncError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +144,7 @@ void User::parse_euid(const Event& event, NetworkInfo& netInfo) {
|
||||||
// Move values
|
// Move values
|
||||||
nick = std::move(split[0]);
|
nick = std::move(split[0]);
|
||||||
hops = std::stoull(std::string(split[1]));
|
hops = std::stoull(std::string(split[1]));
|
||||||
umode.parse(split[3], netInfo);
|
umode.parse<false>(split[3], netInfo);
|
||||||
ident = std::move(split[4]);
|
ident = std::move(split[4]);
|
||||||
host = std::move(split[5]);
|
host = std::move(split[5]);
|
||||||
realhost = std::move(split[6]);
|
realhost = std::move(split[6]);
|
||||||
|
@ -132,7 +167,7 @@ void Channel::parse_sjoin(const Event& event, Cache& cache, NetworkInfo& netInfo
|
||||||
}
|
}
|
||||||
// Move values
|
// Move values
|
||||||
name = std::move(split[1]);
|
name = std::move(split[1]);
|
||||||
mode.parse(split[2], netInfo);
|
mode.parse<true>(split[2], netInfo);
|
||||||
// Get members
|
// Get members
|
||||||
for (auto& raw_uuid : strSplit(event.text, ' ')) {
|
for (auto& raw_uuid : strSplit(event.text, ' ')) {
|
||||||
// Erase leading sign
|
// Erase leading sign
|
||||||
|
@ -359,7 +394,7 @@ async::result<void> Instance::process(const Event event) {
|
||||||
throw DesyncError();
|
throw DesyncError();
|
||||||
}
|
}
|
||||||
// Update mode
|
// Update mode
|
||||||
res->get()->umode.parse(event.text, netInfo);
|
res->get()->umode.parse<false>(event.text, netInfo);
|
||||||
}
|
}
|
||||||
// Channel updates
|
// Channel updates
|
||||||
else if (event.name == "SJOIN") {
|
else if (event.name == "SJOIN") {
|
||||||
|
@ -378,6 +413,62 @@ async::result<void> Instance::process(const Event event) {
|
||||||
}
|
}
|
||||||
// Set topic
|
// Set topic
|
||||||
res->get()->topic = event.text;
|
res->get()->topic = event.text;
|
||||||
|
} else if (event.name == "JOIN") {
|
||||||
|
// User joined existing channel
|
||||||
|
// Split args
|
||||||
|
auto split = strSplit(event.args, ' ', 2);
|
||||||
|
if (split.size() != 3) {
|
||||||
|
throw ParseError("In join event parser: join even did not receive enough arguments (expected 3)");
|
||||||
|
}
|
||||||
|
// Get channel from cache
|
||||||
|
auto c_res = cache.find_channel_by_name(split[1]);
|
||||||
|
if (c_res == cache.channels.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
// Get user from cache
|
||||||
|
auto u_res = cache.find_user_by_uid(std::get<UUID>(event.sender.id));
|
||||||
|
if (u_res == cache.users.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
// Assign user to channel and vice versa
|
||||||
|
c_res->get()->members.push_back(*u_res);
|
||||||
|
u_res->get()->channels.push_back(*c_res);
|
||||||
|
// Update channel modes
|
||||||
|
c_res->get()->mode.parse<true>(split[2], netInfo);
|
||||||
|
} else if (event.name == "PART" || event.name == "KICK") {
|
||||||
|
// User left channel
|
||||||
|
// Get channel from cache
|
||||||
|
auto c_res = cache.find_channel_by_name(strSplit(event.args, ' ', 1)[0]);
|
||||||
|
if (c_res == cache.channels.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
// Get user from cache
|
||||||
|
auto u_res = cache.find_user_by_uid(std::get<UUID>(event.sender.id));
|
||||||
|
if (u_res == cache.users.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
// Remove channel from both user and channel
|
||||||
|
c_res->get()->removeMember(*u_res);
|
||||||
|
u_res->get()->removeChannel(*c_res);
|
||||||
|
} else if (event.name == "TMODE" || event.name == "BMASK") {
|
||||||
|
// Channel modes changed
|
||||||
|
// Split args
|
||||||
|
std::string_view modes, channelName;
|
||||||
|
{
|
||||||
|
auto split = strSplit(event.args, ' ', 2);
|
||||||
|
if (split.size() != 3) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
channelName = split[1];
|
||||||
|
modes = split[2];
|
||||||
|
}
|
||||||
|
// Get channel from cache
|
||||||
|
auto c_res = cache.find_channel_by_name(channelName);
|
||||||
|
if (c_res == cache.channels.end()) {
|
||||||
|
throw DesyncError();
|
||||||
|
}
|
||||||
|
// Apply changes
|
||||||
|
c_res->get()->mode.parse<true>("+{} {}"_format(modes, event.text), netInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//std::clog << event.dump() << std::flush;
|
//std::clog << event.dump() << std::flush;
|
||||||
|
|
16
instance.hpp
16
instance.hpp
|
@ -52,14 +52,16 @@ struct Command {
|
||||||
std::string name, args, text;
|
std::string name, args, text;
|
||||||
|
|
||||||
std::string dump() const {
|
std::string dump() const {
|
||||||
return fmt::format("{} {}{}\n", name, args, (text.empty()?"":":"+text));
|
return fmt::format("{} {}{}\n", name, args, (text.empty()?"":" :"+text));
|
||||||
}
|
}
|
||||||
void parse(std::string_view str);
|
void parse(std::string_view str);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModeSet {
|
struct ModeSet {
|
||||||
std::string str;
|
std::string str;
|
||||||
|
std::vector<std::tuple<char, std::string>> params;
|
||||||
|
|
||||||
|
template<bool channelModes>
|
||||||
void parse(std::string_view str, NetworkInfo& netInfo);
|
void parse(std::string_view str, NetworkInfo& netInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,6 +120,18 @@ struct NetworkInfo {
|
||||||
paramOnSetAndUnsetModes, // Properties like k
|
paramOnSetAndUnsetModes, // Properties like k
|
||||||
paramOnSetOnlyModes, // Properties like f
|
paramOnSetOnlyModes, // Properties like f
|
||||||
paramLessModes; // Properties like z
|
paramLessModes; // Properties like z
|
||||||
|
|
||||||
|
bool takesNoParam(char mode) {
|
||||||
|
return paramLessModes.find(mode) != paramLessModes.npos;
|
||||||
|
}
|
||||||
|
bool takesParamOnUnset(char mode) {
|
||||||
|
return listModes.find(mode) != std::string::npos ||
|
||||||
|
paramOnSetAndUnsetModes.find(mode) != std::string::npos;
|
||||||
|
}
|
||||||
|
bool takesParamOnSet(char mode) {
|
||||||
|
return paramOnSetOnlyModes.find(mode) != std::string::npos ||
|
||||||
|
takesParamOnUnset(mode);
|
||||||
|
}
|
||||||
} channelModes;
|
} channelModes;
|
||||||
|
|
||||||
async::result<void> wait_ready() {
|
async::result<void> wait_ready() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue