summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-11-24 11:04:29 -0600
committerNathan Ringo <nathan@remexre.com>2024-11-24 11:04:29 -0600
commit6704dcb51c9de5c66102600d06ffe637fd2db7c1 (patch)
tree15c9e68f9ee32146bbb007a355f4d911616db784
parentdd0e6e45c35133ec8a3e2886b7b050484b388d03 (diff)
Adds plugin to encourage the quitting of Twitter. Eh, it's a tradition at this point.
-rw-r--r--src/lib.rs21
-rw-r--r--src/main.rs2
-rw-r--r--src/quit_twitter.rs33
3 files changed, 53 insertions, 3 deletions
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<HandlerConfig>);
@@ -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<ControlFlow<(), ()>> {
+ 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(()))
+}