minor error message improvements

This commit is contained in:
Stachelbeere1248 2024-12-28 03:57:52 +01:00
parent 86a23a327a
commit 4b03762390
Signed by: Stachelbeere1248
SSH key fingerprint: SHA256:IozEKdw2dB8TZxkpPdMxcWSoWTIMwoLaCcZJ1AJnY2o
2 changed files with 50 additions and 38 deletions

View file

@ -1,30 +1,29 @@
use std::ops::Add;
use poise::CreateReply; use poise::CreateReply;
use reqwest::{Client, Response}; use reqwest::{Client, Response};
use serde::Deserialize; use serde::Deserialize;
use serenity::{ use serenity::all::ButtonStyle;
all::{ChannelId, CreateActionRow, CreateAllowedMentions, CreateButton, CreateMessage, ReactionType, User}, use serenity::all::{ChannelId, CreateActionRow, CreateAllowedMentions, CreateButton, CreateMessage, ReactionType, User};
}; use sqlx::{query_as, Pool, Sqlite};
use serenity::all::{ButtonStyle}; use std::ops::Add;
use sqlx::{Pool, query_as, Sqlite};
use crate::commands::command_helper::cooldown; use crate::commands::command_helper::cooldown;
use crate::Context;
use crate::error::Error; use crate::error::Error;
use crate::error::Error::Other;
use crate::Context;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Links { struct Links {
#[serde(rename = "DISCORD")] #[serde(rename = "DISCORD")]
pub discord: String, pub discord: Option<String>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
struct SocialMedia { struct SocialMedia {
pub links: Links, pub links: Option<Links>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
struct HypixelPlayer { struct HypixelPlayer {
#[serde(rename = "socialMedia")] #[serde(rename = "socialMedia")]
pub social_media: SocialMedia, pub social_media: Option<SocialMedia>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
struct HypixelResponse { struct HypixelResponse {
@ -49,9 +48,7 @@ impl Uuid {
let url: String = format!("https://api.mojang.com/users/profiles/minecraft/{ign}"); let url: String = format!("https://api.mojang.com/users/profiles/minecraft/{ign}");
let response_400: Response = reqwest::get(url).await?.error_for_status()?; let response_400: Response = reqwest::get(url).await?.error_for_status()?;
let deserialized = response_400.json::<MojangPlayer>().await?; let deserialized = response_400.json::<MojangPlayer>().await?;
let uuid = Uuid { let uuid = Uuid { uuid: deserialized.id };
uuid: deserialized.id,
};
Ok(uuid) Ok(uuid)
} }
@ -71,7 +68,18 @@ impl Uuid {
let url: String = format!("https://api.hypixel.net/v2/player?uuid={}", self.uuid); let url: String = format!("https://api.hypixel.net/v2/player?uuid={}", self.uuid);
let response_400: Response = client.get(url).send().await?.error_for_status()?; let response_400: Response = client.get(url).send().await?.error_for_status()?;
let deserialized = response_400.json::<HypixelResponse>().await?; let deserialized = response_400.json::<HypixelResponse>().await?;
let matches = deserialized.player.social_media.links.discord == user.name; let matches = deserialized
.player
.social_media
.map(|sm| sm.links)
.flatten()
.map(|l| l.discord)
.flatten()
.ok_or(Other(format!(
"The Hypixel profile has no Discord account linked. Please follow the steps in {}",
ChannelId::new(1256219552568840263_u64)
)))?
== user.name;
Ok(matches) Ok(matches)
} }
} }
@ -127,7 +135,7 @@ pub(crate) async fn account(_ctx: Context<'_>) -> Result<(), Error> {
slash_command, slash_command,
install_context = "User|Guild", install_context = "User|Guild",
interaction_context = "Guild|BotDm|PrivateChannel", interaction_context = "Guild|BotDm|PrivateChannel",
ephemeral = "false", ephemeral = "false"
)] )]
/// Verify a Minecraft account on the Zombies MultiPlayer Discord. /// Verify a Minecraft account on the Zombies MultiPlayer Discord.
pub(crate) async fn add<'a>( pub(crate) async fn add<'a>(
@ -140,10 +148,15 @@ pub(crate) async fn add<'a>(
#[description = "admin-only"] force: Option<bool>, #[description = "admin-only"] force: Option<bool>,
) -> Result<(), Error> { ) -> Result<(), Error> {
ctx.defer().await?; ctx.defer().await?;
let force: bool = force.unwrap_or(false) && ctx.framework().options.owners.contains(&ctx.author().id) && {
let _ = user.as_ref().ok_or(Other(
"Warning: attempted to run forced account add without specifying a target Discord account.".to_string(),
))?;
true
};
let user: User = user.unwrap_or(ctx.author().clone()); let user: User = user.unwrap_or(ctx.author().clone());
let uuid: Uuid = Uuid::for_ign(ign.as_str()).await?; let uuid: Uuid = Uuid::for_ign(ign.as_str()).await?;
let force: bool = force.unwrap_or(false) && ctx.framework().options.owners.contains(&ctx.author().id); match force || uuid.has_discord_user(&user, &ctx.data().hypixel_api_client).await? {
match uuid.has_discord_user(&user, &ctx.data().hypixel_api_client).await? || force {
true => { true => {
let pool = &ctx.data().sqlite_pool; let pool = &ctx.data().sqlite_pool;
let status: &str = match link_id_from_minecraft(pool, uuid.get()).await { let status: &str = match link_id_from_minecraft(pool, uuid.get()).await {
@ -176,8 +189,7 @@ pub(crate) async fn add<'a>(
sqlx::query( sqlx::query(
format!( format!(
"UPDATE minecraft_links SET link_id = {} WHERE link_id = {};", "UPDATE minecraft_links SET link_id = {} WHERE link_id = {};",
mc_id.inner, mc_id.inner, dc_id.inner
dc_id.inner
) )
.as_str(), .as_str(),
) )
@ -186,8 +198,7 @@ pub(crate) async fn add<'a>(
sqlx::query( sqlx::query(
format!( format!(
"UPDATE discord_links SET link_id = {} WHERE link_id = {};", "UPDATE discord_links SET link_id = {} WHERE link_id = {};",
mc_id.inner, mc_id.inner, dc_id.inner
dc_id.inner
) )
.as_str(), .as_str(),
) )
@ -244,8 +255,9 @@ pub(crate) async fn list(ctx: Context<'_>, user: User) -> Result<(), Error> {
ctx.send( ctx.send(
CreateReply::default() CreateReply::default()
.content(s) .content(s)
.allowed_mentions(CreateAllowedMentions::new().empty_roles().empty_users()) .allowed_mentions(CreateAllowedMentions::new().empty_roles().empty_users()),
).await?; )
.await?;
Ok(()) Ok(())
} }
@ -304,7 +316,7 @@ struct LinkId {
impl From<u16> for LinkId { impl From<u16> for LinkId {
fn from(unsigned: u16) -> Self { fn from(unsigned: u16) -> Self {
Self { Self {
inner: unsigned.cast_signed() inner: unsigned.cast_signed(),
} }
} }
} }

View file

@ -14,7 +14,7 @@ macro_rules! reply_fail_handler {
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
SqlxError(sqlx::Error), SqlxError(sqlx::Error),
HttpsError(reqwest::Error), ApiError(reqwest::Error),
SerenityError(serenity::Error), SerenityError(serenity::Error),
OnCooldown(std::time::Duration), OnCooldown(std::time::Duration),
Other(String), Other(String),
@ -24,7 +24,7 @@ impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> FmtResult { fn fmt(&self, f: &mut Formatter) -> FmtResult {
match self { match self {
Error::SqlxError(e) => write!(f, "SQLx Error: {}", e), Error::SqlxError(e) => write!(f, "SQLx Error: {}", e),
Error::HttpsError(e) => write!(f, "HTTPS Error (Hypixel / Mojang API):\n{}", e), Error::ApiError(e) => write!(f, "HTTPS Error (Hypixel / Mojang API):\n{}", e),
Error::SerenityError(e) => write!(f, "Discord Error:\n {}", e), Error::SerenityError(e) => write!(f, "Discord Error:\n {}", e),
Error::OnCooldown(d) => write!(f, "This command is on cooldown. {}s remaining.", d.as_secs()), Error::OnCooldown(d) => write!(f, "This command is on cooldown. {}s remaining.", d.as_secs()),
Error::Other(s) => write!(f, "{}", s), Error::Other(s) => write!(f, "{}", s),
@ -40,7 +40,7 @@ impl From<sqlx::Error> for Error {
impl From<reqwest::Error> for Error { impl From<reqwest::Error> for Error {
fn from(error: reqwest::Error) -> Self { fn from(error: reqwest::Error) -> Self {
Error::HttpsError(error) Error::ApiError(error)
} }
} }