aboutsummaryrefslogtreecommitdiff
path: root/src/discord.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/discord.rs')
-rw-r--r--src/discord.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/discord.rs b/src/discord.rs
new file mode 100644
index 0000000..c7aea78
--- /dev/null
+++ b/src/discord.rs
@@ -0,0 +1,98 @@
+use std::sync::Arc;
+
+use anyhow::Result;
+use chrono::prelude::*;
+use evtclib::Log;
+use serenity::client::bridge::gateway::ShardManager;
+use serenity::model::id::*;
+use serenity::prelude::*;
+
+use log::info;
+
+use super::categories::Categorizable;
+
+const MAX_HOURS: i64 = 5;
+
+struct ShardManagerContainer;
+
+impl TypeMapKey for ShardManagerContainer {
+ type Value = Arc<Mutex<ShardManager>>;
+}
+
+#[derive(Debug, Clone)]
+struct Handler {
+ channel_id: u64,
+ log: Log,
+ link: String,
+}
+
+impl EventHandler for Handler {
+ fn ready(&self, ctx: Context, _ready: serenity::model::gateway::Ready) {
+ info!("Discord client is ready");
+ let mut messages = ChannelId(self.channel_id)
+ .messages(&ctx, |r| r.limit(25))
+ .unwrap();
+ 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)
+ });
+
+ if let Some(mut m) = messages.pop() {
+ let new_text = insert_link(&m.content, &self.log, &self.link);
+ m.edit(&ctx, |m| m.content(new_text)).unwrap();
+ } else {
+ let new_text = insert_link("", &self.log, &self.link);
+ ChannelId(self.channel_id).say(&ctx, new_text).unwrap();
+ }
+
+ let data = ctx.data.read();
+ if let Some(manager) = data.get::<ShardManagerContainer>() {
+ manager.lock().shutdown_all();
+ }
+ }
+}
+
+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()?;
+ Ok(())
+}
+
+fn find_insertion(text: &str, category: &str) -> Option<usize> {
+ let cat_pos = text.find(&format!("**{}**", category))?;
+ let empty_line = text[cat_pos..].find("\n\n")?;
+ Some(cat_pos + empty_line + 1)
+}
+
+fn insert_link(text: &str, log: &Log, link: &str) -> String {
+ let mut text = format!("\n\n{}\n\n", text);
+ let point = find_insertion(&text, log.category());
+ let link_line = format!("{} {}\n", state_emoji(log), link);
+ if let Some(i) = point {
+ text.insert_str(i, &link_line);
+ } else {
+ text.push_str(&format!("**{}**\n{}", log.category(), link_line));
+ }
+ text.trim().into()
+}
+
+fn state_emoji(log: &Log) -> &'static str {
+ if log.was_rewarded() {
+ "✔️"
+ } else {
+ "❌"
+ }
+}