mirror of
https://github.com/matrix-construct/construct
synced 2024-12-25 15:04:10 +01:00
ircd:Ⓜ️:room::members: Simplify and improve interface; callsites.
This commit is contained in:
parent
8787dcfaf7
commit
eb3b4d82fb
7 changed files with 195 additions and 248 deletions
|
@ -23,19 +23,18 @@ namespace ircd::m
|
|||
///
|
||||
struct ircd::m::room::members
|
||||
{
|
||||
using closure = std::function<void (const id::user &)>;
|
||||
using closure_bool = std::function<bool (const id::user &)>;
|
||||
using closure_idx = std::function<bool (const id::user &, const event::idx &)>;
|
||||
using closure = std::function<bool (const id::user &)>;
|
||||
|
||||
static string_view membership(const mutable_buffer &out, const event::idx &);
|
||||
static bool membership(const event::idx &, const string_view &);
|
||||
|
||||
m::room room;
|
||||
|
||||
bool for_each(const string_view &membership, const event::closure_bool &) const;
|
||||
void for_each(const string_view &membership, const event::closure &) const;
|
||||
bool for_each(const string_view &membership, const closure_bool &) const;
|
||||
void for_each(const string_view &membership, const closure &) const;
|
||||
bool for_each(const event::closure_bool &) const;
|
||||
void for_each(const event::closure &) const;
|
||||
bool for_each(const closure_bool &) const;
|
||||
void for_each(const closure &) const;
|
||||
bool for_each(const string_view &membership, const closure &) const;
|
||||
bool for_each(const string_view &membership, const closure_idx &) const;
|
||||
bool for_each(const closure &) const;
|
||||
bool for_each(const closure_idx &) const;
|
||||
|
||||
bool empty(const string_view &membership) const;
|
||||
bool empty() const;
|
||||
|
|
15
ircd/m.cc
15
ircd/m.cc
|
@ -3082,15 +3082,14 @@ const
|
|||
};
|
||||
|
||||
room.fopts = &fopts;
|
||||
const m::room::members members{room};
|
||||
return members.for_each(membership, event::closure_bool{[&seen, &closure]
|
||||
(const m::event &event)
|
||||
const m::room::members members
|
||||
{
|
||||
const auto &other
|
||||
{
|
||||
at<"state_key"_>(event)
|
||||
};
|
||||
room
|
||||
};
|
||||
|
||||
return members.for_each(membership, [&seen, &closure]
|
||||
(const user::id &other)
|
||||
{
|
||||
const auto it
|
||||
{
|
||||
seen.lower_bound(other)
|
||||
|
@ -3101,7 +3100,7 @@ const
|
|||
|
||||
seen.emplace_hint(it, std::string{other});
|
||||
return closure(m::user{other});
|
||||
}});
|
||||
});
|
||||
}});
|
||||
}
|
||||
|
||||
|
|
290
ircd/m_room.cc
290
ircd/m_room.cc
|
@ -1237,15 +1237,15 @@ const
|
|||
{
|
||||
user::id::buf ret;
|
||||
const members members{*this};
|
||||
members.for_each(membership, members::closure_bool{[&host, &ret]
|
||||
(const id::user &user_id)
|
||||
members.for_each(membership, [&host, &ret]
|
||||
(const auto &user_id, const auto &event_idx)
|
||||
{
|
||||
if(host && user_id.host() != host)
|
||||
return true;
|
||||
|
||||
ret = user_id;
|
||||
return false;
|
||||
}});
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -3068,57 +3068,16 @@ bool
|
|||
ircd::m::room::members::empty()
|
||||
const
|
||||
{
|
||||
const room::state state
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
// for_each() returns true when it reaches the end of the iteration.
|
||||
return state.for_each("m.room.member", state::closure_bool{[]
|
||||
(const auto &type, const auto &state_key, const auto &event_idx)
|
||||
{
|
||||
return false;
|
||||
}});
|
||||
return empty(string_view{});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::members::empty(const string_view &membership)
|
||||
const
|
||||
{
|
||||
const room::state state
|
||||
return for_each(membership, closure{[](const auto &)
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
// joined members optimization. Only possible when seeking
|
||||
// membership="join" on the present state of the room.
|
||||
if(membership == "join" && state.present())
|
||||
{
|
||||
// _for_each() returns true when it reaches the end of the iteration.
|
||||
const room::origins origins{room};
|
||||
return origins._for_each(origins, []
|
||||
(const string_view &)
|
||||
{
|
||||
// closure returns false to break causing _for_each() to return false.
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// for_each() returns true when it reaches the end of the iteration.
|
||||
return state.for_each("m.room.member", state::closure_bool{[&membership]
|
||||
(const auto &type, const auto &state_key, const auto &event_idx)
|
||||
{
|
||||
// return false if the query succeeds, breaking the iteration.
|
||||
return !m::query(std::nothrow, event_idx, "content", [&membership]
|
||||
(const json::object &content)
|
||||
{
|
||||
const json::string &content_membership
|
||||
{
|
||||
content["membership"]
|
||||
};
|
||||
|
||||
return !membership || content_membership == membership;
|
||||
});
|
||||
return false;
|
||||
}});
|
||||
}
|
||||
|
||||
|
@ -3126,178 +3085,98 @@ size_t
|
|||
ircd::m::room::members::count()
|
||||
const
|
||||
{
|
||||
const room::state state
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
return state.count("m.room.member");
|
||||
return count(string_view{});
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::room::members::count(const string_view &membership)
|
||||
const
|
||||
{
|
||||
// Allow empty membership string to count all memberships
|
||||
if(!membership)
|
||||
return count();
|
||||
|
||||
// joined members optimization. Only possible when seeking
|
||||
// membership="join" on the present state of the room.
|
||||
if(membership == "join" && state{room}.present())
|
||||
{
|
||||
size_t ret{0};
|
||||
const room::origins origins{room};
|
||||
origins._for_each(origins, [&ret](const string_view &)
|
||||
{
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const event::keys::include keys
|
||||
{
|
||||
"content",
|
||||
};
|
||||
|
||||
const m::event::fetch::opts fopts
|
||||
{
|
||||
keys, room.fopts? room.fopts->gopts : db::gopts{}
|
||||
};
|
||||
|
||||
const room::state state
|
||||
{
|
||||
room, &fopts
|
||||
};
|
||||
|
||||
size_t ret{0};
|
||||
state.for_each("m.room.member", event::closure{[&ret, &membership]
|
||||
(const m::event &event)
|
||||
this->for_each(membership, room::members::closure{[&ret]
|
||||
(const id::user &)
|
||||
{
|
||||
ret += m::membership(event) == membership;
|
||||
++ret;
|
||||
return true;
|
||||
}});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::members::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::members::for_each(const closure_bool &closure)
|
||||
ircd::m::room::members::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
return for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::members::for_each(const event::closure &closure)
|
||||
bool
|
||||
ircd::m::room::members::for_each(const closure_idx &closure)
|
||||
const
|
||||
{
|
||||
for_each(string_view{}, closure);
|
||||
return for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::members::for_each(const event::closure_bool &closure)
|
||||
ircd::m::room::members::for_each(const string_view &membership,
|
||||
const closure_idx &closure)
|
||||
const
|
||||
{
|
||||
const room::state state{room};
|
||||
return state.for_each("m.room.member", event::closure_bool{[&closure]
|
||||
(const m::event &event)
|
||||
const m::room::state state
|
||||
{
|
||||
return closure(event);
|
||||
}});
|
||||
room
|
||||
};
|
||||
|
||||
const bool present
|
||||
{
|
||||
state.present()
|
||||
};
|
||||
|
||||
// joined members optimization. Only possible when seeking
|
||||
// membership="join" on the present state of the room.
|
||||
if(membership == "join" && present)
|
||||
return this->for_each(membership, [&closure, &state, this]
|
||||
(const id::user &member)
|
||||
{
|
||||
const auto event_idx
|
||||
{
|
||||
state.get(std::nothrow, "m.room.member", member)
|
||||
};
|
||||
|
||||
assert(event_idx);
|
||||
return event_idx?
|
||||
closure(member, event_idx):
|
||||
true;
|
||||
});
|
||||
|
||||
return state.for_each("m.room.member", [this, &membership, &closure]
|
||||
(const string_view &type, const string_view &state_key, const event::idx &event_idx)
|
||||
{
|
||||
return !membership || this->membership(event_idx, membership)?
|
||||
closure(state_key, event_idx):
|
||||
true;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
ircd::m::room::members::for_each(const string_view &membership,
|
||||
const closure &closure)
|
||||
const
|
||||
{
|
||||
for_each(membership, closure_bool{[&closure]
|
||||
(const user::id &user_id)
|
||||
const m::room::state state
|
||||
{
|
||||
closure(user_id);
|
||||
return true;
|
||||
}});
|
||||
}
|
||||
|
||||
/// Iterate the mxid's of the users in the room, optionally with a specific
|
||||
/// membership state. This query contains internal optimizations as the closure
|
||||
/// only requires a user::id. The db::gopts set in the room.fopts pointer is
|
||||
/// still used if provided.
|
||||
bool
|
||||
ircd::m::room::members::for_each(const string_view &membership,
|
||||
const closure_bool &closure)
|
||||
const
|
||||
{
|
||||
// Setup the list of event fields to fetch for the closure
|
||||
static const event::keys::include keys
|
||||
{
|
||||
"state_key", "content",
|
||||
room
|
||||
};
|
||||
|
||||
// In this case the fetch opts isn't static so it can maintain the
|
||||
// previously given db::gopts, but it will use our keys list.
|
||||
const m::event::fetch::opts fopts
|
||||
const bool present
|
||||
{
|
||||
keys, room.fopts? room.fopts->gopts : db::gopts{}
|
||||
state.present()
|
||||
};
|
||||
|
||||
// Stack-over the the current fetch opts with our new opts for this query,
|
||||
// putting them back when we're finished. This requires a const_cast which
|
||||
// should be okay here.
|
||||
auto &room(const_cast<m::room &>(this->room));
|
||||
const scope_restore theirs
|
||||
{
|
||||
room.fopts, &fopts
|
||||
};
|
||||
|
||||
return for_each(membership, event::closure_bool{[&closure]
|
||||
(const event &event)
|
||||
{
|
||||
const user::id &user_id
|
||||
{
|
||||
at<"state_key"_>(event)
|
||||
};
|
||||
|
||||
return closure(user_id);
|
||||
}});
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::members::for_each(const string_view &membership,
|
||||
const event::closure &closure)
|
||||
const
|
||||
{
|
||||
for_each(membership, event::closure_bool{[&closure]
|
||||
(const m::event &event)
|
||||
{
|
||||
closure(event);
|
||||
return true;
|
||||
}});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::members::for_each(const string_view &membership,
|
||||
const event::closure_bool &closure)
|
||||
const
|
||||
{
|
||||
if(empty(membership))
|
||||
return for_each(closure);
|
||||
|
||||
// joined members optimization. Only possible when seeking
|
||||
// membership="join" on the present state of the room.
|
||||
if(!room.event_id && membership == "join")
|
||||
{
|
||||
const room::origins origins{room};
|
||||
return origins._for_each(origins, [&closure, this]
|
||||
if(membership == "join" && present)
|
||||
return room::origins::_for_each(room, [this, &closure]
|
||||
(const string_view &key)
|
||||
{
|
||||
const string_view &member
|
||||
|
@ -3305,26 +3184,49 @@ const
|
|||
std::get<1>(dbs::room_joined_key(key))
|
||||
};
|
||||
|
||||
bool ret{true};
|
||||
room.get(std::nothrow, "m.room.member", member, event::closure{[&closure, &ret]
|
||||
(const event &event)
|
||||
{
|
||||
ret = closure(event);
|
||||
}});
|
||||
|
||||
return ret;
|
||||
return closure(member);
|
||||
});
|
||||
}
|
||||
|
||||
return for_each(event::closure_bool{[&membership, &closure]
|
||||
(const event &event)
|
||||
return this->for_each(membership, [&closure]
|
||||
(const auto &user_id, const auto &event_idx)
|
||||
{
|
||||
if(m::membership(event) == membership)
|
||||
if(!closure(event))
|
||||
return false;
|
||||
return closure(user_id);
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}});
|
||||
bool
|
||||
ircd::m::room::members::membership(const event::idx &event_idx,
|
||||
const string_view &membership)
|
||||
{
|
||||
return m::query(std::nothrow, event_idx, "content", [&membership]
|
||||
(const json::object &content)
|
||||
{
|
||||
const json::string &content_membership
|
||||
{
|
||||
content["membership"]
|
||||
};
|
||||
|
||||
return content_membership && content_membership == membership;
|
||||
});
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::room::members::membership(const mutable_buffer &out,
|
||||
const event::idx &event_idx)
|
||||
{
|
||||
return m::query(std::nothrow, event_idx, "content", [&out]
|
||||
(const json::object &content) -> string_view
|
||||
{
|
||||
const json::string &content_membership
|
||||
{
|
||||
content["membership"]
|
||||
};
|
||||
|
||||
return strlcpy
|
||||
{
|
||||
out, content_membership
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -596,7 +596,7 @@ initialsync_room_ephemeral_events(client &client,
|
|||
//TODO: We're skipping receipts from members who left so we enjoy the
|
||||
//TODO: joined members optimizations. Need to figure out if anyone
|
||||
//TODO: left in the synced timeline and include them manually.
|
||||
members.for_each("join", m::room::members::closure{[&events, &room]
|
||||
members.for_each("join", [&events, &room]
|
||||
(const m::user &user)
|
||||
{
|
||||
const m::user::room user_room{user};
|
||||
|
@ -644,7 +644,9 @@ initialsync_room_ephemeral_events(client &client,
|
|||
};
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -99,15 +99,23 @@ get__members(client &client,
|
|||
room
|
||||
};
|
||||
|
||||
members.for_each(membership, m::event::closure_bool{[&request, &chunk, ¬_membership]
|
||||
(const m::event &event)
|
||||
members.for_each(membership, [&request, &chunk, ¬_membership]
|
||||
(const m::user::id &member, const m::event::idx &event_idx)
|
||||
{
|
||||
if(m::membership(event) == not_membership)
|
||||
if(m::room::members::membership(event_idx, not_membership))
|
||||
return true;
|
||||
|
||||
const m::event::fetch event
|
||||
{
|
||||
event_idx, std::nothrow
|
||||
};
|
||||
|
||||
if(!event.valid)
|
||||
return true;
|
||||
|
||||
chunk.append(event);
|
||||
return true;
|
||||
}});
|
||||
});
|
||||
|
||||
return std::move(response);
|
||||
}
|
||||
|
@ -161,17 +169,9 @@ get__joined_members(client &client,
|
|||
room
|
||||
};
|
||||
|
||||
members.for_each("join", m::room::members::closure{[&joined, &room]
|
||||
(const m::user::id &user_id)
|
||||
members.for_each("join", [&joined, &room]
|
||||
(const m::user::id &user_id, const m::event::idx &event_idx)
|
||||
{
|
||||
const m::event::idx &event_idx
|
||||
{
|
||||
room.get(std::nothrow, "m.room.member", user_id)
|
||||
};
|
||||
|
||||
if(!event_idx)
|
||||
return;
|
||||
|
||||
json::stack::object room_member
|
||||
{
|
||||
joined, user_id
|
||||
|
@ -186,7 +186,9 @@ get__joined_members(client &client,
|
|||
room_member, key, val
|
||||
};
|
||||
});
|
||||
}});
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return std::move(response);
|
||||
}
|
||||
|
|
|
@ -8217,9 +8217,9 @@ console_cmd__room__members(opt &out, const string_view &line)
|
|||
m::room_id(param.at(0))
|
||||
};
|
||||
|
||||
const string_view membership
|
||||
const string_view &membership
|
||||
{
|
||||
param.at(1, "join"_sv)
|
||||
param[1]
|
||||
};
|
||||
|
||||
const m::room room
|
||||
|
@ -8232,14 +8232,30 @@ console_cmd__room__members(opt &out, const string_view &line)
|
|||
room
|
||||
};
|
||||
|
||||
const m::room::members::closure closure{[&out, &membership]
|
||||
(const m::user::id &user_id)
|
||||
if(membership)
|
||||
{
|
||||
out << std::setw(8) << std::left << membership
|
||||
<< " " << user_id << std::endl;
|
||||
}};
|
||||
members.for_each(membership, [&out, &membership]
|
||||
(const m::user::id &user_id)
|
||||
{
|
||||
out << std::setw(8) << std::left << membership
|
||||
<< " " << user_id << std::endl;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
members.for_each(membership, [&out]
|
||||
(const m::user::id &user_id, const m::event::idx &event_idx)
|
||||
{
|
||||
char buf[32];
|
||||
out << std::setw(8) << std::left << m::room::members::membership(buf, event_idx)
|
||||
<< " " << user_id << std::endl;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
members.for_each(membership, closure);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -8271,9 +8287,18 @@ console_cmd__room__members__events(opt &out, const string_view &line)
|
|||
room
|
||||
};
|
||||
|
||||
const auto closure{[&out](const m::event &event)
|
||||
const auto closure{[&out](const auto &user_id, const auto &event_idx)
|
||||
{
|
||||
const m::event::fetch event
|
||||
{
|
||||
event_idx, std::nothrow
|
||||
};
|
||||
|
||||
if(!event.valid)
|
||||
return true;
|
||||
|
||||
out << pretty_oneline(event) << std::endl;
|
||||
return true;
|
||||
}};
|
||||
|
||||
members.for_each(membership, closure);
|
||||
|
@ -8346,12 +8371,30 @@ console_cmd__room__members__origin(opt &out, const string_view &line)
|
|||
};
|
||||
|
||||
members.for_each(membership, [&out, &origin]
|
||||
(const m::event &event)
|
||||
(const auto &user_id, const auto &event_idx)
|
||||
{
|
||||
if(json::get<"origin"_>(event) != origin)
|
||||
return;
|
||||
const bool same_origin
|
||||
{
|
||||
m::query(std::nothrow, event_idx, "origin", [&origin]
|
||||
(const auto &_origin)
|
||||
{
|
||||
return _origin == origin;
|
||||
})
|
||||
};
|
||||
|
||||
if(!same_origin)
|
||||
return true;
|
||||
|
||||
const m::event::fetch event
|
||||
{
|
||||
event_idx, std::nothrow
|
||||
};
|
||||
|
||||
if(!event.valid)
|
||||
return true;
|
||||
|
||||
out << pretty_oneline(event) << std::endl;
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
|
@ -8404,12 +8447,12 @@ console_cmd__room__members__read(opt &out, const string_view &line)
|
|||
<< std::endl;
|
||||
}};
|
||||
|
||||
const auto member_closure{[&room_id, event_closure]
|
||||
(const m::event &event)
|
||||
members.for_each(membership, [&room_id, &event_closure]
|
||||
(const m::user::id &user_id, const m::event::idx &event_idx)
|
||||
{
|
||||
const m::user user
|
||||
{
|
||||
at<"state_key"_>(event)
|
||||
user_id
|
||||
};
|
||||
|
||||
static const m::event::fetch::opts fopts
|
||||
|
@ -8429,9 +8472,9 @@ console_cmd__room__members__read(opt &out, const string_view &line)
|
|||
};
|
||||
|
||||
user_room.get(std::nothrow, "ircd.read", room_id, event_closure);
|
||||
}};
|
||||
return true;
|
||||
});
|
||||
|
||||
members.for_each(membership, member_closure);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ _join_room__m_direct(const m::event &event,
|
|||
|
||||
m::user::id::buf other_person;
|
||||
const m::room::members members{room};
|
||||
members.for_each(m::room::members::closure_bool{[&user_id, &other_person]
|
||||
members.for_each([&user_id, &other_person]
|
||||
(const auto &other_id)
|
||||
{
|
||||
if(other_id == user_id)
|
||||
|
@ -83,7 +83,7 @@ _join_room__m_direct(const m::event &event,
|
|||
|
||||
other_person = other_id;
|
||||
return false;
|
||||
}});
|
||||
});
|
||||
|
||||
if(!other_person)
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue