2018-02-14 21:23:20 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
|
|
|
|
#include "rooms.h"
|
|
|
|
|
|
|
|
using namespace ircd;
|
|
|
|
|
2019-03-28 00:13:10 +01:00
|
|
|
void
|
|
|
|
handle_receipt_m_read(client &client,
|
2019-09-29 01:12:07 +02:00
|
|
|
const m::resource::request &request,
|
2019-03-28 00:13:10 +01:00
|
|
|
const m::room::id &room_id,
|
|
|
|
const m::event::id &event_id);
|
|
|
|
|
2021-02-05 05:28:16 +01:00
|
|
|
static conf::item<bool>
|
|
|
|
receipt_read_attention
|
|
|
|
{
|
|
|
|
{ "name", "ircd.m.receipt.read.attention" },
|
|
|
|
{ "default", false },
|
|
|
|
};
|
|
|
|
|
2019-09-29 01:12:07 +02:00
|
|
|
m::resource::response
|
2018-02-14 21:23:20 +01:00
|
|
|
post__receipt(client &client,
|
2019-09-29 01:12:07 +02:00
|
|
|
const m::resource::request &request,
|
2018-02-14 21:23:20 +01:00
|
|
|
const m::room::id &room_id)
|
|
|
|
{
|
2018-02-15 06:52:19 +01:00
|
|
|
if(request.parv.size() < 3)
|
|
|
|
throw m::NEED_MORE_PARAMS
|
|
|
|
{
|
|
|
|
"receipt type required"
|
|
|
|
};
|
|
|
|
|
2018-02-14 21:23:20 +01:00
|
|
|
const string_view &receipt_type
|
|
|
|
{
|
|
|
|
request.parv[2]
|
|
|
|
};
|
|
|
|
|
2019-03-28 00:13:10 +01:00
|
|
|
if(receipt_type == "m.read")
|
|
|
|
{
|
|
|
|
if(request.parv.size() < 4)
|
|
|
|
throw m::NEED_MORE_PARAMS
|
|
|
|
{
|
|
|
|
"event_id required"
|
|
|
|
};
|
|
|
|
|
|
|
|
m::event::id::buf event_id
|
2019-03-27 23:30:40 +01:00
|
|
|
{
|
2019-03-28 00:13:10 +01:00
|
|
|
url::decode(event_id, request.parv[3])
|
2019-03-27 23:30:40 +01:00
|
|
|
};
|
|
|
|
|
2019-03-28 00:13:10 +01:00
|
|
|
handle_receipt_m_read(client, request, room_id, event_id);
|
|
|
|
}
|
|
|
|
else throw m::UNSUPPORTED
|
2018-02-14 21:23:20 +01:00
|
|
|
{
|
2019-03-28 00:13:10 +01:00
|
|
|
"Sorry, receipt type '%s' is not supported here.",
|
|
|
|
receipt_type
|
2018-02-14 21:23:20 +01:00
|
|
|
};
|
|
|
|
|
2019-09-29 01:12:07 +02:00
|
|
|
return m::resource::response
|
2018-05-30 21:07:03 +02:00
|
|
|
{
|
2019-03-28 00:13:10 +01:00
|
|
|
client, http::OK
|
|
|
|
};
|
|
|
|
}
|
2018-05-30 21:07:03 +02:00
|
|
|
|
2019-03-28 00:13:10 +01:00
|
|
|
void
|
|
|
|
handle_receipt_m_read(client &client,
|
2019-09-29 01:12:07 +02:00
|
|
|
const m::resource::request &request,
|
2019-03-28 00:13:10 +01:00
|
|
|
const m::room::id &room_id,
|
|
|
|
const m::event::id &event_id)
|
|
|
|
{
|
2021-02-05 05:28:16 +01:00
|
|
|
const bool client_hidden
|
|
|
|
{
|
|
|
|
// Spec hidden; defaults to false.
|
|
|
|
request.get("m.hidden", false)
|
|
|
|
};
|
|
|
|
|
2021-01-25 08:48:00 +01:00
|
|
|
const bool freshest
|
|
|
|
{
|
2021-02-05 05:28:16 +01:00
|
|
|
// If the receipt already to be marked hidden we can elide queries.
|
|
|
|
client_hidden
|
|
|
|
|
|
|
|
// Check if deepest receipt in the room.
|
|
|
|
|| m::receipt::freshest(room_id, request.user_id, event_id)
|
2021-01-25 08:48:00 +01:00
|
|
|
};
|
2018-05-30 21:07:03 +02:00
|
|
|
|
2019-09-08 03:04:13 +02:00
|
|
|
const bool ignoring
|
|
|
|
{
|
2021-02-05 05:28:16 +01:00
|
|
|
// If the receipt already to be marked hidden we can elide queries.
|
|
|
|
(client_hidden || !freshest)
|
|
|
|
|
2019-09-08 03:04:13 +02:00
|
|
|
// Check if user wants to prevent sending receipts to this room.
|
2021-02-05 05:28:16 +01:00
|
|
|
|| m::receipt::ignoring(request.user_id, room_id)
|
2018-04-28 11:46:11 +02:00
|
|
|
|
2019-09-08 03:04:13 +02:00
|
|
|
// Check if user wants to prevent based on this event's specifics.
|
|
|
|
|| m::receipt::ignoring(request.user_id, event_id)
|
|
|
|
};
|
2018-05-26 14:27:43 +02:00
|
|
|
|
2021-02-05 05:28:16 +01:00
|
|
|
const bool hidden
|
|
|
|
{
|
|
|
|
false
|
|
|
|
|
|
|
|
// Client wants it hidden.
|
|
|
|
|| client_hidden
|
|
|
|
|
|
|
|
// The freshest receipt is the one on the effectively deepest event
|
|
|
|
// in the room and what we'll end up revealing to the federation.
|
|
|
|
|| !freshest
|
|
|
|
|
|
|
|
// Feature to not send receipts based on configurable state in user's room
|
|
|
|
|| ignoring
|
|
|
|
};
|
|
|
|
|
|
|
|
// When the receipt is not federated (marked as hidden) we don't need
|
|
|
|
// to save it locally unless configured for advanced eye-tracking
|
|
|
|
// features; bail out here.
|
|
|
|
if(!receipt_read_attention && hidden)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const bool add_hidden
|
|
|
|
{
|
|
|
|
// Has to be hidden to add m.hidden
|
|
|
|
hidden
|
|
|
|
|
|
|
|
// Don't need to add hidden if client already made it hidden
|
|
|
|
&& !client_hidden
|
|
|
|
};
|
|
|
|
|
2019-09-06 20:13:58 +02:00
|
|
|
// The options object starts with anything in the request content, which
|
|
|
|
// differs depending on whether this is being called from a /receipt or
|
|
|
|
// /read_markers resource handler. The receipt::read() implementation
|
|
|
|
// looks for properties knowing this call pattern, thus it's best to just
|
|
|
|
// convey the whole content here for forward compat.
|
2019-09-08 03:04:13 +02:00
|
|
|
json::object options
|
2019-09-06 20:13:58 +02:00
|
|
|
{
|
|
|
|
request
|
|
|
|
};
|
|
|
|
|
2019-09-08 03:04:13 +02:00
|
|
|
// Ignoring still involves creating a receipt in all respects except
|
|
|
|
// transmitting it to local and remote parties. This behavior is achieved
|
|
|
|
// by the m.hidden tag. If the options do not contain this tag we add it.
|
|
|
|
std::string options_buf;
|
2021-02-05 05:28:16 +01:00
|
|
|
if(add_hidden)
|
|
|
|
options = options_buf = json::replace(options,
|
|
|
|
{
|
|
|
|
{ "m.hidden", true }
|
|
|
|
});
|
2019-09-08 03:04:13 +02:00
|
|
|
|
2019-09-06 20:13:58 +02:00
|
|
|
m::receipt::read(room_id, request.user_id, event_id, options);
|
2018-04-07 17:26:29 +02:00
|
|
|
}
|