diff --git a/include/ircd/m/room.h b/include/ircd/m/room.h index 9a24704c5..00baa508e 100644 --- a/include/ircd/m/room.h +++ b/include/ircd/m/room.h @@ -350,6 +350,10 @@ struct ircd::m::room::origins bool only(const string_view &origin) const; size_t count() const; + // select an origin in the room at random; use proffer to refuse and try another. + string_view random(const mutable_buffer &buf, const closure_bool &proffer = nullptr) const; + bool random(const closure &, const closure_bool &proffer = nullptr) const; + origins(const m::room &room) :room{room} {} diff --git a/ircd/m/room.cc b/ircd/m/room.cc index cc24e441c..67ab4a619 100644 --- a/ircd/m/room.cc +++ b/ircd/m/room.cc @@ -1701,6 +1701,39 @@ const // room::origins // +ircd::string_view +ircd::m::room::origins::random(const mutable_buffer &buf, + const closure_bool &proffer) +const +{ + string_view ret; + const auto closure{[&buf, &proffer, &ret] + (const string_view &origin) + { + ret = { data(buf), copy(buf, origin) }; + }}; + + random(closure, proffer); + return ret; +} + +bool +ircd::m::room::origins::random(const closure &view, + const closure_bool &proffer) +const +{ + using prototype = bool (const m::room &, + const m::room::origins::closure &, + const m::room::origins::closure_bool &); + + static m::import random_origin + { + "m_room", "random_origin" + }; + + return random_origin(room, view, proffer); +} + size_t ircd::m::room::origins::count() const diff --git a/modules/console.cc b/modules/console.cc index 39b15d910..401cc4073 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -4674,15 +4674,6 @@ console_cmd__room__origins(opt &out, const string_view &line) bool console_cmd__room__origins__random(opt &out, const string_view &line) { - using prototype = string_view (const m::room &, - const mutable_buffer &, - const std::function &); - - static m::import random_origin - { - "m_room", "random_origin" - }; - const params param{line, " ", { "room_id", "[noerror]" @@ -4703,6 +4694,11 @@ console_cmd__room__origins__random(opt &out, const string_view &line) room_id }; + const m::room::origins origins + { + room + }; + const auto ok{[&noerror] (const string_view &origin) { @@ -4715,7 +4711,7 @@ console_cmd__room__origins__random(opt &out, const string_view &line) char buf[256]; const string_view origin { - random_origin(room, buf, ok) + origins.random(buf, ok) }; if(!origin) diff --git a/modules/m_room.cc b/modules/m_room.cc index 5c3a791b6..6315a5136 100644 --- a/modules/m_room.cc +++ b/modules/m_room.cc @@ -16,12 +16,12 @@ IRCD_MODULE "Matrix state library; modular components." }; -extern "C" string_view +extern "C" bool random_origin(const m::room &room, - const mutable_buffer &buf, - const std::function &ok) + const m::room::origins::closure &view, + const m::room::origins::closure_bool &proffer = nullptr) { - string_view ret; + bool ret{false}; const m::room::origins origins { room @@ -40,7 +40,7 @@ random_origin(const m::room &room, ssize_t(rand::integer(0, max - 1)) }; - const m::room::origins::closure_bool closure{[&ok, &buf, &ret, &select] + const m::room::origins::closure_bool closure{[&proffer, &view, &select] (const string_view &origin) { if(select-- > 0) @@ -48,23 +48,19 @@ random_origin(const m::room &room, // Test if this random selection is "ok" e.g. the callback allows the // user to test a blacklist for this origin. Skip to next if not. - if(ok && !ok(origin)) + if(proffer && !proffer(origin)) { ++select; return true; } - ret = - { - data(buf), copy(buf, origin) - }; - + view(origin); return false; }}; - const auto iteration{[&origins, &closure] + const auto iteration{[&origins, &closure, &ret] { - origins.for_each(closure); + ret = !origins.for_each(closure); }}; // Attempt select on first iteration