diff --git a/include/ircd/m/user.h b/include/ircd/m/user.h index 00bdef1f2..5bf9a755a 100644 --- a/include/ircd/m/user.h +++ b/include/ircd/m/user.h @@ -26,6 +26,7 @@ struct ircd::m::user struct room; struct rooms; struct mitsein; + struct events; using id = m::id::user; using closure = std::function; using closure_bool = std::function; @@ -165,6 +166,22 @@ struct ircd::m::user::mitsein mitsein(const m::user &user); }; +/// Interface to all events from a user (sender) +struct ircd::m::user::events +{ + using idx_closure_bool = std::function; + using closure_bool = std::function; + + m::user user; + + public: + bool for_each(const idx_closure_bool &) const; + bool for_each(const closure_bool &) const; + size_t count() const; + + events(const m::user &user); +}; + inline ircd::m::user::operator const ircd::m::user::id &() const diff --git a/ircd/m/m.cc b/ircd/m/m.cc index 4e726f894..b9538c494 100644 --- a/ircd/m/m.cc +++ b/ircd/m/m.cc @@ -2235,6 +2235,77 @@ const }}); } +// +// user::events +// + +ircd::m::user::events::events(const m::user &user) +:user{user} +{ +} + +size_t +ircd::m::user::events::count() +const +{ + size_t ret{0}; + for_each([&ret](const event::idx &) + { + ++ret; + return true; + }); + + return ret; +} + +bool +ircd::m::user::events::for_each(const closure_bool &closure) +const +{ + m::event::fetch event; + return for_each([&closure, &event] + (const event::idx &event_idx) + { + if(!seek(event, event_idx, std::nothrow)) + return true; + + return closure(event); + }); +} + +bool +ircd::m::user::events::for_each(const idx_closure_bool &closure) +const +{ + const m::user::rooms rooms + { + user + }; + + return rooms.for_each(rooms::closure_bool{[this, &closure] + (const m::room &room, const string_view &membership) + { + m::room::messages it + { + room + }; + + bool ret{true}; + for(; ret && it; --it) + { + const auto &idx{it.event_idx()}; + m::get(std::nothrow, idx, "sender", [this, &closure, &idx, &ret] + (const string_view &sender) + { + if(sender == this->user.user_id) + ret = closure(idx); + }); + } + + return ret; + }}); +} + /////////////////////////////////////////////////////////////////////////////// // // m/room.h diff --git a/modules/console.cc b/modules/console.cc index 401cc4073..084bda32f 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -5850,6 +5850,51 @@ console_cmd__user__filter(opt &out, const string_view &line) return true; } +bool +console_cmd__user__events(opt &out, const string_view &line) +{ + const params param{line, " ", + { + "user_id", "limit" + }}; + + const m::user::events user + { + m::user(param.at("user_id")) + }; + + size_t limit + { + param.at("limit", 32) + }; + + user.for_each([&out, &limit] + (const m::event &event) + { + out << pretty_oneline(event) << std::endl;; + return bool(--limit); + }); + + return true; +} + +bool +console_cmd__user__events__count(opt &out, const string_view &line) +{ + const params param{line, " ", + { + "user_id" + }}; + + const m::user::events user + { + m::user(param.at("user_id")) + }; + + out << user.count() << std::endl; + return true; +} + // // node //