aboutsummaryrefslogblamecommitdiff
path: root/src/handler.rs
blob: b83d789696f909434eb70949807074d6bdea8ca6 (plain) (tree)
1
2
3
4
5
6
7


                                                                                                                
 
                     
                         
 





                                                                                                   




                             



                                                           



                                                                      
                                                                                       














                                                                                       
                                               


                                                                              







                                                       
                        







                                                            

                 
                                                 


                                                 


                                                                              
                                                                                
                     

                                                      





                                                                      




                                                                          



























































                                                                                                                                                                                                                                                           

                 











































                                                                                                            



                    

          





























                                                                                                              
use poise::serenity_prelude::{self as serenity, Interaction, MessageComponentInteraction, MessageId, ChannelId};
use regex::Regex;
use serde_json::json;

use crate::models::*;
use crate::{Data, Error};

use tracing::info;

/**
 * Handles specific events, including ReactionAdd, which is needed for the reaction role handler to
 * function properly
 */
pub async fn event_handler(
    ctx: &serenity::Context,
    event: &poise::Event<'_>,
    data: &Data,
) -> Result<(), Error> {
    {
        let pool = data.pg.lock().unwrap().clone();
        match event {
            poise::Event::ReactionAdd { add_reaction } => {
                let current_user = ctx.http.get_current_user().await?;
                if add_reaction.user_id.unwrap() == current_user.id {
                    return Ok(());
                }
                // This fetches the role and lets us query extra data including role ID
                let rrole = sqlx::query_as!(
                    ReactionRole,
                    "SELECT * FROM reaction_roles WHERE message_id=$1 AND reaction=$2",
                    add_reaction.message_id.0.to_string(),
                    add_reaction.emoji.to_string()
                )
                .fetch_one(&pool)
                .await?;
                let member = ctx
                    .http
                    .get_member(
                        rrole.guild_id.parse::<u64>()?,
                        add_reaction.user_id.unwrap().0,
                    )
                    .await?;
                // Honestly, not really needed.
                let member_roles = member.roles;
                let role_id = serenity::RoleId(rrole.role_id.parse::<u64>()?);
                if member_roles.contains(&role_id) {
                    ctx.http
                        .remove_member_role(
                            member.guild_id.0,
                            member.user.id.0,
                            role_id.0,
                            Some("Reaction Role Menu"),
                        )
                        .await?;
                } else {
                    ctx.http
                        .add_member_role(
                            rrole.guild_id.parse::<u64>()?,
                            add_reaction.user_id.unwrap().0,
                            rrole.role_id.parse::<u64>()?,
                            Some("Reaction Role"),
                        )
                        .await?;
                }

                if let Ok(dm_chan) = add_reaction
                    .user_id
                    .unwrap()
                    .create_dm_channel(&ctx.http)
                    .await {
                        dm_chan.say(ctx, format!("Toggled the role!")).await?;
                    } else {
                        info!("Could not DM user, but we did the role anyways");
                    }

                add_reaction.delete(&ctx.http).await?;
            },
            poise::Event::Message { new_message } => {
                let current_user = ctx.http.get_current_user().await?;

                if new_message.author.id.0 != current_user.id.0 {
                    // This message does *not* belong to the bot
                    let filters = sqlx::query_as::<_, MessageFilter>(
                        "SELECT * FROM message_filter WHERE guild_id=$1")
                        .bind(new_message.guild_id.unwrap().0.to_string())
                    .fetch_all(&pool)
                    .await?;

                    let content = new_message.content.clone();

                    for f in filters {
                        let r = Regex::new(&f.pattern)?;
                        
                        if r.is_match(&content) {
                            match f.action {
                                FilterAction::Review => {
                                    if let Ok(c) = sqlx::query_as!(ConfigChannel, "SELECT * FROM channels WHERE purpose='review' AND guild_id=$1", new_message.guild_id.unwrap().0.to_string())
                                        .fetch_one(&pool)
                                        .await {
                                            let chan = serenity::ChannelId(c.channel_id.parse::<u64>()?);

                                            chan.send_message(&ctx, |m| {
                                                m.content(format!("Message was flagged for review (using rule {})", f.id));
                                                m.components(|c| {
                                                    c.create_action_row(|r| {
                                                        r.create_button(|b| {
                                                            b.style(serenity::ButtonStyle::Primary);
                                                            b.label("Approve");
                                                            b.custom_id("approve");
                                                            b
                                                        });
                                                        r.create_button(|b| {
                                                            b.style(serenity::ButtonStyle::Danger);
                                                            b.label("Deny");
                                                            b.custom_id("deny");
                                                            b
                                                        });
                                                        r
                                                    });
                                                    c
                                                });
                                                m.embed(|e| {
                                                    e.author(|a| {
                                                        a.name(new_message.clone().author.name);
                                                        a.icon_url(new_message.clone().author.face())
                                                    });
                                                    e.description(content.clone());
                                                    e.footer(|f| {
                                                        f.text(format!("{}:{}", new_message.channel_id.0, new_message.id.0.to_string()))
                                                    });
                                                    e.field("Link", new_message.link().clone(), true)
                                                })
                                            }).await?;
                                        } else {
                                            let guild = new_message.guild(&ctx).unwrap();

                                            let owner = guild.owner_id;
                                            let dm_chan = owner.create_dm_channel(&ctx.http).await?;
                                            dm_chan.say(&ctx.http, format!("Hi! I tried to flag a message for review in {}, but you haven't set a review channel yet! Set one now by running `filter channel` in the server.", guild.name.clone())).await?;
                                        }
                                },
                                FilterAction::Delete => {
                                    new_message.delete(&ctx.http).await?;
                                }
                            }
                        }
                    }
                }
            },
            poise::Event::InteractionCreate { interaction } => {
                match interaction {
                    Interaction::MessageComponent(mci) => {
                        let data = &mci.data;

                        let mci2 = mci.clone();

                        match data.custom_id.as_str() {
                            "approve" => {

                               let msg_report = mci2.message.clone();
                               let footer = msg_report.embeds[0].clone().footer.unwrap().text;
                               let mut footer = footer.split(':');
                               let orig_channel_id = footer.next().unwrap();
                               let orig_msg_id = footer.next().unwrap();
                               let orig_msg_id = MessageId(orig_msg_id.parse::<u64>()?);
                               let orig_channel_id = ChannelId(orig_channel_id.parse::<u64>()?);

                               let orig_msg = ctx.http.get_message(orig_channel_id.0, orig_msg_id.0).await?;


                                disable_buttons(&ctx, mci2).await?;                                
                            },
                            "deny" => {
                               let msg_report = mci2.message.clone();
                               let footer = msg_report.embeds[0].clone().footer.unwrap().text;
                               let mut footer = footer.split(':');
                               let orig_channel_id = footer.next().unwrap();
                               let orig_msg_id = footer.next().unwrap();
                               let orig_msg_id = MessageId(orig_msg_id.parse::<u64>()?);
                               let orig_channel_id = ChannelId(orig_channel_id.parse::<u64>()?);

                               let orig_msg = ctx.http.get_message(orig_channel_id.0, orig_msg_id.0).await?;

                               orig_msg.delete(&ctx).await?;

                               disable_buttons(&ctx, mci2).await?;
                            },
                            _ => (),
                        };
                    },
                    _ => ()
                };
            },
            _ => (),
        }
    }

    Ok(())
}

async fn disable_buttons(ctx: &serenity::Context, mut mci: MessageComponentInteraction) -> Result<(), Error> {
    mci.message.edit(&ctx, |m| {
                                    m.components(|c| {
                                        c.create_action_row(|r| {
                                            r.create_button(|b| {
                                                b.style(serenity::ButtonStyle::Primary);
                                                b.label("Approve");
                                                b.custom_id("approve");
                                                b.disabled(true);
                                                b
                                            });
                                            r.create_button(|b| {
                                                b.style(serenity::ButtonStyle::Danger);
                                                b.label("Deny");
                                                b.custom_id("deny");
                                                b.disabled(true);
                                                b
                                            });
                                            r
                                        });
                                        c
                                    });
                                    m
                                }).await?;

    ctx.http.create_interaction_response(mci.id.0, &mci.token, &json!({ "type": 7})).await?;

    Ok(())
}