diff --git a/modules/m_room_history_visibility.cc b/modules/m_room_history_visibility.cc index 20a7bf885..3737407e0 100644 --- a/modules/m_room_history_visibility.cc +++ b/modules/m_room_history_visibility.cc @@ -16,22 +16,111 @@ IRCD_MODULE "Matrix m.room.history_visibility" }; -namespace ircd::m +static bool +_visible_(const m::event &event, + const m::user::id &user_id, + const m::room &room, + const string_view &history_visibility) { - extern hook::site<> visible_hook; + char membership_buf[32]; + const string_view membership + { + room.membership(membership_buf, user_id) + }; + + if(membership == "join") + return true; + + if(history_visibility == "joined") + return false; + + if(history_visibility == "invited") + return membership == "invite"; + + assert(history_visibility == "shared"); + const m::room present{room.room_id}; + return present.membership(user_id, "join"); } -decltype(ircd::m::visible_hook) -ircd::m::visible_hook +static bool +_visible_(const m::event &event, + const m::node::id &node_id, + const m::room &room, + const string_view &history_visibility) { - { "name", "m.event.visible" } -}; + return true; +} + +static bool +_visible(const m::event &event, + const string_view &mxid, + const m::room &room, + const string_view &history_visibility) +{ + if(history_visibility == "world_readable") + return true; + + if(empty(mxid)) + return false; + + switch(m::sigil(mxid)) + { + case m::id::USER: + return _visible_(event, m::user::id{mxid}, room, history_visibility); + + case m::id::NODE: + return _visible_(event, m::node::id{mxid}, room, history_visibility); + + default: throw m::UNSUPPORTED + { + "Cannot determine visibility for '%s' mxids", + reflect(m::sigil(mxid)) + }; + } +} extern "C" bool visible(const m::event &event, const string_view &mxid) { - return true; + const m::room room + { + at<"room_id"_>(event), at<"event_id"_>(event) + }; + + static const m::event::fetch::opts fopts + { + m::event::keys::include{"content"} + }; + + const m::room::state state + { + room, &fopts + }; + + bool ret{false}; + const bool has_state_event + { + state.get(std::nothrow, "m.room.history_visibility", "", [&] + (const m::event &event) + { + const json::object &content + { + json::get<"content"_>(event) + }; + + const string_view &history_visibility + { + unquote(content.get("history_visibility", "shared")) + }; + + ret = _visible(event, mxid, room, history_visibility); + }) + }; + + return !has_state_event? + _visible(event, mxid, room, "shared"): + ret; } static void @@ -56,18 +145,3 @@ _changed_visibility_hookfn { "type", "m.room.history_visibility" }, } }; - -static void -_event_visible(const m::event &event) -{ - -} - -const m::hookfn<> -_event_visible_hookfn -{ - _event_visible, - { - { "_site", "m.event.visible" }, - } -};