mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-05-24 17:20:49 +00:00
Core/Prelude: Fix lifetime unsoundness
This commit is contained in:
parent
c672a8836c
commit
f1719019d1
9 changed files with 150 additions and 112 deletions
|
@ -1,6 +1,5 @@
|
|||
use crate::{AppData, Result};
|
||||
use async_trait::async_trait;
|
||||
use crossbeam_channel::after;
|
||||
use futures_util::{
|
||||
future::{join_all, ready, FutureExt},
|
||||
stream::{FuturesUnordered, StreamExt},
|
||||
|
@ -78,7 +77,7 @@ impl MemberToChannels {
|
|||
pub struct AnnouncerHandler {
|
||||
cache_http: Arc<CacheAndHttp>,
|
||||
data: AppData,
|
||||
announcers: HashMap<&'static str, RwLock<Box<dyn Announcer>>>,
|
||||
announcers: HashMap<&'static str, RwLock<Box<dyn Announcer + Send + Sync>>>,
|
||||
}
|
||||
|
||||
// Querying for the AnnouncerHandler in the internal data returns a vec of keys.
|
||||
|
@ -100,7 +99,11 @@ impl AnnouncerHandler {
|
|||
/// Insert a new announcer into the handler.
|
||||
///
|
||||
/// The handler must take an unique key. If a duplicate is found, this method panics.
|
||||
pub fn add(&mut self, key: &'static str, announcer: impl Announcer + 'static) -> &mut Self {
|
||||
pub fn add(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
announcer: impl Announcer + Send + Sync + 'static,
|
||||
) -> &mut Self {
|
||||
if let Some(_) = self
|
||||
.announcers
|
||||
.insert(key, RwLock::new(Box::new(announcer)))
|
||||
|
@ -132,7 +135,7 @@ impl AnnouncerHandler {
|
|||
data: AppData,
|
||||
cache_http: Arc<CacheAndHttp>,
|
||||
key: &'static str,
|
||||
announcer: &'_ RwLock<Box<dyn Announcer>>,
|
||||
announcer: &'_ RwLock<Box<dyn Announcer + Send + Sync>>,
|
||||
) -> Result<()> {
|
||||
let channels = MemberToChannels(Self::get_guilds(&data, key).await?);
|
||||
announcer
|
||||
|
@ -151,7 +154,8 @@ impl AnnouncerHandler {
|
|||
self.data.write().await.insert::<Self>(keys.clone());
|
||||
loop {
|
||||
eprintln!("{}: announcer started scanning", chrono::Utc::now());
|
||||
let after_timer = after(cooldown);
|
||||
// let after_timer = after(cooldown);
|
||||
let after = tokio::time::delay_for(cooldown);
|
||||
join_all(self.announcers.iter().map(|(key, announcer)| {
|
||||
eprintln!(" - scanning key `{}`", key);
|
||||
Self::announce(self.data.clone(), self.cache_http.clone(), *key, announcer).map(
|
||||
|
@ -164,7 +168,7 @@ impl AnnouncerHandler {
|
|||
}))
|
||||
.await;
|
||||
eprintln!("{}: announcer finished scanning", chrono::Utc::now());
|
||||
after_timer.recv().ok();
|
||||
after.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,18 +13,39 @@ use tokio::time as tokio_time;
|
|||
const ARROW_RIGHT: &'static str = "➡️";
|
||||
const ARROW_LEFT: &'static str = "⬅️";
|
||||
|
||||
/// Paginate! with a pager function.
|
||||
#[async_trait::async_trait]
|
||||
pub trait Paginate {
|
||||
async fn render(&mut self, page: u8, ctx: &Context, m: &mut Message) -> Result<bool>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<T> Paginate for T
|
||||
where
|
||||
T: for<'m> FnMut(
|
||||
u8,
|
||||
&'m Context,
|
||||
&'m mut Message,
|
||||
) -> std::pin::Pin<Box<dyn Future<Output = Result<bool>> + Send + 'm>>
|
||||
+ Send,
|
||||
{
|
||||
async fn render(&mut self, page: u8, ctx: &Context, m: &mut Message) -> Result<bool> {
|
||||
self(page, ctx, m).await
|
||||
}
|
||||
}
|
||||
|
||||
// Paginate! with a pager function.
|
||||
/// If awaited, will block until everything is done.
|
||||
pub async fn paginate<'a, T, F>(
|
||||
mut pager: T,
|
||||
ctx: &'a Context,
|
||||
pub async fn paginate(
|
||||
mut pager: impl for<'m> FnMut(
|
||||
u8,
|
||||
&'m Context,
|
||||
&'m mut Message,
|
||||
) -> std::pin::Pin<Box<dyn Future<Output = Result<bool>> + Send + 'm>>
|
||||
+ Send,
|
||||
ctx: &Context,
|
||||
channel: ChannelId,
|
||||
timeout: std::time::Duration,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: for<'m> FnMut(u8, &'a Context, &'m mut Message) -> F,
|
||||
F: Future<Output = Result<bool>>,
|
||||
{
|
||||
) -> Result<()> {
|
||||
let mut message = channel
|
||||
.send_message(&ctx, |e| e.content("Youmu is loading the first page..."))
|
||||
.await?;
|
||||
|
@ -35,8 +56,9 @@ where
|
|||
message
|
||||
.react(&ctx, ReactionType::try_from(ARROW_RIGHT)?)
|
||||
.await?;
|
||||
pager(0, ctx, &mut message).await?;
|
||||
// Build a reaction collector
|
||||
let mut reaction_collector = message.await_reactions(&ctx).await;
|
||||
let mut reaction_collector = message.await_reactions(&ctx).removed(true).await;
|
||||
let mut page = 0;
|
||||
|
||||
// Loop the handler function.
|
||||
|
@ -59,29 +81,25 @@ where
|
|||
}
|
||||
|
||||
// Handle the reaction and return a new page number.
|
||||
async fn handle_reaction<'a, T, F>(
|
||||
async fn handle_reaction(
|
||||
page: u8,
|
||||
pager: &mut T,
|
||||
ctx: &'a Context,
|
||||
message: &'_ mut Message,
|
||||
pager: &mut impl Paginate,
|
||||
ctx: &Context,
|
||||
message: &mut Message,
|
||||
reaction: &ReactionAction,
|
||||
) -> Result<u8>
|
||||
where
|
||||
T: for<'m> FnMut(u8, &'a Context, &'m mut Message) -> F,
|
||||
F: Future<Output = Result<bool>>,
|
||||
{
|
||||
) -> Result<u8> {
|
||||
let reaction = match reaction {
|
||||
ReactionAction::Added(v) | ReactionAction::Removed(v) => v,
|
||||
};
|
||||
match &reaction.emoji {
|
||||
ReactionType::Unicode(ref s) => match s.as_str() {
|
||||
ARROW_LEFT if page == 0 => Ok(page),
|
||||
ARROW_LEFT => Ok(if pager(page - 1, ctx, message).await? {
|
||||
ARROW_LEFT => Ok(if pager.render(page - 1, ctx, message).await? {
|
||||
page - 1
|
||||
} else {
|
||||
page
|
||||
}),
|
||||
ARROW_RIGHT => Ok(if pager(page + 1, ctx, message).await? {
|
||||
ARROW_RIGHT => Ok(if pager.render(page + 1, ctx, message).await? {
|
||||
page + 1
|
||||
} else {
|
||||
page
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use serenity::{framework::standard::StandardFramework, prelude::*};
|
||||
use serenity::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
/// Set up the prelude libraries.
|
||||
///
|
||||
/// Panics on failure: Youmubot should *NOT* attempt to continue when this function fails.
|
||||
pub fn setup_prelude(db_path: &Path, data: &mut TypeMap, _: &mut StandardFramework) {
|
||||
pub fn setup_prelude(db_path: &Path, data: &mut TypeMap) {
|
||||
// Setup the announcer DB.
|
||||
crate::announcer::AnnouncerChannels::insert_into(data, db_path.join("announcers.yaml"))
|
||||
.expect("Announcers DB set up");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue