more patterns

This commit is contained in:
Eric Mertens 2023-11-27 18:47:32 -08:00
parent e23fb33d89
commit 61bd4b558e
3 changed files with 70 additions and 25 deletions

14
c_callback.hpp Normal file
View File

@ -0,0 +1,14 @@
#pragma once
template <typename> struct CCallback_;
template <typename F, typename R, typename... Ts>
struct CCallback_<R (F::*) (Ts...) const>
{
static R invoke(Ts... args, void* u)
{
return (*reinterpret_cast<F*>(u))(args...);
}
};
template <typename F>
using CCallback = CCallback_<decltype(&F::operator())>;

View File

@ -2,6 +2,7 @@
#include "irc_parse_thread.hpp" #include "irc_parse_thread.hpp"
#include "connection.hpp" #include "connection.hpp"
#include "c_callback.hpp"
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
@ -45,24 +46,41 @@ SnotePattern const patterns[] =
{SnoteTag::TemporaryKlineExpired, {SnoteTag::TemporaryKlineExpired,
R"(^Temporary K-line for \[([^ ]+)\] expired$)"}, R"(^Temporary K-line for \[([^ ]+)\] expired$)"},
{SnoteTag::PropagatedBanExpired,
R"(^Propagated ban for \[([^ ]+)\] expired$)"},
{SnoteTag::DisconnectingKlined, {SnoteTag::DisconnectingKlined,
R"(^Disconnecting K-Lined user ([^ ]+)\[([^@]+)@([^ ]+)\] \((.*)\)$)"}, R"(^Disconnecting K-Lined user ([^ ]+)\[([^@]+)@([^ ]+)\] \((.*)\)$)"},
{SnoteTag::NewPropagatedKline,
R"(^([^ ]+)!([^ ]+)@([^ ]+)\{([^ ]+)\} added global ([^ ]+) min\. K-Line for \[([^ ]+)\] \[(.*)\]$)"},
{SnoteTag::NewTemporaryKline,
R"(^([^ ]+)!([^ ]+)@([^ ]+)\{([^ ]+)\} added temporary ([^ ]+) min\. K-Line for \[([^ ]+)\] \[(.*)\]$)"},
{SnoteTag::LoginAttempts,
"^Warning: \x02([^ ]+)\x02 failed login attempts to \x02([^ ]+)\x02\\. Last attempt received from \x02(.+)\x02.*$"},
{SnoteTag::PossibleFlooder,
R"(^Possible Flooder ([^ ]+)\[([^ ]+)@[^ ]+\] on ([^ ]+) target: ([^ ]+)$)"},
{SnoteTag::Killed,
R"(^Received KILL message for ([^ ]+)!([^ ]+)@([^ ]+)\. From ([^ ]+) Path: ([^ ]+) \((.*)\)$)"},
}; };
auto setup_database() -> hs_database_t* auto setup_database() -> hs_database_t*
{ {
auto const n = std::size(patterns); auto const n = std::size(patterns);
std::vector<char const*> expressions; std::vector<char const*> expressions;
std::vector<unsigned> flags(n, 0); std::vector<unsigned> flags(n, HS_FLAG_SINGLEMATCH);
std::vector<unsigned> ids; std::vector<unsigned> ids;
expressions.reserve(std::size(patterns)); expressions.reserve(n);
ids.reserve(std::size(patterns)); ids.reserve(n);
for (std::size_t i = 0; i < n; i++) for (std::size_t i = 0; i < n; i++)
{ {
expressions.push_back(patterns[i].expression); expressions.push_back(patterns[i].expression);
flags.push_back(0);
ids.push_back(i); ids.push_back(i);
} }
@ -104,32 +122,34 @@ auto SnoteThread::start(Connection& connection) -> std::shared_ptr<SnoteThread>
connection.add_listener<IrcMsgEvent>([&connection, thread](IrcMsgEvent& event) connection.add_listener<IrcMsgEvent>([&connection, thread](IrcMsgEvent& event)
{ {
auto& args = event.irc.args; auto& args = event.irc.args;
if (IrcCommand::NOTICE == event.command if (IrcCommand::NOTICE == event.command && "*" == args[0] && args[1].starts_with(prefix))
&& "*" == args[0]
&& args[1].starts_with(prefix))
{ {
event.handled_ = true; event.handled_ = true;
auto message = args[1].substr(strlen(prefix)); auto const message = args[1].substr(strlen(prefix));
unsigned int match_id = -1;
auto const scan_result = hs_scan(thread->db_.get(), message.data(), message.size(), 0, thread->scratch_.get(),
[](unsigned int id, unsigned long long from, unsigned long long to, unsigned int flags, void *context) -> int
{
int* const match_id = static_cast<int*>(context);
*match_id = id;
return 1; // stop scanning
}
, &match_id);
if (scan_result != HS_SUCCESS && scan_result != HS_SCAN_TERMINATED) unsigned match_id;
auto cb = [&match_id](unsigned id, unsigned long long, unsigned long long, unsigned) -> int
{ {
abort(); match_id = id;
} return 1; // stop scanning
};
if (match_id == -1) auto const scan_result =
hs_scan(
thread->db_.get(),
message.data(), message.size(),
0, // no flags
thread->scratch_.get(),
CCallback<decltype(cb)>::invoke, &cb
);
switch (scan_result)
{ {
case HS_SUCCESS:
std::cout << "Unknown snote: " << message << std::endl; std::cout << "Unknown snote: " << message << std::endl;
} break;
else
case HS_SCAN_TERMINATED:
{ {
auto& pattern = patterns[match_id]; auto& pattern = patterns[match_id];
std::match_results<std::string_view::const_iterator> results; std::match_results<std::string_view::const_iterator> results;
@ -145,6 +165,11 @@ auto SnoteThread::start(Connection& connection) -> std::shared_ptr<SnoteThread>
parts.push_back(std::string_view{sub.first, sub.second}); parts.push_back(std::string_view{sub.first, sub.second});
} }
connection.make_event<SnoteEvent>(pattern.tag, std::move(parts)); connection.make_event<SnoteEvent>(pattern.tag, std::move(parts));
break;
}
default:
abort();
} }
} }
}); });

View File

@ -16,7 +16,13 @@ enum class SnoteTag
NickChange, NickChange,
CreateChannel, CreateChannel,
TemporaryKlineExpired, TemporaryKlineExpired,
PropagatedBanExpired,
DisconnectingKlined, DisconnectingKlined,
NewPropagatedKline,
NewTemporaryKline,
LoginAttempts,
PossibleFlooder,
Killed,
}; };
struct SnoteEvent : Event struct SnoteEvent : Event