From 6704dcb51c9de5c66102600d06ffe637fd2db7c1 Mon Sep 17 00:00:00 2001 From: Nathan Ringo Date: Sun, 24 Nov 2024 11:04:29 -0600 Subject: Adds plugin to encourage the quitting of Twitter. Eh, it's a tradition at this point. --- src/lib.rs | 21 +++++++++++++++++++-- src/main.rs | 2 +- src/quit_twitter.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/quit_twitter.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 3b11a48..d24d386 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,11 @@ mod labwatch; +mod quit_twitter; use serenity::{ - all::{ChannelId, Context, EventHandler, Ready}, + all::{ChannelId, Context, EventHandler, Message, Ready}, async_trait, }; -use std::{path::PathBuf, sync::Arc}; +use std::{ops::ControlFlow, path::PathBuf, sync::Arc}; pub struct Handler(Arc); @@ -24,4 +25,20 @@ impl EventHandler for Handler { async fn ready(&self, ctx: Context, _data_about_bot: Ready) { tokio::spawn(labwatch::start(self.0.clone(), ctx)); } + + async fn message(&self, ctx: Context, msg: Message) { + // Apologies for the macro, but Rust does some control-flow analysis on async functions + // that it's much easier to pass when all your calls are direct calls. + macro_rules! handlers { + ($($handler:expr),* $(,)?) => { + $(match $handler(&self.0, &ctx, &msg).await { + Ok(ControlFlow::Break(())) => return, + Ok(ControlFlow::Continue(())) => (), + Err(err) => log::error!("{err:?}"), + })* + }; + } + + handlers![quit_twitter::on_message]; + } } diff --git a/src/main.rs b/src/main.rs index ed10360..3bceb37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,7 +74,7 @@ async fn main() -> Result<()> { } // Start up the client. - let intents = GatewayIntents::default(); + let intents = GatewayIntents::default() | GatewayIntents::MESSAGE_CONTENT; Client::builder(&args.discord_token, intents) .event_handler(Handler::from(HandlerConfig { db_dir: args.db_dir, diff --git a/src/quit_twitter.rs b/src/quit_twitter.rs new file mode 100644 index 0000000..fdeee94 --- /dev/null +++ b/src/quit_twitter.rs @@ -0,0 +1,33 @@ +use crate::HandlerConfig; +use anyhow::{anyhow, Context as _, Result}; +use serenity::all::{Context, Message}; +use std::ops::ControlFlow; + +const TWITTER_URLS: &[&str] = &[ + "https://fixupx.com/", + "https://fixvx.com/", + "https://pbs.twimg.com/", + "https://t.co/", + "https://twitter.com/", + "https://x.com/", +]; + +const REACTS: &[char] = &['🇶', '🇺', '🇮', '🇹', '🐦']; + +pub async fn on_message( + config: &HandlerConfig, + ctx: &Context, + msg: &Message, +) -> Result> { + let is_twitter = TWITTER_URLS.iter().any(|url| msg.content.contains(url)); + if !is_twitter { + return Ok(ControlFlow::Continue(())); + } + + for &react in REACTS { + msg.react(&ctx.http, react) + .await + .with_context(|| anyhow!("Failed to react with {react} on a Twitter message"))?; + } + Ok(ControlFlow::Break(())) +} -- cgit v1.2.3