construct/matrix/user_notifications.cc

154 lines
3.3 KiB
C++

// 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.
decltype(ircd::m::user::notifications::type_prefix)
ircd::m::user::notifications::type_prefix
{
"ircd.push.note"
};
ircd::m::user::notifications::opts
ircd::m::user::notifications::unmake_type(const string_view &type)
{
const string_view &room_id
{
type.substr(type.find('!'))
};
const string_view &only
{
lstrip(split(type, '!').first, type_prefix)
};
opts ret;
ret.only = lstrip(only, '.');
ret.room_id = room_id? room::id{room_id} : room::id{};
return ret;
}
/// valid result examples:
///
/// ircd.push.note.highlight!AAAANTUiY1fBZ230:zemos.net
/// ircd.push.note.highlight
/// ircd.push.note!AAAANTUiY1fBZ230:zemos.net
/// ircd.push.note
ircd::string_view
ircd::m::user::notifications::make_type(const mutable_buffer &buf,
const opts &opts)
{
return fmt::sprintf
{
buf, "%s%s%s%s",
type_prefix,
opts.only? "."_sv : string_view{},
opts.only,
string_view{opts.room_id},
};
}
bool
ircd::m::user::notifications::empty(const opts &opts)
const
{
return !for_each(opts, closure_meta{[&]
(const auto &, const auto &) noexcept
{
return false;
}});
}
size_t
ircd::m::user::notifications::count(const opts &opts)
const
{
size_t ret(0);
for_each(opts, closure_meta{[&ret]
(const auto &, const auto &) noexcept
{
++ret;
return true;
}});
return ret;
}
bool
ircd::m::user::notifications::for_each(const opts &opts,
const closure &closure)
const
{
return for_each(opts, closure_meta{[&closure]
(const auto &type, const auto &event_idx)
{
return m::query(std::nothrow, event_idx, "content", [&closure, &event_idx]
(const json::object &content)
{
return closure(event_idx, content);
});
}});
}
bool
ircd::m::user::notifications::for_each(const opts &opts,
const closure_meta &closure)
const
{
const user::room user_room
{
user
};
char type_buf[event::TYPE_MAX_SIZE];
const auto type
{
make_type(type_buf, opts)
};
const room::type events
{
user_room, type, {-1UL, -1L}, true
};
if(!opts.sorted || opts.room_id)
return events.for_each([&opts, &closure]
(const auto &type, const auto &depth, const auto &event_idx)
{
if(opts.from && event_idx > opts.from) //TODO: XXX
return true;
if(opts.to && event_idx <= opts.to) //TODO: XXX
return false;
return closure(type, event_idx);
});
std::vector<event::idx> idxs;
idxs.reserve(events.count());
events.for_each([&opts, &idxs]
(const auto &type, const auto &depth, const auto &event_idx)
{
if(opts.from && event_idx > opts.from)
return true;
if(opts.to && event_idx <= opts.to)
return true;
idxs.emplace_back(event_idx);
return true;
});
std::sort(rbegin(idxs), rend(idxs));
for(const auto &idx : idxs)
if(!closure(string_view{}, idx)) //NOTE: no type string to closure
return false;
return true;
}