0
0
Fork 0
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:
Jason Volk 2020-03-20 17:19:38 -07:00
parent 1d30da7bf3
commit d1ff1aec74
2 changed files with 230 additions and 0 deletions

View file

@ -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

View file

@ -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)
{