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) {
|
||||
enum {
|
||||
ADDING,
|
||||
REMOVING
|
||||
} 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 == '+') {
|
||||
op = ADDING;
|
||||
} else if (character == '-') {
|
||||
|
@ -87,11 +92,41 @@ void ModeSet::parse(std::string_view in, NetworkInfo &netInfo) {
|
|||
if (op == ADDING) {
|
||||
if (str.find(character) == str.npos) {
|
||||
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) {
|
||||
auto res = str.find(character);
|
||||
if (res != str.npos) {
|
||||
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
|
||||
nick = std::move(split[0]);
|
||||
hops = std::stoull(std::string(split[1]));
|
||||
umode.parse(split[3], netInfo);
|
||||
umode.parse<false>(split[3], netInfo);
|
||||
ident = std::move(split[4]);
|
||||
host = std::move(split[5]);
|
||||
realhost = std::move(split[6]);
|
||||
|
@ -132,7 +167,7 @@ void Channel::parse_sjoin(const Event& event, Cache& cache, NetworkInfo& netInfo
|
|||
}
|
||||
// Move values
|
||||
name = std::move(split[1]);
|
||||
mode.parse(split[2], netInfo);
|
||||
mode.parse<true>(split[2], netInfo);
|
||||
// Get members
|
||||
for (auto& raw_uuid : strSplit(event.text, ' ')) {
|
||||
// Erase leading sign
|
||||
|
@ -359,7 +394,7 @@ async::result<void> Instance::process(const Event event) {
|
|||
throw DesyncError();
|
||||
}
|
||||
// Update mode
|
||||
res->get()->umode.parse(event.text, netInfo);
|
||||
res->get()->umode.parse<false>(event.text, netInfo);
|
||||
}
|
||||
// Channel updates
|
||||
else if (event.name == "SJOIN") {
|
||||
|
@ -378,6 +413,62 @@ async::result<void> Instance::process(const Event event) {
|
|||
}
|
||||
// Set topic
|
||||
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;
|
||||
|
|
16
instance.hpp
16
instance.hpp
|
@ -52,14 +52,16 @@ struct Command {
|
|||
std::string name, args, text;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
struct ModeSet {
|
||||
std::string str;
|
||||
std::vector<std::tuple<char, std::string>> params;
|
||||
|
||||
template<bool channelModes>
|
||||
void parse(std::string_view str, NetworkInfo& netInfo);
|
||||
};
|
||||
|
||||
|
@ -118,6 +120,18 @@ struct NetworkInfo {
|
|||
paramOnSetAndUnsetModes, // Properties like k
|
||||
paramOnSetOnlyModes, // Properties like f
|
||||
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;
|
||||
|
||||
async::result<void> wait_ready() {
|
||||
|
|
Loading…
Add table
Reference in a new issue