From dc0b760714780840967fc488553c892d4199db45 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 22 Jan 2024 00:24:14 +0100 Subject: [PATCH] feat: Remove poll command --- .env.example | 10 ----- src/api/client.rs | 68 ----------------------------- src/api/mod.rs | 3 -- src/api/model/auth.rs | 6 --- src/api/model/mod.rs | 1 - src/api/routing.rs | 30 ------------- src/commands/misc.rs | 51 ---------------------- src/db/model.rs | 15 ------- src/events/interaction.rs | 54 ----------------------- src/events/mod.rs | 4 -- src/events/ready.rs | 2 +- src/main.rs | 11 ----- src/utils/message.rs | 52 ---------------------- src/utils/mod.rs | 2 - src/utils/poll.rs | 91 --------------------------------------- 15 files changed, 1 insertion(+), 399 deletions(-) delete mode 100644 src/api/client.rs delete mode 100644 src/api/mod.rs delete mode 100644 src/api/model/auth.rs delete mode 100644 src/api/model/mod.rs delete mode 100644 src/api/routing.rs delete mode 100644 src/events/interaction.rs delete mode 100644 src/utils/message.rs delete mode 100644 src/utils/poll.rs diff --git a/.env.example b/.env.example index 4ee995d..199b0a6 100644 --- a/.env.example +++ b/.env.example @@ -2,13 +2,3 @@ DISCORD_AUTHORIZATION_TOKEN= # The connection string to the MongoDB database MONGODB_URI='' - -# The api server for the poll command -API_SERVER='' -# The client id for the api -API_CLIENT_ID='' -# The client secret for the api -API_CLIENT_SECRET='' - -# The poll secret used for the poll command -POLL_SECRET='' \ No newline at end of file diff --git a/src/api/client.rs b/src/api/client.rs deleted file mode 100644 index e3be6a2..0000000 --- a/src/api/client.rs +++ /dev/null @@ -1,68 +0,0 @@ -use reqwest::header::HeaderMap; -use reqwest::Client; -use serde::de::DeserializeOwned; - -use super::model::auth::Authentication; -use super::routing::Endpoint; - -pub struct Api { - pub client: Client, - pub server: reqwest::Url, - pub client_id: String, - pub client_secret: String, -} - -struct RequestInfo<'a> { - headers: Option, - route: Endpoint<'a>, -} - -impl Api { - pub fn new(server: reqwest::Url, client_id: String, client_secret: String) -> Self { - let client = Client::builder() - .build() - .expect("Cannot build reqwest::Client"); - - Api { - client, - server, - client_id, - client_secret, - } - } - - async fn fire( - &self, - request_info: &RequestInfo<'_>, - ) -> Result { - let client = &self.client; - let mut req = request_info.route.to_request(&self.server); - - if let Some(headers) = &request_info.headers { - *req.headers_mut() = headers.clone(); - } - - client - .execute(req) - .await? - .error_for_status()? - .json::() - .await - } - - pub async fn authenticate( - &self, - discord_id_hash: &str, - ) -> Result { - let route = Endpoint::Authenticate { - id: &self.client_id, - secret: &self.client_secret, - discord_id_hash, - }; - self.fire(&RequestInfo { - headers: None, - route, - }) - .await - } -} diff --git a/src/api/mod.rs b/src/api/mod.rs deleted file mode 100644 index 503ee09..0000000 --- a/src/api/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod client; -pub mod model; -mod routing; diff --git a/src/api/model/auth.rs b/src/api/model/auth.rs deleted file mode 100644 index 776b0a7..0000000 --- a/src/api/model/auth.rs +++ /dev/null @@ -1,6 +0,0 @@ -use serde::Deserialize; - -#[derive(Deserialize)] -pub struct Authentication { - pub access_token: String, -} diff --git a/src/api/model/mod.rs b/src/api/model/mod.rs deleted file mode 100644 index 0e4a05d..0000000 --- a/src/api/model/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod auth; diff --git a/src/api/routing.rs b/src/api/routing.rs deleted file mode 100644 index 6b3034f..0000000 --- a/src/api/routing.rs +++ /dev/null @@ -1,30 +0,0 @@ -use reqwest::{Body, Method, Request}; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -#[serde(untagged)] -pub enum Endpoint<'a> { - Authenticate { - id: &'a str, - secret: &'a str, - discord_id_hash: &'a str, - }, -} - -macro_rules! route { - ($self:ident, $server:ident, $endpoint:literal, $method:ident) => {{ - let mut req = Request::new(Method::$method, $server.join($endpoint).unwrap()); - *req.body_mut() = Some(Body::from(serde_json::to_vec($self).unwrap())); - req - }}; -} - -impl Endpoint<'_> { - pub fn to_request(&self, server: &reqwest::Url) -> Request { - match self { - Self::Authenticate { - .. - } => route!(self, server, "/auth/", POST), - } - } -} diff --git a/src/commands/misc.rs b/src/commands/misc.rs index 234f598..786a5ec 100644 --- a/src/commands/misc.rs +++ b/src/commands/misc.rs @@ -1,7 +1,5 @@ -use poise::serenity_prelude::{CreateActionRow, CreateAllowedMentions, CreateButton, ReactionType}; use poise::{CreateReply, ReplyHandle}; -use crate::utils::message::clone_message; use crate::{Context, Error}; /// Make the Discord bot sentient. @@ -50,52 +48,3 @@ pub async fn reply( send_ephermal(&ctx, &format!("Response: {message}")).await?; Ok(()) } - -/// Start a poll. -#[poise::command(slash_command)] -pub async fn poll( - ctx: Context<'_>, - #[description = "The id of the poll"] id: u64, /* This is currently unused in the API, leaving as a placeholder in case it is required. */ - #[description = "A link to a message to clone"] message_link: String, - #[description = "The minumum server age in days to allow members to poll"] age: u16, - #[description = "Enable pings"] ping: bool, -) -> Result<(), Error> { - let get_id = - |segments: &mut std::str::Split| segments.next_back().unwrap().parse::(); - - let url = reqwest::Url::parse(&message_link)?; - let mut segments = url.path_segments().ok_or("Invalid Discord message link")?; - - if segments.clone().count() != 4 { - return Err("Invalid Discord message link".into()); - } - - let message_id = get_id(&mut segments)?; - let channel_id = get_id(&mut segments)?; - - let message = ctx - .serenity_context() - .http - .get_message(channel_id.into(), message_id.into()) - .await?; - - let message = clone_message(&message).components(vec![CreateActionRow::Buttons(vec![ - CreateButton::new(format!("poll:{id}:{age}")) - .label("Vote") - .emoji(ReactionType::Unicode("🗳️".to_string())), - ])]); - - ctx.send(if ping { - message.allowed_mentions( - CreateAllowedMentions::default() - .all_roles(true) - .all_users(true) - .everyone(true), - ) - } else { - message - }) - .await?; - - Ok(()) -} diff --git a/src/db/model.rs b/src/db/model.rs index 3438e0c..32d613b 100644 --- a/src/db/model.rs +++ b/src/db/model.rs @@ -23,21 +23,6 @@ pub struct LockedChannel { pub overwrites: Option>, } -#[skip_serializing_none] -#[derive(Serialize, Deserialize, Debug, Default)] -pub struct Poll { - pub author: Option, - pub image_url: Option, - pub votes: Option, -} - -#[skip_serializing_none] -#[derive(Serialize, Deserialize, Debug, Default)] -pub struct PollAuthor { - pub name: Option, - pub id: Option, -} - impl From for Document { fn from(muted: Muted) -> Self { to_document(&muted) diff --git a/src/events/interaction.rs b/src/events/interaction.rs deleted file mode 100644 index 63a6ff0..0000000 --- a/src/events/interaction.rs +++ /dev/null @@ -1,54 +0,0 @@ -use chrono::{Duration, Utc}; -use poise::serenity_prelude::{ - ComponentInteraction, ComponentInteractionData, ComponentInteractionDataKind, -}; - -use super::*; -use crate::{utils, BotData}; - -pub async fn interaction_create( - ctx: &serenity::Context, - interaction: &serenity::Interaction, - data: &BotData, -) -> Result<(), serenity::prelude::SerenityError> { - if let serenity::Interaction::Component(ComponentInteraction { - data: - ComponentInteractionData { - kind: ComponentInteractionDataKind::Button, - custom_id, - .. - }, - .. - }) = interaction - { - if custom_id.starts_with("poll") { - handle_poll(ctx, interaction, custom_id, data).await? - } - } - - Ok(()) -} - -pub async fn handle_poll( - ctx: &serenity::Context, - interaction: &serenity::Interaction, - custom_id: &str, - data: &BotData, -) -> Result<(), serenity::prelude::SerenityError> { - fn parse(str: &str) -> T - where - ::Err: std::fmt::Debug, - T: std::str::FromStr, - { - str.parse::().unwrap() - } - - let poll: Vec<_> = custom_id.split(':').collect::>(); - - let poll_id = parse::(poll[1]); - let min_age = parse::(poll[2]); - - let min_join_date = serenity::Timestamp::from(Utc::now() - Duration::days(min_age)); - - utils::poll::handle_poll(ctx, interaction, poll_id, min_join_date, data).await -} diff --git a/src/events/mod.rs b/src/events/mod.rs index 32ff5a3..4ac993b 100644 --- a/src/events/mod.rs +++ b/src/events/mod.rs @@ -6,7 +6,6 @@ use tokio::sync::RwLock; mod guild_member_addition; mod guild_member_update; -mod interaction; mod message_create; mod ready; @@ -28,9 +27,6 @@ pub async fn event_handler( new, .. } => guild_member_update::guild_member_update(ctx, old_if_available, new).await, - serenity::FullEvent::InteractionCreate { interaction } => { - interaction::interaction_create(ctx, interaction, data).await? - }, _ => {}, } Ok(()) diff --git a/src/events/ready.rs b/src/events/ready.rs index e3e18f9..07db727 100644 --- a/src/events/ready.rs +++ b/src/events/ready.rs @@ -39,7 +39,7 @@ pub async fn load_muted_members(ctx: &serenity::Context, data: &Arc guild_id.into(), user_id.into(), mute_role_id, - amount_left as u64, // i64 as u64 is handled properly here + amount_left as u64, ), ); } diff --git a/src/main.rs b/src/main.rs index ba4dd42..dd7d929 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use std::env; use std::sync::Arc; -use api::client::Api; use commands::{configuration, misc, moderation}; use db::database::Database; use events::event_handler; @@ -15,7 +14,6 @@ use utils::bot::load_configuration; use crate::model::application::Configuration; -mod api; mod commands; mod db; mod events; @@ -35,8 +33,6 @@ pub struct Data { configuration: Configuration, database: Arc, pending_unmutes: HashMap>>, - poll_secret: String, - api: Api, } #[tokio::main] @@ -54,7 +50,6 @@ async fn main() { moderation::ban(), moderation::unban(), misc::reply(), - misc::poll(), ]; poise::set_qualified_names(&mut commands); @@ -92,12 +87,6 @@ async fn main() { .unwrap(), ), pending_unmutes: HashMap::new(), - poll_secret: env::var("POLL_SECRET").unwrap(), - api: Api::new( - reqwest::Url::parse(&env::var("API_SERVER").unwrap()).unwrap(), - env::var("API_CLIENT_ID").unwrap(), - env::var("API_CLIENT_SECRET").unwrap(), - ), }))) }) }) diff --git a/src/utils/message.rs b/src/utils/message.rs deleted file mode 100644 index 5754ab7..0000000 --- a/src/utils/message.rs +++ /dev/null @@ -1,52 +0,0 @@ -use chrono::Utc; -use poise::serenity_prelude::{CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, Message}; -use poise::CreateReply; - -pub fn clone_message(message: &Message) -> CreateReply { - let mut reply = CreateReply { - content: Some(message.content.clone()), - ..Default::default() - }; - - if let Some(embed) = message.embeds.first() { - let mut new_embed = CreateEmbed::new(); - - if let Some(color) = embed.colour { - new_embed = new_embed.color(color); - } - - new_embed = new_embed.timestamp(Utc::now()); - - if let Some(title) = &embed.title { - new_embed = new_embed.title(title); - } - - if let Some(description) = &embed.description { - new_embed = new_embed.description(description); - } - - if let Some(footer) = &embed.footer { - new_embed = new_embed.footer(CreateEmbedFooter::new(&footer.text)); - } - - if let Some(author) = &embed.author { - new_embed = new_embed.author(CreateEmbedAuthor::new(&author.name)); - } - - if let Some(image) = &embed.image { - new_embed = new_embed.image(image.url.as_str()); - } - - if let Some(thumbnail) = &embed.thumbnail { - new_embed = new_embed.thumbnail(thumbnail.url.as_str()); - } - - for field in &embed.fields { - new_embed = new_embed.field(field.name.as_str(), field.value.as_str(), field.inline); - } - - reply = reply.embed(new_embed); - } - - reply -} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 31e887d..3567dd1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -5,10 +5,8 @@ pub mod bot; pub mod code_embed; pub mod decancer; pub mod macros; -pub mod message; pub mod message_response; pub mod moderation; -pub mod poll; pub fn parse_duration(duration: String) -> Result { let d = parse_duration::parse(&duration)?; diff --git a/src/utils/poll.rs b/src/utils/poll.rs deleted file mode 100644 index 3523727..0000000 --- a/src/utils/poll.rs +++ /dev/null @@ -1,91 +0,0 @@ - - -use base64::Engine; -use poise::serenity_prelude::{ - CreateActionRow, CreateButton, CreateEmbed, CreateEmbedFooter, - CreateInteractionResponseMessage, ReactionType, Timestamp, -}; -use reqwest::StatusCode; - -use tracing::log::{error, trace}; - -use crate::{BotData}; - -use super::*; - -pub async fn handle_poll( - ctx: &serenity::Context, - interaction: &serenity::Interaction, - poll_id: u64, - min_join_date: Timestamp, - data: &BotData, -) -> Result<(), serenity::prelude::SerenityError> { - trace!("Handling poll: {}.", poll_id); - - let data = data.read().await; - - let component = &interaction.clone().message_component().unwrap(); - - let member = component.member.as_ref().unwrap(); - - let eligible = member.joined_at.unwrap() <= min_join_date; - let result = if eligible { - match data - .api - .authenticate(&base64::engine::general_purpose::STANDARD_NO_PAD.encode( - hmac_sha256::HMAC::mac(member.user.id.to_string(), &data.poll_secret), - )) - .await - { - Ok(auth) => Ok(auth.access_token), - Err(err) => match err.status() { - Some(StatusCode::PRECONDITION_FAILED) => Err("You can only vote once."), - _ => { - error!("API Request error: {:?}", err); - Err("API Request failed. Please try again later.") - }, - }, - } - } else { - Err("You are not eligible to vote on this poll because you joined this server too recently.") - }; - - let icon_url = component - .guild_id - .unwrap() - .to_guild_cached(&ctx.cache) - .unwrap() - .icon_url() - .unwrap(); - - component - .create_response( - &ctx.http, - serenity::CreateInteractionResponse::Message(if let Ok(token) = result.as_deref() { - let url = format!("https://revanced.app/poll#{token}"); - - CreateInteractionResponseMessage::new().components(vec![CreateActionRow::Buttons( - vec![CreateButton::new_link(url) - .label("Vote") - .emoji(ReactionType::Unicode("🗳️".to_string()))], - )]) - } else { - CreateInteractionResponseMessage::new() - .ephemeral(true) - .embed( - match result { - Ok(_) => CreateEmbed::new() - .title("Cast your vote") - .description("You can now vote on the poll."), - Err(msg) => CreateEmbed::new().title("Error").description(msg), - } - .color(data.configuration.general.embed_color) - .thumbnail(&icon_url) - .footer(CreateEmbedFooter::new("ReVanced").icon_url(&icon_url)), - ) - }), - ) - .await?; - - Ok(()) -}