moderatior
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 361 |
1 files changed, 115 insertions, 246 deletions
diff --git a/src/main.rs b/src/main.rs index ceae5b9..339abb8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ -#![feature(if_let_guard, let_chains, lazy_cell)] -#![allow(confusable_idents, mixed_script_confusables)] +#![feature(if_let_guard, let_chains, generic_const_exprs)] use anyhow::Result; -use emoji::named::*; +emojib::the_crate!(); +use emoji::named::*; use poise::{serenity_prelude::*, CreateReply}; use std::convert::identity; use std::fs::read_to_string; @@ -133,7 +133,8 @@ pub fn format(log: AuditLogEntry) -> Option<String> { .reduce(|a, b| format!("{a}\n{b}")) .unwrap_or_else(String::new); Some(format!( - "<@{}> {}", + "<t:{}:d> <@{}> {}", + log.id.created_at().unix_timestamp(), log.user_id, match log.action { GuildUpdate => format!("guild changes\n{changes}"), @@ -215,192 +216,6 @@ fn diff(old: &str, new: &str) -> String { .replace('`', "\u{200b}`") } -async fn event_handler(c: &serenity::all::Context, e: &FullEvent) -> Result<()> { - match e { - FullEvent::GuildAuditLogEntryCreate { entry, .. } => { - let Some(h) = format(entry.clone()) else { - return Ok(()); - }; - ChannelId::new(1220060625338761286) - .send_message( - c, - CreateMessage::new() - .allowed_mentions(CreateAllowedMentions::new().empty_users().empty_roles()) - .content(h), - ) - .await?; - } - FullEvent::GuildMemberAddition { new_member } => { - ChannelId::new(944772532559568936) - .send_message( - c, - CreateMessage::new().content(format!("{RIGHT} hi <@{}>", new_member.user.id)), - ) - .await - .unwrap(); - } - FullEvent::GuildMemberRemoval { - user, - member_data_if_available, - .. - } => { - ChannelId::new(944772532559568936) - .send_message( - c, - CreateMessage::new().content(format!( - "{LEFT} goodbye {} <@{}>", - match member_data_if_available { - Some(x) => x.nick.as_ref().unwrap_or(&user.name), - None => &user.name, - }, - user.id - )), - ) - .await - .unwrap(); - } - FullEvent::Message { new_message } => db::set_m(new_message.clone()), - FullEvent::MessageUpdate { - event: - MessageUpdateEvent { - id, - channel_id, - content: Some(content), - author: - Some(User { - id: author, bot, .. - }), - attachments: Some(attachments), - .. - }, - .. - } if !bot => { - if let Some((oc, _, _)) = db::get(id.get()) { - let diff = diff(&oc, content); - ChannelId::new(1226396559185285280) - .send_message( - c, - CreateMessage::new() - .allowed_mentions( - CreateAllowedMentions::new() - .empty_users() - .empty_roles(), - ) - .content(format!( - "<t:{}:d> <@{author}> {EDIT} their message https://discord.com/channels/925674713429184564/{channel_id}/{id}\n```diff{diff}```", - id.created_at().unix_timestamp() - )), - ) - .await - .unwrap(); - } - db::set( - id.get(), - ( - content.clone(), - attachments.iter().map(|a| a.url.clone()).collect(), - author.get(), - ), - ) - } - FullEvent::MessageDelete { - deleted_message_id, - channel_id, - .. - } => { - let log = c - .http() - .get_guild(925674713429184564.into()) - .await - .unwrap() - .audit_logs( - c, - Some(audit_log::Action::Message(MessageAction::Delete)), - None, - None, - Some(1), - ) - .await? - .entries - .into_iter() - .next() - .unwrap(); - - let ban_log = c - .http() - .get_guild(925674713429184564.into()) - .await - .unwrap() - .audit_logs( - c, - Some(audit_log::Action::Member(MemberAction::BanAdd)), - None, - None, - Some(1), - ) - .await? - .entries - .into_iter() - .next() - .unwrap() - .id; - - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_secs(); - let since = now.saturating_sub(log.id.created_at().unix_timestamp() as _); - let since_ban = now.saturating_sub(ban_log.created_at().unix_timestamp() as _); - if since_ban < 60 { - return Ok(()); - } - let (author, who) = (log.target_id.unwrap(), log.user_id); - ChannelId::new(1226396559185285280) - .send_message( - c, - CreateMessage::new() - .allowed_mentions( - CreateAllowedMentions::new() - .empty_users() - .empty_roles(), - ) - .content(match db::get(deleted_message_id.get()) { - Some((content, links, a)) => { - if a == 1224510735959462068 { return Ok(()) } - if author.get() != a || since > 20 { - format!( - "<t:{}:d> <@{a}> {CANCEL} deleted their own message (in <#{channel_id}>):```\n{content}\n```\n{}", - deleted_message_id.created_at().unix_timestamp(), - links - .into_iter() - .reduce(|a, b| format!("{a} {b}")) - .unwrap_or_else(String::new) - ) - } else { - format!( - "<t:{}:d> <@{who}> {CANCEL} deleted message by <@{author}> (in <#{channel_id}>):```\n{content}\n```\n{}", - deleted_message_id.created_at().unix_timestamp(), - links - .into_iter() - .reduce(|a, b| format!("{a} {b}")) - .unwrap_or_else(String::new) - ) - } - } - None => format!( - "<t:{}:d> <@{who}> {CANCEL} deleted message by <@{author}> in <#{channel_id}> (content unavailable)", - deleted_message_id.created_at().unix_timestamp() - ), - }), - ) - .await - .unwrap(); - } - _ => (), - } - Ok(()) -} - pub struct Bot; impl Bot { pub async fn spawn() { @@ -409,9 +224,117 @@ impl Bot { std::env::var("TOKEN").unwrap_or_else(|_| read_to_string("token").expect("wher token")); let f = poise::Framework::builder() .options(poise::FrameworkOptions { - commands: vec![help(), reload(), redact(), spy()], + commands: vec![help(), reload(), redact()], on_error: |e| Box::pin(on_error(e)), - event_handler: |c, e, _, _| Box::pin(event_handler(c, e)), + event_handler: |c, e, _, _| { + Box::pin(async move { + match e { + FullEvent::GuildAuditLogEntryCreate { entry, .. } => { + let Some(h) = format(entry.clone()) else { + return Ok(()); + }; + ChannelId::new(1220060625338761286).send_message( + c, + CreateMessage::new() + .allowed_mentions(CreateAllowedMentions::new().empty_users().empty_roles()) + .content(h), + ) + .await?; + } + FullEvent::GuildMemberAddition { new_member } => { + ChannelId::new(944772532559568936) + .send_message( + c, + CreateMessage::new() + .content(format!("{RIGHT} hi <@{}>", new_member.user.id), + )) + .await + .unwrap(); + } + FullEvent::GuildMemberRemoval { user, member_data_if_available, .. } => { + ChannelId::new(944772532559568936) + .send_message( + c, + CreateMessage::new() + .content(format!("{LEFT} goodbye {} <@{}>", match member_data_if_available { + Some(x) => x.nick.as_ref().unwrap_or(&user.name), + None => &user.name, + }, user.id)), + ) + .await + .unwrap(); + }, + FullEvent::Message { new_message } => db::set_m(new_message.clone()), + FullEvent::MessageUpdate { event: MessageUpdateEvent { id, channel_id, content: Some(content), author: Some(User{ id: author, bot, ..}), attachments: Some(attachments), .. }, .. } if !bot => { + if let Some((oc, _, _)) = db::get(id.get()) && &oc != content { + let diff = diff(&oc, content); + ChannelId::new(1226396559185285280) + .send_message( + c, + CreateMessage::new() + .allowed_mentions( + CreateAllowedMentions::new() + .empty_users() + .empty_roles(), + ) + .add_file(CreateAttachment::bytes(diff, "diff.patch")) + .content(format!("<@{author}> {EDIT} their message https://discord.com/channels/925674713429184564/{channel_id}/{id}")), + ) + .await + .unwrap(); + } + db::set(id.get(), (content.clone(), attachments.iter().map(|a|a.url.clone()).collect(), author.get())) + }, + FullEvent::MessageDelete { + deleted_message_id, channel_id, .. + } => { + let log = c.http().get_guild(925674713429184564.into()).await.unwrap() + .audit_logs(c, Some(audit_log::Action::Message(MessageAction::Delete)), None, None, Some(1)).await? + .entries.into_iter().next().unwrap(); + + let since = std::time::SystemTime::now().duration_since( std::time::UNIX_EPOCH).unwrap().as_secs().saturating_sub(log.id.created_at().unix_timestamp() as _); + let (author, who) = (log.target_id.unwrap(), log.user_id); + ChannelId::new(1226396559185285280) + .send_message( + c, + CreateMessage::new() + .allowed_mentions( + CreateAllowedMentions::new() + .empty_users() + .empty_roles(), + ) + .content(match db::get(deleted_message_id.get()) { + Some((content, links, a)) => { + if a == 1224510735959462068 { return Ok(()) } + if author.get() != a || since > 20 { + format!( + "<@{a}> {CANCEL} deleted their own message (in <#{channel_id}>):```\n{content}\n```\n{}", + links + .into_iter() + .reduce(|a, b| format!("{a} {b}")) + .unwrap_or_else(String::new) + ) + } else { + format!( + "<@{who}> {CANCEL} deleted message by <@{author}> (in <#{channel_id}>):```\n{content}\n```\n{}", + links + .into_iter() + .reduce(|a, b| format!("{a} {b}")) + .unwrap_or_else(String::new) + ) + } + } + None => format!("<@{who}> {CANCEL} deleted message by <@{author}> in <#{channel_id}> (content unavailable)"), + }), + ) + .await + .unwrap(); + } + _ => (), + } + Ok(()) + }) + }, ..Default::default() }) .setup(|ctx, _ready, f| { @@ -463,60 +386,6 @@ async fn main() { Bot::spawn().await; } -#[poise::command( - slash_command, - context_menu_command = "Read all messages", - rename = "spy" -)] -/// Collect the messages of a user. -/// Will be dispatched to your DM's. -/// This command may take some time. -pub async fn spy(c: Context<'_>, #[description = "the user to spy on"] who: User) -> Result<()> { - let u = c.author_member().await.ok_or(anyhow::anyhow!("dang"))?; - if !(u.user.name == "bendn" - || u.roles.contains(&RoleId::new(925676016708489227)) - || u.roles.contains(&RoleId::new(925708634896367647))) - { - poise::say_reply(c, "access denied. this incident will be reported").await?; - return Ok(()); - } - let h = c.reply("please check your dm's").await?; - let mut n = 0u64; - for (x, y) in db::values() - .filter(|(_, _, x)| *x == who.id) - .map(|(x, y, _)| (x, y)) - { - if let Err(_) = c - .author() - .dm( - c, - CreateMessage::new().content(format!( - "```{x}```\n{}", - y.into_iter() - .reduce(|a, b| format!("{a} {b}")) - .unwrap_or_default() - )), - ) - .await - && n == 0 - { - h.edit( - c, - CreateReply::default().content("please open your dm's (couldnt send)"), - ) - .await?; - return Ok(()); - }; - n += 1; - } - h.edit( - c, - CreateReply::default().content(format!("all ({n}) sent. please check your dm's")), - ) - .await?; - Ok(()) -} - #[poise::command(slash_command)] pub async fn reload(c: Context<'_>) -> Result<()> { if c.author().id != OWNER { |