diff --git a/include/ircd/m/room.h b/include/ircd/m/room.h index 19ac13ca2..60d7170a3 100644 --- a/include/ircd/m/room.h +++ b/include/ircd/m/room.h @@ -153,10 +153,12 @@ struct ircd::m::room void get(const string_view &type, const event::closure &) const; bool has(const string_view &type) const; - // misc + // misc / convenience utils bool membership(const m::id::user &, const string_view &membership = "join") const; string_view membership(const mutable_buffer &out, const m::id::user &) const; bool visible(const string_view &mxid, const m::event *const & = nullptr) const; + string_view join_rule(const mutable_buffer &out) const; + bool join_rule(const string_view &rule) const; bool lonly() const; room(const id &room_id, diff --git a/ircd/m/room.cc b/ircd/m/room.cc index 664193838..3f462d2fd 100644 --- a/ircd/m/room.cc +++ b/ircd/m/room.cc @@ -263,6 +263,70 @@ ircd::m::my(const room &room) // room // +/// Test of the join_rule of the room is the argument. +bool +ircd::m::room::join_rule(const string_view &rule) +const +{ + char buf[32]; + return join_rule(mutable_buffer{buf}) == rule; +} + +/// Receive the join_rule of the room into buffer of sufficient size. +/// The protocol does not specify a join_rule string longer than 7 +/// characters but do be considerate of the future. This function +/// properly defaults the string as per the protocol spec. +ircd::string_view +ircd::m::room::join_rule(const mutable_buffer &out) +const +{ + static const string_view default_join_rule + { + "invite" + }; + + string_view ret + { + default_join_rule + }; + + const event::keys::include keys + { + "content" + }; + + const m::event::fetch::opts fopts + { + keys, this->fopts? this->fopts->gopts : db::gopts{} + }; + + const room::state state + { + *this, &fopts + }; + + state.get(std::nothrow, "m.room.join_rules", "", [&ret, &out] + (const m::event &event) + { + const auto &content + { + json::get<"content"_>(event) + }; + + const string_view &rule + { + content.get("join_rule", default_join_rule) + }; + + ret = string_view + { + data(out), copy(out, unquote(rule)) + }; + }); + + return ret; +} + /// The only joined members are from our origin (local only). This indicates /// we won't have any other federation servers to query for room data, nor do /// we need to broadcast events to the federation. This is not an authority