diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/discord.rs | 74 |
1 files changed, 46 insertions, 28 deletions
diff --git a/src/discord.rs b/src/discord.rs index 839b1c8..976b2d6 100644 --- a/src/discord.rs +++ b/src/discord.rs @@ -6,6 +6,7 @@ use evtclib::{Log, Outcome}; use serenity::client::bridge::gateway::ShardManager; use serenity::model::id::*; use serenity::prelude::*; +use tokio::runtime::Runtime; use log::info; @@ -34,61 +35,78 @@ struct Handler { } impl Handler { - fn do_link_update(&self, ctx: &Context) -> Result<()> { - let mut messages = ChannelId(self.channel_id).messages(&ctx, |r| r.limit(25))?; + async fn do_link_update(&self, ctx: &Context) -> Result<()> { + let mut messages = ChannelId(self.channel_id) + .messages(&ctx, |r| r.limit(25)) + .await?; messages.sort_by_key(|m| m.timestamp); - messages.retain(|m| { - m.is_own(ctx) - && Utc::now().signed_duration_since(m.timestamp) - < chrono::Duration::hours(MAX_HOURS) - }); + + // Retain does not work with async predicates, so we have to do it the old-fashioned way. + // This is slower than a proper implementation because we do more element shifts than + // needed, but it is also the easiest way to implement it and shouldn't matter for the 25 + // messages that we load. + let mut i = 0; + while i < messages.len() { + let is_good = messages[i].is_own(ctx).await + && Utc::now().signed_duration_since(messages[i].timestamp) + < chrono::Duration::hours(MAX_HOURS); + if is_good { + i += 1; + } else { + messages.remove(i); + } + } if let Some(mut m) = messages.pop() { let new_text = insert_link(&m.content, &self.log, &self.link); if new_text.len() <= MAX_MESSAGE_LENGTH { - m.edit(ctx, |m| m.content(new_text))?; + m.edit(ctx, |m| m.content(new_text)).await?; return Ok(()); } } let new_text = insert_link("", &self.log, &self.link); - ChannelId(self.channel_id).say(ctx, new_text)?; + ChannelId(self.channel_id).say(ctx, new_text).await?; Ok(()) } } +#[serenity::async_trait] impl EventHandler for Handler { - fn ready(&self, ctx: Context, _ready: serenity::model::gateway::Ready) { + async fn ready(&self, ctx: Context, _ready: serenity::model::gateway::Ready) { info!("Discord client is ready"); - let result = self.do_link_update(&ctx); + let result = self.do_link_update(&ctx).await; - let mut data = ctx.data.write(); + let mut data = ctx.data.write().await; data.insert::<PostLinkResult>(result); if let Some(manager) = data.get::<ShardManagerContainer>() { - manager.lock().shutdown_all(); + manager.lock().await.shutdown_all().await; } } } pub fn post_link(discord_token: &str, channel_id: u64, log: Log, link: String) -> Result<()> { - let mut client = Client::new( - discord_token, - Handler { - channel_id, - log, - link, - }, - )?; - { - let mut data = client.data.write(); - data.insert::<ShardManagerContainer>(Arc::clone(&client.shard_manager)); - } - client.start()?; + let mut rt = Runtime::new()?; + + rt.block_on(async { + let mut client = Client::builder(discord_token) + .event_handler(Handler { + channel_id, + log, + link, + }) + .await?; + { + let mut data = client.data.write().await; + data.insert::<ShardManagerContainer>(Arc::clone(&client.shard_manager)); + } + client.start().await?; - let mut data = client.data.write(); - data.remove::<PostLinkResult>().unwrap_or(Ok(())) + let mut data = client.data.write().await; + data.remove::<PostLinkResult>().unwrap_or(Ok(())) + }) } fn find_insertion(text: &str, category: &str) -> Option<usize> { |