manifold/src/events.rs

313 lines
14 KiB
Rust

use std::sync::atomic::AtomicBool;
use poise::{async_trait, 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;
#[async_trait]
pub trait EventHandler {
async fn listen(ctx: &Context, framework_ctx: FrameworkContext<'_, ManifoldData, ManifoldError>, event: &Event<'_>) -> ManifoldResult<()>;
}
pub struct Handler {
pub timer_running: AtomicBool,
}
#[async_trait]
impl EventHandler for Handler {
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(())
}
}
}
impl Handler {
pub fn new() -> Self {
Handler {
timer_running: AtomicBool::from(false)
}
}
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 => t!("logging.bot_start").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(t!("logging.user_banned", user = 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(t!("logging.user_unbanned", user = 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(t!("logging.user_joined", name = new_member.user.name, nickname = new_member.nick.as_ref().unwrap_or(&new_member.user.name), uid = 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<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(t!("logging.user_left", name = 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<Member>, _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(t!("logging.role_created", name = &new.name, role_id = &new.id))
.colour(Colour::from_rgb(0, 255, 0))
.timestamp(Timestamp::now())
.field(t!("logging.role_created.permissions"), &new.permissions, false)
.field(t!("logging.role_created.hoist"), &new.hoist, true)
.field(t!("logging.role_created.icon"), &new.icon.clone().unwrap_or("None set".to_string()), true)
.field(t!("logging.role_created.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<Role>) -> 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(t!("logging.role_deleted", name = &role.name, role_id = &role.id))
.colour(Colour::from_rgb(255, 0, 0))
.timestamp(Timestamp::now())
.field(t!("logging.role_deleted.permissions"), &role.permissions, false)
.field(t!("logging.role_deleted.hoist"), &role.hoist, true)
.field(t!("logging.role_deleted.icon"), &role.icon.clone().unwrap_or("None set".to_string()), true)
.field(t!("logging.role_deleted.mentionable"), &role.mentionable, true)
},
None => {
return e
.title(t!("logging.role_deleted.not_cached", role_id = 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<Role>, _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;
let db = &fctx.user_data().await.database;
if let Some(u) = userinfo.get_mut(&msg.author.id.as_u64()) {
u.last_seen = Some(chrono::Utc::now().timestamp());
u.insert(db)?;
} 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()),
};
new_user.insert(db)?;
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<GuildId>) -> ManifoldResult<()> {
let log_channel = fctx.user_data().await.bot_config.channels.log;
let channel = match ctx.cache.guild_channel(channel_id) {
Some(c) => c.name,
None => t!("global.not_available_with_id", id = channel_id).to_string()
};
match ctx.cache.message(channel_id, deleted_message_id) {
Some(msg) => {
let mut attachment_urls: Vec<String> = Vec::new();
for attachment in &msg.attachments {
attachment_urls.push(attachment.url.clone());
}
log_channel.send_message(ctx, |f| {
f
.content("")
.embed(|e| {
e
.title(t!("logging.message_deleted", channel = channel, channel_id = channel_id))
.colour(Colour::from_rgb(255, 0, 0))
.author(|a| a.name(&msg.author.name))
.field(t!("logging.message_deleted.content"), msg.content_safe(&ctx.cache), false)
.field(t!("logging.message_deleted.attachments"), attachment_urls.join(", "), false)
.timestamp(Timestamp::now())
.footer(|f| f.text(&msg.author.id));
for attachment in &msg.attachments {
e.image(attachment.url.clone());
}
e
})
}).await?;
},
None => {
log_channel.send_message(ctx, |f| {
f
.content("")
.embed(|e| {
e
.title(t!("logging.message_deleted.not_cached", channel_name = channel, channel_id = channel_id))
.colour(Colour::from_rgb(255, 0, 0))
.timestamp(Timestamp::now())
})
}).await?;
}
}
Ok(())
}
async fn message_edited(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, original: &Option<Message>, new_message: &Option<Message>) -> 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(t!("logging.message_edited", channel_name = message_channel, channel_id = new.channel_id))
.colour(Colour::from_rgb(255, 153, 0))
.author(|a| a.name(new.author.name.clone()))
.timestamp(Timestamp::now())
.field(t!("logging.message_edited.original_content"), match original.as_ref() {
Some(m) => m.content.clone(),
None => t!("global.not_available").to_string(),
}, false)
.field(t!("logging.message_edited.new_content"), new.content.clone(), false)
.field(t!("logging.message_edited.created_at"), new.timestamp, true)
.field(t!("logging.message_edited.author"), &new.author.id, true)
})
}).await?;
}
Ok(())
}
}