mirror of
https://github.com/matrix-construct/construct
synced 2024-11-17 15:30:52 +01:00
ircd:Ⓜ️:users: Refactor !users room out of the users:: interface.
This commit is contained in:
parent
eb587c6334
commit
0c05241fec
3 changed files with 161 additions and 33 deletions
|
@ -13,7 +13,35 @@
|
||||||
|
|
||||||
namespace ircd::m::users
|
namespace ircd::m::users
|
||||||
{
|
{
|
||||||
bool for_each(const string_view &id_lower_bound, const user::closure_bool &);
|
struct opts extern const default_opts;
|
||||||
|
|
||||||
|
// Iterate the users
|
||||||
|
bool for_each(const opts &, const user::closure_bool &);
|
||||||
bool for_each(const user::closure_bool &);
|
bool for_each(const user::closure_bool &);
|
||||||
void for_each(const user::closure &);
|
|
||||||
|
size_t count(const opts & = default_opts);
|
||||||
|
bool exists(const opts & = default_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shape the query by matching users based on the options filled in.
|
||||||
|
struct ircd::m::users::opts
|
||||||
|
{
|
||||||
|
/// Fill this in to match the localpart of an mxid. If this is empty then
|
||||||
|
/// all localparts can be matched.
|
||||||
|
string_view localpart;
|
||||||
|
|
||||||
|
/// The results match if their localpart startswith the specified localpart.
|
||||||
|
bool localpart_prefix {false};
|
||||||
|
|
||||||
|
/// Fill this in to match the hostpart of an mxid, i.e the origin. If this
|
||||||
|
/// is empty then all servers can be matched.
|
||||||
|
string_view hostpart;
|
||||||
|
|
||||||
|
/// The results match if their hostpart startswith the specified hostpart
|
||||||
|
bool hostpart_prefix {false};
|
||||||
|
|
||||||
|
/// Construction from a single string; decomposes into the options
|
||||||
|
/// based on ad hoc rules, see definition or use default ctor.
|
||||||
|
opts(const string_view &query);
|
||||||
|
opts() = default;
|
||||||
|
};
|
||||||
|
|
|
@ -11152,23 +11152,25 @@ console_cmd__users(opt &out, const string_view &line)
|
||||||
{
|
{
|
||||||
const params param{line, " ",
|
const params param{line, " ",
|
||||||
{
|
{
|
||||||
"prefix"
|
"query"
|
||||||
}};
|
}};
|
||||||
|
|
||||||
const auto prefix
|
const auto query
|
||||||
{
|
{
|
||||||
param.at("prefix", string_view{})
|
param.at("query", string_view{})
|
||||||
};
|
};
|
||||||
|
|
||||||
m::users::for_each(prefix, m::user::closure_bool{[&out, &prefix]
|
const m::users::opts opts
|
||||||
|
{
|
||||||
|
query
|
||||||
|
};
|
||||||
|
|
||||||
|
m::users::for_each(opts, [&out]
|
||||||
(const m::user &user)
|
(const m::user &user)
|
||||||
{
|
{
|
||||||
if(prefix && !startswith(user.user_id, prefix))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
out << user.user_id << std::endl;
|
out << user.user_id << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,49 +8,147 @@
|
||||||
// copyright notice and this permission notice is present in all copies. The
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
// full license for this software is available in the LICENSE file.
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
|
namespace ircd::m::users
|
||||||
|
{
|
||||||
|
static bool for_each_host(const opts &, const user::closure_bool &);
|
||||||
|
static bool for_each_in_host(const opts &, const user::closure_bool &);
|
||||||
|
}
|
||||||
|
|
||||||
ircd::mapi::header
|
ircd::mapi::header
|
||||||
IRCD_MODULE
|
IRCD_MODULE
|
||||||
{
|
{
|
||||||
"Matrix users interface"
|
"Matrix users interface"
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
decltype(ircd::m::users::default_opts)
|
||||||
|
ircd::m::users::default_opts;
|
||||||
|
|
||||||
|
bool
|
||||||
IRCD_MODULE_EXPORT
|
IRCD_MODULE_EXPORT
|
||||||
ircd::m::users::for_each(const user::closure &closure)
|
ircd::m::users::exists(const opts &opts)
|
||||||
{
|
{
|
||||||
for_each(user::closure_bool{[&closure]
|
return !for_each(opts, []
|
||||||
(const m::user &user)
|
(const auto &)
|
||||||
{
|
{
|
||||||
closure(user);
|
// return false to break and have for_each() returns false
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
IRCD_MODULE_EXPORT
|
||||||
|
ircd::m::users::count(const opts &opts)
|
||||||
|
{
|
||||||
|
size_t ret(0);
|
||||||
|
for_each(opts, [&ret](const auto &)
|
||||||
|
{
|
||||||
|
++ret;
|
||||||
return true;
|
return true;
|
||||||
}});
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IRCD_MODULE_EXPORT
|
IRCD_MODULE_EXPORT
|
||||||
ircd::m::users::for_each(const user::closure_bool &closure)
|
ircd::m::users::for_each(const user::closure_bool &closure)
|
||||||
{
|
{
|
||||||
return for_each(string_view{}, closure);
|
return for_each(default_opts, closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IRCD_MODULE_EXPORT
|
IRCD_MODULE_EXPORT
|
||||||
ircd::m::users::for_each(const string_view &lower_bound,
|
ircd::m::users::for_each(const opts &opts,
|
||||||
const user::closure_bool &closure)
|
const user::closure_bool &closure)
|
||||||
{
|
{
|
||||||
const m::room::state state
|
// Note: if opts.hostpart is given then for_each_host() will close over
|
||||||
{
|
// that host, so no branch is needed here.
|
||||||
user::users
|
return for_each_host(opts, closure);
|
||||||
};
|
}
|
||||||
|
|
||||||
return state.for_each("ircd.user", lower_bound, m::room::state::keys_bool{[&closure]
|
bool
|
||||||
(const string_view &user_id)
|
ircd::m::users::for_each_host(const opts &opts,
|
||||||
{
|
const user::closure_bool &closure)
|
||||||
const m::user &user
|
{
|
||||||
{
|
bool ret{true};
|
||||||
user_id
|
events::for_each_origin(opts.hostpart, [&ret, &opts, &closure]
|
||||||
};
|
(const string_view &origin)
|
||||||
|
{
|
||||||
return closure(user);
|
// The events:: iteration interface works with prefixes; if our
|
||||||
}});
|
// user wants to iterate users on exactly a single server, we test
|
||||||
|
// for an exact match here and can break from the loop if no match.
|
||||||
|
if(opts.hostpart && !opts.hostpart_prefix)
|
||||||
|
if(origin != opts.hostpart)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto _opts(opts);
|
||||||
|
_opts.hostpart = origin;
|
||||||
|
ret = for_each_in_host(_opts, closure);
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::m::users::for_each_in_host(const opts &opts,
|
||||||
|
const user::closure_bool &closure)
|
||||||
|
{
|
||||||
|
assert(opts.hostpart);
|
||||||
|
|
||||||
|
bool ret{true};
|
||||||
|
events::for_each_sender(opts.hostpart, [&opts, &ret, &closure]
|
||||||
|
(const id::user &sender)
|
||||||
|
{
|
||||||
|
// The events:: iteration interface only tests if the sender's
|
||||||
|
// hostpart startswith our queried hostpart; we want an exact
|
||||||
|
// match here, otherwise our loop can finish.
|
||||||
|
if(sender.host() != opts.hostpart)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Skip this entry if the user wants a prefix match on the localpart
|
||||||
|
// and this mxid doesn't match.
|
||||||
|
if(opts.localpart && opts.localpart_prefix)
|
||||||
|
if(!startswith(sender.local(), opts.localpart))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Skip this entry if the user wants an exact match on the localpart
|
||||||
|
// and this mxid doesn't match.
|
||||||
|
if(opts.localpart && !opts.localpart_prefix)
|
||||||
|
if(sender.local() != opts.localpart)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Call the user with match.
|
||||||
|
ret = closure(sender);
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
IRCD_MODULE_EXPORT
|
||||||
|
ircd::m::users::opts::opts(const string_view &query)
|
||||||
|
{
|
||||||
|
if(startswith(query, '@') && has(query, ':'))
|
||||||
|
{
|
||||||
|
localpart = split(query, ':').first;
|
||||||
|
hostpart = split(query, ':').second;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(startswith(query, '@'))
|
||||||
|
{
|
||||||
|
localpart = query;
|
||||||
|
localpart_prefix = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(startswith(query, ':'))
|
||||||
|
{
|
||||||
|
hostpart = lstrip(query, ':');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostpart = query;
|
||||||
|
hostpart_prefix = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue