From 035dbbab88879c3df19c452fe390e0aee3a5f6e0 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Wed, 28 Aug 2019 16:22:53 -0700 Subject: [PATCH] ircd::m::typing: Add user control over sending and receiving typing events per room. --- include/ircd/m/typing.h | 4 ++ modules/client/sync/rooms/ephemeral/typing.cc | 4 ++ modules/m_typing.cc | 39 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/include/ircd/m/typing.h b/include/ircd/m/typing.h index b577177b0..59004035e 100644 --- a/include/ircd/m/typing.h +++ b/include/ircd/m/typing.h @@ -40,6 +40,10 @@ struct ircd::m::typing //NOTE: no yielding in this iteration. static bool for_each(const closure &); + // Get whether a user enabled typing events for a room. The type string + // can be "send" or "sync" prevent typing one's events from being sent or + // others' from being sync'ed, respectively + static bool allow(const id::user &, const id::room &, const string_view &type); using edu::m_typing::m_typing; }; diff --git a/modules/client/sync/rooms/ephemeral/typing.cc b/modules/client/sync/rooms/ephemeral/typing.cc index 307d00c9c..de71bbe2f 100644 --- a/modules/client/sync/rooms/ephemeral/typing.cc +++ b/modules/client/sync/rooms/ephemeral/typing.cc @@ -59,6 +59,10 @@ ircd::m::sync::room_ephemeral_m_typing_linear(data &data) if(json::get<"room_id"_>(*data.event) != user_room.room_id) return false; + // Check if the user does not want to receive typing events for this room. + if(!m::typing::allow(data.user, *data.room, "sync")) + return false; + json::stack::object rooms { *data.out, "rooms" diff --git a/modules/m_typing.cc b/modules/m_typing.cc index 894af1ecf..f9ea4fc87 100644 --- a/modules/m_typing.cc +++ b/modules/m_typing.cc @@ -216,6 +216,11 @@ ircd::m::typing::commit::commit(const m::typing &edu) string_view{room.room_id} }; + // If the user does not want to transmit typing events to this room, + // bail out here. + if(!allow(at<"user_id"_>(edu), room, "send")) + return; + // Clients like Riot will send erroneous and/or redundant typing requests // for example requesting typing=false when the state already =false. // We don't want to tax the vm::eval for this noise so we try to update @@ -243,6 +248,40 @@ ircd::m::typing::commit::commit(const m::typing &edu) }; } +bool +IRCD_MODULE_EXPORT +ircd::m::typing::allow(const user::id &user_id, + const room::id &room_id, + const string_view &allow_type) +{ + const user::room user_room + { + user_id + }; + + const room::state state + { + user_room + }; + + char buf[event::TYPE_MAX_SIZE+1] + { + "ircd.typing.disable." + }; + + const string_view &type + { + strlcat{buf, allow_type} + }; + + const string_view &state_key + { + room_id + }; + + return !state.has(type, state_key); +} + bool IRCD_MODULE_EXPORT ircd::m::typing::for_each(const closure &closure)