mirror of
https://github.com/matrix-construct/construct
synced 2024-12-25 23:14:13 +01:00
modules/m_relation: Add hook to discover and fetch events from m_relates_to.
This commit is contained in:
parent
14fffaeded
commit
59ad4731ae
3 changed files with 150 additions and 0 deletions
|
@ -71,6 +71,7 @@ ircd::m::matrix::module_names
|
|||
"m_presence",
|
||||
"m_profile",
|
||||
"m_receipt",
|
||||
"m_relation",
|
||||
"m_room_aliases",
|
||||
"m_room_canonical_alias",
|
||||
"m_room_create",
|
||||
|
|
|
@ -101,6 +101,7 @@ m_noop_la_SOURCES = m_noop.cc
|
|||
m_presence_la_SOURCES = m_presence.cc
|
||||
m_profile_la_SOURCES = m_profile.cc
|
||||
m_receipt_la_SOURCES = m_receipt.cc
|
||||
m_relation_la_SOURCES = m_relation.cc
|
||||
m_room_aliases_la_SOURCES = m_room_aliases.cc
|
||||
m_room_canonical_alias_la_SOURCES = m_room_canonical_alias.cc
|
||||
m_room_create_la_SOURCES = m_room_create.cc
|
||||
|
@ -130,6 +131,7 @@ m_module_LTLIBRARIES = \
|
|||
m_presence.la \
|
||||
m_profile.la \
|
||||
m_receipt.la \
|
||||
m_relation.la \
|
||||
m_room_aliases.la \
|
||||
m_room_canonical_alias.la \
|
||||
m_room_create.la \
|
||||
|
|
147
modules/m_relation.cc
Normal file
147
modules/m_relation.cc
Normal file
|
@ -0,0 +1,147 @@
|
|||
// The Construct
|
||||
//
|
||||
// Copyright (C) The Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2020 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.
|
||||
|
||||
namespace ircd::m::relation
|
||||
{
|
||||
static void handle_fetch(const event &, vm::eval &);
|
||||
extern hookfn<vm::eval &> fetch_hook;
|
||||
extern conf::item<seconds> fetch_timeout;
|
||||
extern conf::item<bool> fetch_enable;
|
||||
}
|
||||
|
||||
ircd::mapi::header
|
||||
IRCD_MODULE
|
||||
{
|
||||
"Matrix relations"
|
||||
};
|
||||
|
||||
decltype(ircd::m::relation::fetch_enable)
|
||||
ircd::m::relation::fetch_enable
|
||||
{
|
||||
{ "name", "ircd.m.relation.fetch.enable" },
|
||||
{ "default", true },
|
||||
};
|
||||
|
||||
decltype(ircd::m::relation::fetch_timeout)
|
||||
ircd::m::relation::fetch_timeout
|
||||
{
|
||||
{ "name", "ircd.m.relation.fetch.timeout" },
|
||||
{ "default", 5L },
|
||||
};
|
||||
|
||||
decltype(ircd::m::relation::fetch_hook)
|
||||
ircd::m::relation::fetch_hook
|
||||
{
|
||||
handle_fetch,
|
||||
{
|
||||
{ "_site", "vm.fetch" },
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
ircd::m::relation::handle_fetch(const event &event,
|
||||
vm::eval &eval)
|
||||
try
|
||||
{
|
||||
assert(eval.opts);
|
||||
const auto &opts{*eval.opts};
|
||||
if(!opts.fetch_prev)
|
||||
return;
|
||||
|
||||
if(!fetch_enable)
|
||||
return;
|
||||
|
||||
if(my(event))
|
||||
return;
|
||||
|
||||
// event must be in a room for now; we won't have context until dht
|
||||
if(!json::get<"room_id"_>(event))
|
||||
return;
|
||||
|
||||
const auto &content
|
||||
{
|
||||
json::get<"content"_>(event)
|
||||
};
|
||||
|
||||
const json::object &m_relates_to
|
||||
{
|
||||
content["m.relates_to"]
|
||||
};
|
||||
|
||||
if(!m_relates_to || json::type(m_relates_to) != json::OBJECT)
|
||||
return;
|
||||
|
||||
const event::id &event_id
|
||||
{
|
||||
m_relates_to["event_id"]
|
||||
};
|
||||
|
||||
// If the relates_to is a prev_event then the vm::fetch unit will perform
|
||||
// the fetch so this will just be redundant and we can bail.
|
||||
const event::prev prev{event};
|
||||
if(prev.prev_events_has(event_id))
|
||||
return;
|
||||
|
||||
if(likely(m::exists(event_id)))
|
||||
return;
|
||||
|
||||
log::dwarning
|
||||
{
|
||||
log, "%s in %s by %s relates to missing %s; fetching...",
|
||||
string_view(event.event_id),
|
||||
string_view(at<"room_id"_>(event)),
|
||||
string_view(at<"sender"_>(event)),
|
||||
string_view(event_id),
|
||||
};
|
||||
|
||||
m::fetch::opts fetch_opts;
|
||||
fetch_opts.op = m::fetch::op::event;
|
||||
fetch_opts.room_id = at<"room_id"_>(event);
|
||||
fetch_opts.event_id = event_id;
|
||||
auto request
|
||||
{
|
||||
m::fetch::start(fetch_opts)
|
||||
};
|
||||
|
||||
const auto response
|
||||
{
|
||||
request.get(seconds(fetch_timeout))
|
||||
};
|
||||
|
||||
const m::event result
|
||||
{
|
||||
json::object
|
||||
{
|
||||
response
|
||||
}
|
||||
};
|
||||
|
||||
auto eval_opts(opts);
|
||||
eval_opts.fetch_prev = false;
|
||||
eval_opts.fetch_state = false;
|
||||
vm::eval
|
||||
{
|
||||
result, eval_opts
|
||||
};
|
||||
}
|
||||
catch(const ctx::interrupted &)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::derror
|
||||
{
|
||||
log, "Failed to fetch relation for %s in %s :%s",
|
||||
string_view(event.event_id),
|
||||
string_view(json::get<"room_id"_>(event)),
|
||||
e.what(),
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue