mirror of
https://github.com/matrix-construct/construct
synced 2024-11-29 10:12:39 +01:00
ircd:Ⓜ️:push: Implement r0.6.0-13.13.1.5.3 condition kind subroutine logics.
This commit is contained in:
parent
1d30da7bf3
commit
d1ff1aec74
2 changed files with 230 additions and 0 deletions
|
@ -26,6 +26,8 @@ namespace ircd::m::push
|
|||
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 &);
|
||||
}
|
||||
|
||||
/// PushCondition
|
||||
|
|
228
matrix/push.cc
228
matrix/push.cc
|
@ -8,12 +8,240 @@
|
|||
// 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)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::push::event_match(const cond &cond,
|
||||
const event &event)
|
||||
{
|
||||
assert(json::get<"kind"_>(cond) == "event_match");
|
||||
|
||||
const auto &[path, prop]
|
||||
{
|
||||
rsplit(json::get<"key"_>(cond), '.')
|
||||
};
|
||||
|
||||
json::object targ
|
||||
{
|
||||
event.source
|
||||
};
|
||||
|
||||
const token_view_bool walk
|
||||
{
|
||||
[&targ](const string_view &key)
|
||||
{
|
||||
targ = targ[key];
|
||||
return targ && json::type(targ) == json::OBJECT;
|
||||
}
|
||||
};
|
||||
|
||||
if(!tokens(path, ".", walk))
|
||||
return false;
|
||||
|
||||
//TODO: XXX spec leading/trailing; not imatch
|
||||
const globular_imatch pattern
|
||||
{
|
||||
json::get<"pattern"_>(cond)
|
||||
};
|
||||
|
||||
const json::string &value
|
||||
{
|
||||
targ[prop]
|
||||
};
|
||||
|
||||
return pattern(value);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::push::contains_display_name(const cond &cond,
|
||||
const event &event,
|
||||
const m::user &user)
|
||||
{
|
||||
assert(json::get<"kind"_>(cond) == "contains_display_name");
|
||||
|
||||
const json::object &content
|
||||
{
|
||||
json::get<"content"_>(event)
|
||||
};
|
||||
|
||||
const json::string &body
|
||||
{
|
||||
content["body"]
|
||||
};
|
||||
|
||||
if(!body)
|
||||
return false;
|
||||
|
||||
const m::user::profile profile
|
||||
{
|
||||
user
|
||||
};
|
||||
|
||||
char buf[256];
|
||||
const string_view displayname
|
||||
{
|
||||
profile.get(buf, "displayname")
|
||||
};
|
||||
|
||||
return displayname && has(body, displayname);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::push::sender_notification_permission(const cond &cond,
|
||||
const event &event)
|
||||
{
|
||||
assert(json::get<"kind"_>(cond) == "sender_notification_permission");
|
||||
|
||||
const auto &key
|
||||
{
|
||||
json::get<"key"_>(cond)
|
||||
};
|
||||
|
||||
const m::room room
|
||||
{
|
||||
at<"room_id"_>(event)
|
||||
};
|
||||
|
||||
const room::power power
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
const auto &user_level
|
||||
{
|
||||
power.level_user(at<"sender"_>(event))
|
||||
};
|
||||
|
||||
int64_t required_level
|
||||
{
|
||||
room::power::default_power_level
|
||||
};
|
||||
|
||||
power.for_each("notifications", room::power::closure_bool{[&required_level, &key]
|
||||
(const auto &name, const auto &level)
|
||||
{
|
||||
if(name == key)
|
||||
{
|
||||
required_level = level;
|
||||
return false;
|
||||
}
|
||||
else return true;
|
||||
}});
|
||||
|
||||
const bool ret
|
||||
{
|
||||
user_level >= required_level
|
||||
};
|
||||
|
||||
if(!ret)
|
||||
log::dwarning
|
||||
{
|
||||
log, "Insufficient power level %ld for %s to notify '%s' to %s (require:%ld).",
|
||||
user_level,
|
||||
string_view{json::get<"sender"_>(event)},
|
||||
key,
|
||||
string_view{room.room_id},
|
||||
required_level
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::push::room_member_count(const cond &cond,
|
||||
const event &event)
|
||||
{
|
||||
assert(json::get<"kind"_>(cond) == "room_member_count");
|
||||
|
||||
const m::room room
|
||||
{
|
||||
json::get<"room_id"_>(event)
|
||||
};
|
||||
|
||||
const m::room::members members
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
const auto &is
|
||||
{
|
||||
json::get<"is"_>(cond)
|
||||
};
|
||||
|
||||
string_view valstr(is);
|
||||
while(valstr && !all_of<std::isdigit>(valstr))
|
||||
valstr.pop_front();
|
||||
|
||||
const ulong val
|
||||
{
|
||||
lex_cast<ulong>(valstr)
|
||||
};
|
||||
|
||||
const string_view op
|
||||
{
|
||||
begin(is), begin(valstr)
|
||||
};
|
||||
|
||||
switch(hash(op))
|
||||
{
|
||||
default:
|
||||
case "=="_:
|
||||
return
|
||||
val?
|
||||
members.count("join") == val:
|
||||
members.empty("join");
|
||||
|
||||
case ">="_:
|
||||
return
|
||||
val?
|
||||
members.count("join") >= val:
|
||||
true;
|
||||
|
||||
case "<="_:
|
||||
return
|
||||
val?
|
||||
members.count("join") <= val:
|
||||
members.empty("join");
|
||||
|
||||
case ">"_:
|
||||
return
|
||||
val?
|
||||
members.count("join") > val:
|
||||
!members.empty("join");
|
||||
|
||||
case "<"_:
|
||||
return
|
||||
val > 1?
|
||||
members.count("join") < val:
|
||||
val == 1?
|
||||
members.empty("join"):
|
||||
false;
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// path
|
||||
//
|
||||
|
||||
ircd::m::push::path
|
||||
ircd::m::push::make_path(const event &event)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue