use std::sync::atomic::AtomicBool; use poise::{Event, FrameworkContext}; use poise::serenity_prelude::model::{ gateway::Ready, }; use poise::serenity_prelude::{ChannelId, Colour, Context, GuildId, Member, Message, MessageId, Role, RoleId, Timestamp, User}; use crate::ManifoldData; use crate::error::{ManifoldError, ManifoldResult}; use crate::models::user::UserInfo; pub struct Handler { pub timer_running: AtomicBool, } impl Handler { pub fn new() -> Self { Handler { timer_running: AtomicBool::from(false) } } pub async fn listen(ctx: &Context, framework_ctx: FrameworkContext<'_, ManifoldData, ManifoldError>, event: &Event<'_>) -> ManifoldResult<()> { match event { Event::Ready { data_about_bot} => Handler::standard_startup(&ctx, &framework_ctx, data_about_bot).await, Event::GuildBanAddition { guild_id, banned_user } => Handler::ban_add(&ctx, &framework_ctx, guild_id, banned_user).await, Event::GuildBanRemoval { guild_id, unbanned_user } => Handler::ban_remove(&ctx, &framework_ctx, guild_id, unbanned_user).await, Event::GuildMemberAddition { new_member } => Handler::new_member(&ctx, &framework_ctx, &new_member).await, Event::GuildMemberRemoval { guild_id, user, member_data_if_available } => Handler::member_leave(&ctx, &framework_ctx, guild_id, user, member_data_if_available).await, Event::GuildMemberUpdate { old_if_available, new } => Handler::member_update(&ctx, &framework_ctx, old_if_available, new).await, Event::GuildRoleCreate { new } => Handler::new_role(&ctx, &framework_ctx, new).await, Event::GuildRoleDelete { guild_id, removed_role_id, removed_role_data_if_available } => Handler::delete_role(&ctx, &framework_ctx, guild_id, removed_role_id, removed_role_data_if_available).await, Event::GuildRoleUpdate { old_data_if_available, new } => Handler::update_role(&ctx, &framework_ctx, old_data_if_available, new).await, Event::Message { new_message } => Handler::message(&ctx, &framework_ctx, &new_message).await, Event::MessageDelete { channel_id, deleted_message_id, guild_id } => Handler::message_deleted(&ctx, &framework_ctx, channel_id, deleted_message_id, guild_id).await, Event::MessageUpdate { old_if_available, new, event: _event } => Handler::message_edited(&ctx, &framework_ctx, old_if_available, new).await, _ => Ok(()) } } pub async fn standard_startup(ctx: &Context, framework_ctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, data_about_bot: &Ready) -> ManifoldResult<()> { let config = &framework_ctx.user_data().await.bot_config; let responses = &framework_ctx.user_data().await.responses; let greeting = match responses.get_response(&"bot startup".to_string()) { Some(g) => g.to_owned(), None => "Manifold bot connected to discord and ready to begin broadcast operations.".to_string(), }; for guild in &data_about_bot.guilds { match guild.id.edit_nickname(&ctx, Some(&*config.nickname)).await { Ok(()) => (), Err(e) => { error!("Error setting bot nickname (lack permission?): {:?}", e); } } } config.channels.log.say(&ctx, greeting).await.expect("Couldn't message log channel!"); Ok(()) } async fn ban_add(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, _guild_id: &GuildId, banned_user: &User) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { e .title(format!("{} was banned", banned_user.name)) .colour(Colour::from_rgb(255, 0, 0)) .timestamp(Timestamp::now()) }) }).await?; Ok(()) } async fn ban_remove(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, _guild_id: &GuildId, unbanned_user: &User) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { e .title(format!("Ban was lifted for {}", unbanned_user.name)) .colour(Colour::from_rgb(0, 255, 0)) .timestamp(Timestamp::now()) }) }).await?; Ok(()) } async fn new_member(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, new_member: &Member) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { e .title(format!("{} joined the server with nickname {} ({})", new_member.user.name, new_member.nick.as_ref().unwrap_or(&new_member.user.name), new_member.user.id)) .colour(Colour::from_rgb(0, 255, 0)) .timestamp(new_member.joined_at.unwrap_or(Timestamp::now())) .field("Account creation date", new_member.user.created_at(), false) }) }).await?; Ok(()) } async fn member_leave(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, _guild_id: &GuildId, user: &User, _member_data_if_available: &Option) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { e .title(format!("{} left the server", user.name)) .colour(Colour::from_rgb(255, 0, 0)) .timestamp(Timestamp::now()) }) }).await?; Ok(()) } async fn member_update(_ctx: &Context, _fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, _old_if_available: &Option, _new: &Member) -> ManifoldResult<()> { Ok(()) } async fn new_role(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, new: &Role) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { e .title(format!("New role {} ({}) was created", &new.name, &new.id)) .colour(Colour::from_rgb(0, 255, 0)) .timestamp(Timestamp::now()) .field("Role Permissions", &new.permissions, false) .field("Hoist", &new.hoist, true) .field("Icon", &new.icon.clone().unwrap_or("None set".to_string()), true) .field("Mentionable", &new.mentionable, true) }) }).await?; Ok(()) } async fn delete_role(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, _guild_id: &GuildId, removed_role_id: &RoleId, removed_role_data_if_available: &Option) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { match removed_role_data_if_available { Some(role) => { return e .title(format!("Role {} ({}) was deleted", &role.name, &role.id)) .colour(Colour::from_rgb(255, 0, 0)) .timestamp(Timestamp::now()) .field("Role Permissions", &role.permissions, false) .field("Hoist", &role.hoist, true) .field("Icon", &role.icon.clone().unwrap_or("None set".to_string()), true) .field("Mentionable", &role.mentionable, true) }, None => { return e .title(format!("Role {} was deleted (Role was not cached)", removed_role_id)) .colour(Colour::from_rgb(255, 0, 0)) .timestamp(Timestamp::now()) } }; }) }).await?; Ok(()) } async fn update_role(_ctx: &Context, _fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, _old_data_if_available: &Option, _new: &Role) -> ManifoldResult<()> { Ok(()) } async fn message(_ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, msg: &Message) -> ManifoldResult<()> { let userinfo = &mut fctx.user_data().await.user_info.lock().await; if let Some(u) = userinfo.get_mut(&msg.author.id.as_u64()) { u.last_seen = Some(chrono::Utc::now().timestamp()); } else { let new_user = UserInfo { user_id: msg.author.id.as_u64().clone() as i64, username: msg.author.name.to_owned(), weather_location: None, weather_units: None, timezone: None, last_seen: Some(chrono::Utc::now().timestamp()), }; userinfo.insert(msg.author.id.as_u64().clone(), new_user); } Ok(()) } async fn message_deleted(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, channel_id: &ChannelId, deleted_message_id: &MessageId, _guild_id: &Option) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; let mut content: String = "Not Available / Not Cached".to_string(); let author; let channel = match ctx.cache.guild_channel(channel_id) { Some(c) => c.name, None => format!("Not Available / Not Cached ({})", channel_id) }; if let Some(msg) = ctx.cache.message(channel_id, deleted_message_id) { content = msg.content_safe(&ctx.cache); author = msg.author; } else { author = User::default(); } log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { e .title(format!("Message removed in #{} ({})", channel, channel_id )) .colour(Colour::from_rgb(255, 0, 0)) .author(|a| a.name(author.name)) .field("Message Content", content, false) .timestamp(Timestamp::now()) .footer(|f| f.text(author.id)) }) }).await?; Ok(()) } async fn message_edited(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, original: &Option, new_message: &Option) -> ManifoldResult<()> { let log_channel = fctx.user_data().await.bot_config.channels.log; if let Some(new) = new_message.as_ref() { let message_channel = new.channel_id.name(ctx).await.unwrap_or("Unknown Channel".to_string()); log_channel.send_message(ctx, |f| { f .content("") .embed(|e| { e .title(format!("Message updated in #{} ({})", message_channel, new.channel_id)) .colour(Colour::from_rgb(255, 153, 0)) .author(|a| a.name(new.author.name.clone())) .timestamp(Timestamp::now()) .field("Original Content", match original.as_ref() { Some(m) => m.content.clone(), None => "Not available".to_string(), }, false) .field("New Content", new.content.clone(), false) .field("Message created at", new.timestamp, true) .field("Message author", &new.author.id, true) }) }).await?; } Ok(()) } }