0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-29 18:22:50 +01:00

ircd:Ⓜ️:push: Add match interface; condition table; exception propagation.

This commit is contained in:
Jason Volk 2020-03-20 21:28:12 -07:00
parent f0c08d2a54
commit 435721c971
2 changed files with 190 additions and 24 deletions

View file

@ -20,16 +20,33 @@ namespace ircd::m::push
struct rule;
struct rules;
struct pusher;
struct match;
/// scope, kind, ruleid
using path = std::tuple<string_view, string_view, string_view>;
string_view make_type(const mutable_buffer &, const path &);
path make_path(const string_view &type, const string_view &state_key);
path make_path(const event &);
bool match(const cond &, const event &);
}
struct ircd::m::push::match
:boolean
{
struct opts;
using cond_kind_func = bool (*)(const event &, const cond &, const opts &);
static string_view cond_kind_name[4];
static const cond_kind_func cond_kind[5];
explicit match(const event &, const cond &, const opts &);
explicit match(const event &, const rule &, const opts &);
};
struct ircd::m::push::match::opts
{
m::id::user user_id;
};
/// 13.13.1 I'm your pusher, baby.
struct ircd::m::push::pusher
:json::tuple

View file

@ -8,30 +8,102 @@
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
namespace ircd::m::push
{
static bool room_member_count(const cond &, const event &);
static bool sender_notification_permission(const cond &, const event &);
static bool contains_display_name(const cond &, const event &, const m::user &);
static bool event_match(const cond &, const event &);
}
decltype(ircd::m::push::rule::type_prefix)
ircd::m::push::rule::type_prefix
{
"ircd.push.rule"
};
bool
ircd::m::push::match(const cond &cond,
const event &event)
//
// match
//
namespace ircd::m::push
{
return false;
static bool unknown_condition_kind(const event &, const cond &, const match::opts &);
static bool sender_notification_permission(const event &, const cond &, const match::opts &);
static bool contains_display_name(const event &, const cond &, const match::opts &);
static bool room_member_count(const event &, const cond &, const match::opts &);
static bool event_match(const event &, const cond &, const match::opts &);
}
decltype(ircd::m::push::match::cond_kind)
ircd::m::push::match::cond_kind
{
event_match,
room_member_count,
contains_display_name,
sender_notification_permission,
unknown_condition_kind,
};
decltype(ircd::m::push::match::cond_kind_name)
ircd::m::push::match::cond_kind_name
{
"event_match",
"room_member_count",
"contains_display_name",
"sender_notification_permission",
};
//
// match::match
//
ircd::m::push::match::match(const event &event,
const rule &rule,
const match::opts &opts)
:boolean{[&event, &rule, &opts]
{
const auto &conditions
{
json::get<"conditions"_>(rule)
};
for(const json::object &cond : conditions)
if(!match(event, push::cond(cond), opts))
return false;
return true;
}}
{
}
ircd::m::push::match::match(const event &event,
const cond &cond,
const match::opts &opts)
:boolean{[&event, &cond, &opts]
{
const string_view &kind
{
json::get<"kind"_>(cond)
};
const auto pos
{
indexof(kind, string_views(cond_kind_name))
};
assert(pos <= 5);
const auto &func
{
cond_kind[pos]
};
return func(event, cond, opts);
}}
{
}
//
// push::match condition functors (internal)
//
bool
ircd::m::push::event_match(const cond &cond,
const event &event)
ircd::m::push::event_match(const event &event,
const cond &cond,
const match::opts &opts)
try
{
assert(json::get<"kind"_>(cond) == "event_match");
@ -70,11 +142,27 @@ ircd::m::push::event_match(const cond &cond,
return pattern(value);
}
catch(const ctx::interrupted &)
{
throw;
}
catch(const std::exception &e)
{
log::error
{
log, "Push condition 'event_match' %s :%s",
string_view{event.event_id},
e.what(),
};
return false;
}
bool
ircd::m::push::contains_display_name(const cond &cond,
const event &event,
const m::user &user)
ircd::m::push::contains_display_name(const event &event,
const cond &cond,
const match::opts &opts)
try
{
assert(json::get<"kind"_>(cond) == "contains_display_name");
@ -91,9 +179,13 @@ ircd::m::push::contains_display_name(const cond &cond,
if(!body)
return false;
assert(opts.user_id);
if(unlikely(!opts.user_id))
return false;
const m::user::profile profile
{
user
opts.user_id
};
char buf[256];
@ -104,10 +196,27 @@ ircd::m::push::contains_display_name(const cond &cond,
return displayname && has(body, displayname);
}
catch(const ctx::interrupted &)
{
throw;
}
catch(const std::exception &e)
{
log::error
{
log, "Push condition 'contains_display_name' %s :%s",
string_view{event.event_id},
e.what(),
};
return false;
}
bool
ircd::m::push::sender_notification_permission(const cond &cond,
const event &event)
ircd::m::push::sender_notification_permission(const event &event,
const cond &cond,
const match::opts &opts)
try
{
assert(json::get<"kind"_>(cond) == "sender_notification_permission");
@ -165,10 +274,27 @@ ircd::m::push::sender_notification_permission(const cond &cond,
return ret;
}
catch(const ctx::interrupted &)
{
throw;
}
catch(const std::exception &e)
{
log::error
{
log, "Push condition 'sender_notification_permission' %s :%s",
string_view{event.event_id},
e.what(),
};
return false;
}
bool
ircd::m::push::room_member_count(const cond &cond,
const event &event)
ircd::m::push::room_member_count(const event &event,
const cond &cond,
const match::opts &opts)
try
{
assert(json::get<"kind"_>(cond) == "room_member_count");
@ -237,6 +363,29 @@ ircd::m::push::room_member_count(const cond &cond,
false;
};
}
catch(const ctx::interrupted &)
{
throw;
}
catch(const std::exception &e)
{
log::error
{
log, "Push condition 'room_member_count' %s :%s",
string_view{event.event_id},
e.what(),
};
return false;
}
bool
ircd::m::push::unknown_condition_kind(const event &event,
const cond &cond,
const match::opts &opts)
{
return false;
}
//
// path