aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/discord.rs74
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> {