// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2019 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. namespace ircd::m { static resource::response get_notifications(client &, const resource::request &); extern const event::keys notification_event_keys; extern conf::item notifications_limit_default; extern resource::method notifications_method_get; extern resource notifications_resource; } ircd::mapi::header IRCD_MODULE { "Client r0.6.0-13.13.1.3.1 :Listing Notifications" }; decltype(ircd::m::notifications_resource) ircd::m::notifications_resource { "/_matrix/client/r0/notifications", { "(r0.6.0-13.13.1.3.1) Listing Notifications" } }; decltype(ircd::m::notifications_method_get) ircd::m::notifications_method_get { notifications_resource, "GET", get_notifications, { notifications_method_get.REQUIRES_AUTH } }; decltype(ircd::m::notifications_limit_default) ircd::m::notifications_limit_default { { "name", "ircd.client.notifications.limit.default" }, { "default", 12 } }; decltype(ircd::m::notification_event_keys) ircd::m::notification_event_keys { event::keys::include { "event_id", "content", "origin_server_ts", "sender", "state_key", "type", } }; ircd::m::resource::response ircd::m::get_notifications(client &client, const resource::request &request) { const string_view &from { request.query["from"] }; const string_view &only { request.query["only"] }; const ushort limit { request.query.get("limit", size_t(notifications_limit_default)) }; const m::user::notifications::opts opts { .from = from? lex_cast(from): 0, .to = 0, .only = only, }; const m::user::notifications notifications { request.user_id }; resource::response::chunked response { client, http::OK }; json::stack out { response.buf, response.flusher() }; json::stack::object top { out }; size_t count(0); bool finished(true); event::idx next_token(0); { json::stack::array array { top, "notifications" }; finished = notifications.for_each(opts, [&] (const event::idx ¬e_idx, const json::object ¬e) { assert(note_idx); next_token = note_idx; if(count >= limit) return false; const event::idx &event_idx { note.get("event_idx") }; const event::idx &rule_idx { note.get("rule_idx") }; //if(m::redacted(event_idx)) // return true; const m::event::fetch event { std::nothrow, event_idx }; if(unlikely(!event.valid)) return true; json::stack::object object { array }; json::stack::member { object, "room_id", json::get<"room_id"_>(event) }; json::stack::member { object, "ts", json::value { m::get(note_idx, "origin_server_ts") } }; m::event::id::buf last_read; m::receipt::get(last_read, json::get<"room_id"_>(event), request.user_id); json::stack::member { object, "read", json::value { last_read && index(std::nothrow, last_read) >= event_idx } }; //TODO: get from rule_idx json::stack::member { object, "actions", json::value { opts.only == "highlight"? R"(["notify",{"set_tweak":"highlight","value":true}])": R"(["notify"])" } }; //TODO: get from notification source json::stack::member { object, "profile_tag", json::value { nullptr } }; json::stack::object event_object { object, "event" }; m::event::append { event_object, event, { .event_idx = &event_idx, .keys = ¬ification_event_keys, //.query_txnid = false, //.query_prev_state = false, .query_redacted = false, }, }; ++count; return true; }); } if(!finished) json::stack::member { top, "next_token", json::value { lex_cast(next_token), json::STRING } }; top.~object(); return response; }