diff --git a/modules/client/sync/rooms/ephemeral/typing.cc b/modules/client/sync/rooms/ephemeral/typing.cc index 0dd85e19c..cae5689e1 100644 --- a/modules/client/sync/rooms/ephemeral/typing.cc +++ b/modules/client/sync/rooms/ephemeral/typing.cc @@ -32,19 +32,31 @@ ircd::m::sync::room_ephemeral_m_typing bool ircd::m::sync::room_ephemeral_m_typing_linear(data &data) { - if(data.event_idx) + if(json::get<"type"_>(*data.event) != "ircd.typing") return false; - assert(data.event); - if(json::get<"type"_>(*data.event) != "m.typing") - return false; - - const m::room room + const m::room target_room { - json::get<"room_id"_>(*data.event) + unquote(json::get<"content"_>(*data.event).get("room_id")) }; - if(!room.membership(data.user, "join")) + // Check if our user is a member of the room targetted by the typing notif + if(!target_room.membership(data.user, "join")) + return false; + + const m::user::id &sender + { + json::get<"sender"_>(*data.event) + }; + + const m::user::room user_room + { + sender + }; + + // Check if the ircd.typing event was sent to the user's user room, + // and not just to any room. + if(json::get<"room_id"_>(*data.event) != user_room.room_id) return false; json::stack::object rooms @@ -59,7 +71,7 @@ ircd::m::sync::room_ephemeral_m_typing_linear(data &data) json::stack::object room_ { - *data.out, room.room_id + *data.out, target_room.room_id }; json::stack::object ephemeral @@ -82,11 +94,25 @@ ircd::m::sync::room_ephemeral_m_typing_linear(data &data) object, "type", "m.typing" }; - json::stack::member + json::stack::object content { - object, "content", json::get<"content"_>(*data.event) + object, "content" }; + json::stack::array user_ids + { + content, "user_ids" + }; + + m::typing::for_each([&user_ids, &target_room] + (const auto &typing) + { + if(json::get<"room_id"_>(typing) != target_room) + return; + + user_ids.append(json::get<"user_id"_>(typing)); + }); + return true; } diff --git a/modules/m_typing.cc b/modules/m_typing.cc index a1e975491..8e2a5340f 100644 --- a/modules/m_typing.cc +++ b/modules/m_typing.cc @@ -122,7 +122,6 @@ commit(const m::typing &edu) // typing edu handler stack (local and remote) // -static void _handle_edu_m_typing(const m::event &, const m::typing &edu); static void _handle_edu_m_typing(const m::event &, const m::typing &edu); static void handle_edu_m_typing(const m::event &, m::vm::eval &); @@ -163,6 +162,11 @@ _handle_edu_m_typing(const m::event &event, if(!json::get<"room_id"_>(edu)) return; + const auto &origin + { + at<"origin"_>(event) + }; + const m::room::id &room_id { at<"room_id"_>(edu) @@ -173,11 +177,6 @@ _handle_edu_m_typing(const m::event &event, at<"user_id"_>(edu) }; - const auto &origin - { - at<"origin"_>(event) - }; - // Check if this server can send an edu for this user. We make an exception // for our server to allow the timeout worker to use this codepath. if(!my_host(origin)) @@ -241,37 +240,39 @@ _handle_edu_m_typing(const m::event &event, return; } + const m::user::room user_room + { + user_id + }; + + const auto &timeout + { + json::get<"timeout"_>(edu)? + json::get<"timeout"_>(edu): + json::get<"typing"_>(edu)? + milliseconds(timeout_max).count(): + 0L + }; + + const auto evid + { + send(user_room, user_id, "ircd.typing", + { + { "room_id", json::get<"room_id"_>(edu) }, + { "typing", json::get<"typing"_>(edu) }, + { "timeout", timeout }, + }) + }; + + char pbuf[32]; log::info { - typing_log, "%s %s %s typing in %s", + typing_log, "%s %s %s typing in %s timeout:%s", origin, string_view{user_id}, json::get<"typing"_>(edu)? "started"_sv : "stopped"_sv, - string_view{room_id} - }; - - m::event typing{event}; - json::get<"room_id"_>(typing) = room_id; - json::get<"type"_>(typing) = "m.typing"_sv; - - // Buffer has to hold user mxid and then some JSON overhead (see below) - char buf[m::id::MAX_SIZE + 65]; - const json::value user_ids[] - { - { user_id } - }; - - json::get<"content"_>(typing) = json::stringify(mutable_buffer{buf}, json::members - { - { "user_ids", { user_ids, size_t(bool(json::get<"typing"_>(edu))) } } - }); - - m::vm::opts vmopts; - vmopts.notify_servers = false; - vmopts.conforming = false; - m::vm::eval eval - { - typing, vmopts + string_view{room_id}, + pretty(pbuf, milliseconds(long(timeout)), 1), }; }