diff --git a/include/ircd/m/event.h b/include/ircd/m/event.h index eea023505..5c45c8aab 100644 --- a/include/ircd/m/event.h +++ b/include/ircd/m/event.h @@ -74,4 +74,5 @@ namespace ircd::m #include "event/cached.h" #include "event/prefetch.h" #include "event/conforms.h" +#include "event/append.h" #include "event/pretty.h" diff --git a/include/ircd/m/event/append.h b/include/ircd/m/event/append.h new file mode 100644 index 000000000..0f378a3cf --- /dev/null +++ b/include/ircd/m/event/append.h @@ -0,0 +1,26 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// 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. + +#pragma once +#define HAVE_IRCD_M_EVENT_APPEND + +namespace ircd::m +{ + struct event_append_opts + { + const event::idx *event_idx {nullptr}; + const string_view *client_txnid {nullptr}; + const id::user *user_id {nullptr}; + const room *user_room {nullptr}; + }; + + void append(json::stack::object &, const event &, const event_append_opts & = {}); + void append(json::stack::array &, const event &, const event_append_opts & = {}); +} diff --git a/ircd/m_event.cc b/ircd/m_event.cc index 93b78b45e..38c57e8f4 100644 --- a/ircd/m_event.cc +++ b/ircd/m_event.cc @@ -143,6 +143,39 @@ ircd::m::pretty_oneline(std::ostream &s, return s; } +/////////////////////////////////////////////////////////////////////////////// +// +// event/append.h +// + +void +ircd::m::append(json::stack::array &array, + const event &event_, + const event_append_opts &opts) +{ + json::stack::object object + { + array + }; + + append(object, event_, opts); +} + +void +ircd::m::append(json::stack::object &object, + const event &event_, + const event_append_opts &opts) +{ + using prototype = void (json::stack::object &, const event &, const event_append_opts &); + + static mods::import call + { + "m_event", "ircd::m::append" + }; + + call(object, event_, opts); +} + /////////////////////////////////////////////////////////////////////////////// // // event/conforms.h diff --git a/modules/m_event.cc b/modules/m_event.cc index dabe6d33f..398935159 100644 --- a/modules/m_event.cc +++ b/modules/m_event.cc @@ -450,6 +450,84 @@ ircd::m::pretty_oneline(std::ostream &s, return s; } +void +IRCD_MODULE_EXPORT +ircd::m::append(json::stack::object &object, + const event &event, + const event_append_opts &opts) +{ + const bool has_event_idx + { + opts.event_idx && *opts.event_idx + }; + + const bool has_client_txnid + { + opts.client_txnid && *opts.client_txnid + }; + + const bool has_user + { + opts.user_id && opts.user_room + }; + + const bool sender_is_user + { + has_user && json::get<"sender"_>(event) == *opts.user_id + }; + + const auto txnid_idx + { + !has_client_txnid && sender_is_user? + opts.user_room->get(std::nothrow, "ircd.client.txnid", at<"event_id"_>(event)): + 0UL + }; + + if(!has_client_txnid && !txnid_idx && sender_is_user) + log::dwarning + { + log, "Could not find transaction_id for %s from %s in %s", + json::get<"event_id"_>(event), + json::get<"sender"_>(event), + json::get<"room_id"_>(event) + }; + + object.append(event); + + if(!has_event_idx && !txnid_idx) + return; + + json::stack::object unsigned_ + { + object, "unsigned" + }; + + if(has_client_txnid) + json::stack::member + { + unsigned_, "transaction_id", *opts.client_txnid + }; + + if(has_event_idx) + json::stack::member + { + unsigned_, "age", json::value + { + long(vm::current_sequence - *opts.event_idx) + } + }; + + if(txnid_idx) + m::get(std::nothrow, txnid_idx, "content", [&unsigned_] + (const json::object &content) + { + json::stack::member + { + unsigned_, "transaction_id", unquote(content.get("transaction_id")) + }; + }); +} + bool IRCD_MODULE_EXPORT ircd::m::event::auth::chain::for_each(const auth::chain &c,