rewrite errors
This commit is contained in:
parent
c9ea6a393a
commit
c1ab3424bd
12 changed files with 135 additions and 103 deletions
5
.idea/inspectionProfiles/Project_Default.xml
generated
5
.idea/inspectionProfiles/Project_Default.xml
generated
|
@ -2,5 +2,10 @@
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="RsMainFunctionNotFound" enabled="false" level="ERROR" enabled_by_default="false" />
|
<inspection_tool class="RsMainFunctionNotFound" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
|
@ -15,7 +15,8 @@ use serenity::{
|
||||||
};
|
};
|
||||||
use sqlx::{Pool, query_as, Sqlite};
|
use sqlx::{Pool, query_as, Sqlite};
|
||||||
|
|
||||||
use crate::{Context, Error};
|
use crate::Context;
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Links {
|
struct Links {
|
||||||
|
@ -53,7 +54,12 @@ impl Uuid {
|
||||||
async fn fetch(ign: &str) -> Result<Self, Error> {
|
async fn fetch(ign: &str) -> Result<Self, Error> {
|
||||||
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: Response = reqwest::get(url).await?;
|
let response: Response = reqwest::get(url).await?;
|
||||||
match response.error_for_status() {
|
let response_text = response.error_for_status()?.text().await.unwrap();
|
||||||
|
let uuid = (serde_json::from_str(response_text.as_str())
|
||||||
|
as Result<MojangPlayer, JsonError>)
|
||||||
|
.map(|mojang_player: MojangPlayer| Uuid { uuid: mojang_player.id })?;
|
||||||
|
Ok(uuid)
|
||||||
|
/*match response.error_for_status() {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
let response_text = res.text().await.unwrap();
|
let response_text = res.text().await.unwrap();
|
||||||
let uuid = (serde_json::from_str(response_text.as_str())
|
let uuid = (serde_json::from_str(response_text.as_str())
|
||||||
|
@ -64,7 +70,7 @@ impl Uuid {
|
||||||
Err(why) => Err(Error::from(format!(
|
Err(why) => Err(Error::from(format!(
|
||||||
"Mojang returned an error. Please make sure to enter a valid Minecraft username.\n\n\
|
"Mojang returned an error. Please make sure to enter a valid Minecraft username.\n\n\
|
||||||
Details: {}", why).as_str())),
|
Details: {}", why).as_str())),
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -75,20 +81,12 @@ impl DiscordId {
|
||||||
async fn matches_fetch(user: &User, uuid: &str, client: &Client) -> Result<bool, Error> {
|
async fn matches_fetch(user: &User, uuid: &str, client: &Client) -> Result<bool, Error> {
|
||||||
let url: String = format!("https://api.hypixel.net/v2/player?uuid={}", uuid);
|
let url: String = format!("https://api.hypixel.net/v2/player?uuid={}", uuid);
|
||||||
let response: Response = client.get(url).send().await?;
|
let response: Response = client.get(url).send().await?;
|
||||||
match response.error_for_status() {
|
let response_text = response.error_for_status()?.text().await.unwrap();
|
||||||
Ok(res) => {
|
|
||||||
let response_text = res.text().await.unwrap();
|
|
||||||
let matches = (serde_json::from_str(response_text.as_str())
|
let matches = (serde_json::from_str(response_text.as_str())
|
||||||
as Result<HypixelResponse, JsonError>)
|
as Result<HypixelResponse, JsonError>)
|
||||||
.map(|hypixel_response: HypixelResponse| user.name == hypixel_response.player.social_media.links.discord)?;
|
.map(|hypixel_response: HypixelResponse| user.name == hypixel_response.player.social_media.links.discord)?;
|
||||||
Ok(matches)
|
Ok(matches)
|
||||||
}
|
}
|
||||||
Err(why) => {
|
|
||||||
println!("Hypixel issue: {}", why);
|
|
||||||
Err(Error::from("Hypixel returned an error."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl<'a, R: sqlx::Row> sqlx::FromRow<'a, R> for DiscordId
|
impl<'a, R: sqlx::Row> sqlx::FromRow<'a, R> for DiscordId
|
||||||
where
|
where
|
||||||
|
@ -116,17 +114,17 @@ impl Link {
|
||||||
minecraft_accounts: vec![],
|
minecraft_accounts: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn minecraft(mut self, pool: &Pool<Sqlite>) -> Self {
|
async fn minecraft(mut self, pool: &Pool<Sqlite>) -> Result<Self, Error> {
|
||||||
let link_id: i16 = self.link_id.cast_signed();
|
let link_id: i16 = self.link_id.cast_signed();
|
||||||
self.minecraft_accounts = query_as(format!("SELECT minecraft_uuid AS uuid FROM minecraft_links WHERE link_id = {link_id};").as_str())
|
self.minecraft_accounts = query_as(format!("SELECT minecraft_uuid AS uuid FROM minecraft_links WHERE link_id = {link_id};").as_str())
|
||||||
.fetch_all(pool).await.expect("Error getting Minecraft UUIDs.");
|
.fetch_all(pool).await?;
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
async fn discord(mut self, pool: &Pool<Sqlite>) -> Self {
|
async fn discord(mut self, pool: &Pool<Sqlite>) -> Result<Self, Error> {
|
||||||
let link_id: i16 = self.link_id.cast_signed();
|
let link_id: i16 = self.link_id.cast_signed();
|
||||||
self.discord_ids = query_as(format!("SELECT discord_id FROM discord_links WHERE link_id = {link_id};").as_str())
|
self.discord_ids = query_as(format!("SELECT discord_id FROM discord_links WHERE link_id = {link_id};").as_str())
|
||||||
.fetch_all(pool).await.expect("Error getting Discord IDs.");
|
.fetch_all(pool).await?;
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[poise::command(slash_command, subcommands("add", "list"))]
|
#[poise::command(slash_command, subcommands("add", "list"))]
|
||||||
|
@ -148,26 +146,23 @@ pub(crate) async fn add<'a>(
|
||||||
ctx.defer_ephemeral().await?;
|
ctx.defer_ephemeral().await?;
|
||||||
let user = user.unwrap_or(ctx.author().clone());
|
let user = user.unwrap_or(ctx.author().clone());
|
||||||
let uuid = Uuid::fetch(ign.as_str()).await?;
|
let uuid = Uuid::fetch(ign.as_str()).await?;
|
||||||
let valid = DiscordId::matches_fetch(&user, uuid.get(), &ctx.data().hypixel_api_client).await
|
match DiscordId::matches_fetch(&user, uuid.get(), &ctx.data().hypixel_api_client).await? {
|
||||||
.expect("This Minecraft account does not have a Discord account linked.");
|
|
||||||
match valid {
|
|
||||||
true => {
|
true => {
|
||||||
let r = CreateReply::default().ephemeral(false);
|
|
||||||
let pool: Pool<Sqlite> = ctx.data().sqlite_pool.clone();
|
let pool: Pool<Sqlite> = ctx.data().sqlite_pool.clone();
|
||||||
let (status, link_id) = match link_id_from_minecraft(&pool, uuid.get()).await {
|
let (status, link_id) = match link_id_from_minecraft(&pool, uuid.get()).await {
|
||||||
None => {
|
None => {
|
||||||
match link_id_from_discord(&pool, user.id.get()).await {
|
match link_id_from_discord(&pool, user.id.get()).await {
|
||||||
None => {
|
None => {
|
||||||
let id = new_link_id(&pool).await;
|
let id = new_link_id(&pool).await?;
|
||||||
sqlx::query(format!("INSERT INTO discord_links VALUES ({}, {});", id.cast_signed(), user.id.get()).as_str())
|
sqlx::query(format!("INSERT INTO discord_links VALUES ({}, {});", id.cast_signed(), user.id.get()).as_str())
|
||||||
.execute(&pool).await.expect("Database Error: inserting new minecraft value");
|
.execute(&pool).await?;
|
||||||
sqlx::query(format!("INSERT INTO minecraft_links VALUES ({}, \"{}\");", id.cast_signed(), uuid.get()).as_str())
|
sqlx::query(format!("INSERT INTO minecraft_links VALUES ({}, \"{}\");", id.cast_signed(), uuid.get()).as_str())
|
||||||
.execute(&pool).await.expect("Database Error: inserting new minecraft value");
|
.execute(&pool).await?;
|
||||||
("Linked your Discord and Minecraft account.", id)
|
("Linked your Discord and Minecraft account.", id)
|
||||||
}
|
}
|
||||||
Some(dc_id) => {
|
Some(dc_id) => {
|
||||||
sqlx::query(format!("INSERT INTO minecraft_links VALUES ({}, \"{}\");", dc_id.cast_signed(), uuid.get()).as_str())
|
sqlx::query(format!("INSERT INTO minecraft_links VALUES ({}, \"{}\");", dc_id.cast_signed(), uuid.get()).as_str())
|
||||||
.execute(&pool).await.expect("Database Error: inserting new minecraft value");
|
.execute(&pool).await?;
|
||||||
("Your Discord account has previously had an account linked. Added the new link.", dc_id)
|
("Your Discord account has previously had an account linked. Added the new link.", dc_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,22 +171,21 @@ pub(crate) async fn add<'a>(
|
||||||
match link_id_from_discord(&pool, user.id.get()).await {
|
match link_id_from_discord(&pool, user.id.get()).await {
|
||||||
None => {
|
None => {
|
||||||
sqlx::query(format!("INSERT INTO discord_links VALUES ({}, {});", mc_id.cast_signed(), user.id.get()).as_str())
|
sqlx::query(format!("INSERT INTO discord_links VALUES ({}, {});", mc_id.cast_signed(), user.id.get()).as_str())
|
||||||
.execute(&pool).await.expect("Database Error: inserting new minecraft value");
|
.execute(&pool).await?;
|
||||||
("Your Minecraft account has previously had an account linked. Added the new link.", mc_id)
|
("Your Minecraft account has previously had an account linked. Added the new link.", mc_id)
|
||||||
}
|
}
|
||||||
Some(dc_id) => {
|
Some(dc_id) => {
|
||||||
sqlx::query(format!("UPDATE minecraft_links SET link_id = {} WHERE link_id = {};", mc_id.cast_signed(), dc_id.cast_signed()).as_str())
|
sqlx::query(format!("UPDATE minecraft_links SET link_id = {} WHERE link_id = {};", mc_id.cast_signed(), dc_id.cast_signed()).as_str())
|
||||||
.execute(&pool).await.expect("Database Error: Merging Minecraft Accounts.");
|
.execute(&pool).await?;
|
||||||
sqlx::query(format!("UPDATE discord_links SET link_id = {} WHERE link_id = {};", mc_id.cast_signed(), dc_id.cast_signed()).as_str())
|
sqlx::query(format!("UPDATE discord_links SET link_id = {} WHERE link_id = {};", mc_id.cast_signed(), dc_id.cast_signed()).as_str())
|
||||||
.execute(&pool).await.expect("Database Error: Merging Discord Accounts.");
|
.execute(&pool).await?;
|
||||||
("Both your Discord and Minecraft account had linked accounts. Merged all account links.", mc_id)
|
("Both your Discord and Minecraft account had linked accounts. Merged all account links.", mc_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ctx.send(r.content(status)).await?;
|
let link = Link::new(link_id).minecraft(&pool).await?.discord(&pool).await?;
|
||||||
let link = Link::new(link_id).minecraft(&pool).await.discord(&pool).await;
|
let s = list_string(link, user.id.get());
|
||||||
let s = list_string(link, user.id.get()).await;
|
|
||||||
ChannelId::new(1257776992497959075).send_message(
|
ChannelId::new(1257776992497959075).send_message(
|
||||||
ctx,
|
ctx,
|
||||||
CreateMessage::new()
|
CreateMessage::new()
|
||||||
|
@ -202,15 +196,14 @@ pub(crate) async fn add<'a>(
|
||||||
CreateButton::new("deny_verification").emoji(ReactionType::from('❌')),
|
CreateButton::new("deny_verification").emoji(ReactionType::from('❌')),
|
||||||
])]),
|
])]),
|
||||||
).await?;
|
).await?;
|
||||||
}
|
ctx.send(CreateReply::default().ephemeral(false).content(status)).await?;
|
||||||
false => {
|
|
||||||
let r = CreateReply::default().ephemeral(true)
|
|
||||||
.content(format!("The Discord account linked on Hypixel does not seem to match the specified account.\n\
|
|
||||||
Expected account link: `{}`", user.name));
|
|
||||||
ctx.send(r).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
},
|
||||||
|
false => {
|
||||||
|
Err(Error::Other(format!("The Discord account linked on Hypixel does not match the specified discord account.\n\
|
||||||
|
Please set your linked Discord account on Hypixel to `{}`.", user.name)))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[poise::command(slash_command)]
|
#[poise::command(slash_command)]
|
||||||
|
@ -223,18 +216,18 @@ pub(crate) async fn list(
|
||||||
let r = CreateReply::default().ephemeral(false);
|
let r = CreateReply::default().ephemeral(false);
|
||||||
let pool: Pool<Sqlite> = ctx.data().sqlite_pool.clone();
|
let pool: Pool<Sqlite> = ctx.data().sqlite_pool.clone();
|
||||||
let link_id = link_id_from_discord(&pool, user.id.get()).await.expect("This user has no linked accounts");
|
let link_id = link_id_from_discord(&pool, user.id.get()).await.expect("This user has no linked accounts");
|
||||||
let link = Link::new(link_id).minecraft(&pool).await.discord(&pool).await;
|
let link = Link::new(link_id).minecraft(&pool).await?.discord(&pool).await?;
|
||||||
let s = list_string(link, user.id.get()).await;
|
let s = list_string(link, user.id.get());
|
||||||
ctx.send(r.content(s).allowed_mentions(CreateAllowedMentions::new().empty_roles().empty_users())).await?;
|
ctx.send(r.content(s).allowed_mentions(CreateAllowedMentions::new().empty_roles().empty_users())).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[poise::command(slash_command)]
|
#[poise::command(slash_command)]
|
||||||
pub(crate) async fn remove(_ctx: Context<'_>) -> Result<(), Error> {
|
pub(crate) async fn remove(_ctx: Context<'_>) -> Result<(), Error> {
|
||||||
unreachable!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_string(link: Link, user_id: u64) -> String {
|
fn list_string(link: Link, user_id: u64) -> String {
|
||||||
let mut discord_list = String::from("### Discord:");
|
let mut discord_list = String::from("### Discord:");
|
||||||
for dc in link.discord_ids {
|
for dc in link.discord_ids {
|
||||||
discord_list.push_str(format!("\n- <@{}>", dc.id).as_str());
|
discord_list.push_str(format!("\n- <@{}>", dc.id).as_str());
|
||||||
|
@ -247,26 +240,16 @@ async fn list_string(link: Link, user_id: u64) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn link_id_from_minecraft(pool: &Pool<Sqlite>, minecraft_uuid: &str) -> Option<u16> {
|
async fn link_id_from_minecraft(pool: &Pool<Sqlite>, minecraft_uuid: &str) -> Option<u16> {
|
||||||
return query_as(
|
query_as(format!("SELECT link_id FROM minecraft_links WHERE minecraft_uuid = \"{minecraft_uuid}\" LIMIT 1;").as_str())
|
||||||
format!(
|
|
||||||
"SELECT link_id FROM minecraft_links WHERE minecraft_uuid = \"{minecraft_uuid}\" LIMIT 1;"
|
|
||||||
)
|
|
||||||
.as_str(),
|
|
||||||
)
|
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await.expect("Database error: fetching link id by uuid")
|
||||||
.expect("Database error: fetching link id by uuid")
|
.map(|link_id: LinkId| link_id.link_id.cast_unsigned())
|
||||||
.map(|link_id: LinkId| link_id.link_id.cast_unsigned());
|
|
||||||
}
|
}
|
||||||
async fn link_id_from_discord(pool: &Pool<Sqlite>, snowflake: u64) -> Option<u16> {
|
async fn link_id_from_discord(pool: &Pool<Sqlite>, snowflake: u64) -> Option<u16> {
|
||||||
let discord_id: i64 = snowflake.cast_signed();
|
query_as(format!("SELECT link_id FROM discord_links WHERE discord_id = {} LIMIT 1;", snowflake.cast_signed()).as_str())
|
||||||
return query_as(
|
|
||||||
format!("SELECT link_id FROM discord_links WHERE discord_id = {discord_id} LIMIT 1;").as_str(),
|
|
||||||
)
|
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await.expect("Database error: fetching link id by discord")
|
||||||
.expect("Database error: fetching link id by discord")
|
.map(|link_id: LinkId| link_id.link_id.cast_unsigned())
|
||||||
.map(|link_id: LinkId| link_id.link_id.cast_unsigned());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(sqlx::FromRow)]
|
#[derive(sqlx::FromRow)]
|
||||||
|
@ -274,11 +257,9 @@ struct LinkId {
|
||||||
link_id: i16,
|
link_id: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn new_link_id(pool: &Pool<Sqlite>) -> u16 {
|
async fn new_link_id(pool: &Pool<Sqlite>) -> Result<u16, Error> {
|
||||||
let result: Result<LinkId, sqlx::Error> = query_as("SELECT MAX(link_id) AS link_id FROM minecraft_links;")
|
let result: LinkId = query_as("SELECT MAX(link_id) AS link_id FROM minecraft_links;")
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await;
|
.await?;
|
||||||
result
|
Ok(result.link_id.cast_unsigned() + 1)
|
||||||
.expect("Database error: fetching new id")
|
|
||||||
.link_id.cast_unsigned() + 1
|
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
|
use poise::CreateReply;
|
||||||
use crate::{Context, Error};
|
use crate::Context;
|
||||||
use crate::commands::command_helper;
|
use crate::error::Error;
|
||||||
|
|
||||||
#[poise::command(slash_command, guild_only, owners_only)]
|
#[poise::command(slash_command, guild_only, owners_only)]
|
||||||
pub(crate) async fn bots(
|
pub(crate) async fn bots(
|
||||||
|
@ -12,6 +12,7 @@ pub(crate) async fn bots(
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
ctx.defer_ephemeral().await?;
|
ctx.defer_ephemeral().await?;
|
||||||
*ctx.data().bots.write().await = bots;
|
*ctx.data().bots.write().await = bots;
|
||||||
let reply = format!("{} bots are now registered as available", bots).to_string();
|
let content = format!("{} bots are now registered as available", bots).to_string();
|
||||||
command_helper::send_simple(ctx, reply).await
|
ctx.send(CreateReply::default().content(content).ephemeral(true)).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,7 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::{Context, Error};
|
use crate::Context;
|
||||||
|
use crate::error::Error;
|
||||||
pub(crate) async fn send_simple(ctx: Context<'_>, reply: String) -> Result<(), Error> {
|
|
||||||
if let Err(why) = ctx
|
|
||||||
.send(poise::CreateReply {
|
|
||||||
content: Some(reply),
|
|
||||||
embeds: vec![],
|
|
||||||
attachments: vec![],
|
|
||||||
ephemeral: Some(true),
|
|
||||||
components: None,
|
|
||||||
allowed_mentions: None,
|
|
||||||
reply: false,
|
|
||||||
__non_exhaustive: (),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
println!("Error sending message: {:?}", why)
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn cooldown(ctx: &Context, user: u64, guild: u64) -> Result<(), Error> {
|
pub(crate) fn cooldown(ctx: &Context, user: u64, guild: u64) -> Result<(), Error> {
|
||||||
let mut cooldown_tracker = ctx.command().cooldowns.lock().unwrap();
|
let mut cooldown_tracker = ctx.command().cooldowns.lock().unwrap();
|
||||||
|
@ -35,7 +17,7 @@ pub(crate) fn cooldown(ctx: &Context, user: u64, guild: u64) -> Result<(), Error
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
match cooldown_tracker.remaining_cooldown((*ctx).cooldown_context(), &cooldown_durations) {
|
match cooldown_tracker.remaining_cooldown((*ctx).cooldown_context(), &cooldown_durations) {
|
||||||
Some(remaining) => Err(format!("Please wait {} seconds", remaining.as_secs()).into()),
|
Some(remaining) => Err(Error::OnCooldown(remaining)),
|
||||||
None => Ok(cooldown_tracker.start_cooldown((*ctx).cooldown_context())),
|
None => Ok(cooldown_tracker.start_cooldown((*ctx).cooldown_context())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use poise::CreateReply;
|
use poise::CreateReply;
|
||||||
use serenity::all::CreateAllowedMentions;
|
use serenity::all::CreateAllowedMentions;
|
||||||
|
|
||||||
use crate::{Context, Error};
|
use crate::Context;
|
||||||
use crate::commands::command_helper;
|
use crate::commands::command_helper;
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
#[poise::command(slash_command, guild_only)]
|
#[poise::command(slash_command, guild_only)]
|
||||||
pub(crate) async fn helpstart(
|
pub(crate) async fn helpstart(
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use poise::{ChoiceParameter, CreateReply};
|
use poise::{ChoiceParameter, CreateReply};
|
||||||
use serenity::all::{CreateAllowedMentions, RoleId};
|
use serenity::all::{CreateAllowedMentions, RoleId};
|
||||||
|
|
||||||
use crate::{Context, Error};
|
use crate::Context;
|
||||||
//from main.rs
|
//from main.rs
|
||||||
use crate::commands::command_helper::cooldown;
|
use crate::commands::command_helper::cooldown;
|
||||||
//
|
//
|
||||||
use crate::commands::lfg::Difficulty::Normal;
|
use crate::commands::lfg::Difficulty::Normal;
|
||||||
use crate::commands::lfg::Map::*;
|
use crate::commands::lfg::Map::*;
|
||||||
use crate::commands::lfg::Mode::*;
|
use crate::commands::lfg::Mode::*;
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
#[derive(Debug, poise::ChoiceParameter, PartialEq)]
|
#[derive(Debug, poise::ChoiceParameter, PartialEq)]
|
||||||
pub enum Map {
|
pub enum Map {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{Context, Error};
|
use crate::Context;
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
const XD: &str = "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⡿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣧⣄⡀⠀⠀⠀⢀⣠⣼⣿⣿⣿⣿⣧⣄⡀⠀⠀⠀⣀⣤⣼⣷⣦⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠻⣿⣿⣿⣿⣿⣿⠟⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣶⣦⣄⡀⠀⠀⠙⢿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⠋⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⡿⠁⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡗⠀⠀⠀⠐⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⣠⡀⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⠀⣰⣿⣷⡄⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⣾⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⡟⠁⠀⢀⣼⣿⣿⣿⣿⣆⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⢀⣼⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⠋⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⠿⠛⠁⠀⠀⣠⣾⣿⣿⣿⣿⣿\n⣿⣿⣿⠿⠛⠁⠀⠀⠀⠙⠻⣿⣿⣿⣿⣿⡿⠟⠋⠀⠀⠀⠈⠛⠻⡿⠟⠛⠁⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣶⣶⣶⣷⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n";
|
const XD: &str = "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⢿⡿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣧⣄⡀⠀⠀⠀⢀⣠⣼⣿⣿⣿⣿⣧⣄⡀⠀⠀⠀⣀⣤⣼⣷⣦⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠻⣿⣿⣿⣿⣿⣿⠟⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣶⣦⣄⡀⠀⠀⠙⢿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⠋⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠈⢿⡿⠁⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡗⠀⠀⠀⠐⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⠀⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⣠⡀⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⠀⣰⣿⣷⡄⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⣾⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⡟⠁⠀⢀⣼⣿⣿⣿⣿⣆⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⢀⣼⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⠋⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠙⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⣿⠿⠛⠁⠀⠀⣠⣾⣿⣿⣿⣿⣿\n⣿⣿⣿⠿⠛⠁⠀⠀⠀⠙⠻⣿⣿⣿⣿⣿⡿⠟⠋⠀⠀⠀⠈⠛⠻⡿⠟⠛⠁⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣶⣶⣶⣷⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n";
|
||||||
|
|
||||||
|
|
46
src/error.rs
Normal file
46
src/error.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
SqlxError(sqlx::Error),
|
||||||
|
HttpsError(reqwest::Error),
|
||||||
|
ParsingError(serde_json::Error),
|
||||||
|
SerenityError(serenity::Error),
|
||||||
|
OnCooldown(std::time::Duration),
|
||||||
|
Other(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::SqlxError(e) => write!(f, "SQLx Error: {}", e),
|
||||||
|
Error::HttpsError(e) => write!(f, "HTTPS Error (Hypixel / Mojang API):\n{}", e),
|
||||||
|
Error::ParsingError(e) => write!(f, "Parsing Error:\n {}", e),
|
||||||
|
Error::SerenityError(e) => write!(f, "Serenity Error:\n {}", e),
|
||||||
|
Error::OnCooldown(d) => write!(f, "This command is on cooldown. {}s remaining.", d.as_secs()),
|
||||||
|
Error::Other(s) => write!(f, "{}", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<sqlx::Error> for Error {
|
||||||
|
fn from(error: sqlx::Error) -> Self {
|
||||||
|
Error::SqlxError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<reqwest::Error> for Error {
|
||||||
|
fn from(error: reqwest::Error) -> Self {
|
||||||
|
Error::HttpsError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serde_json::Error> for Error {
|
||||||
|
fn from(error: serde_json::Error) -> Self {
|
||||||
|
Error::ParsingError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serenity::Error> for Error {
|
||||||
|
fn from(error: serenity::Error) -> Self {
|
||||||
|
Error::SerenityError(error)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use serenity::all::{ComponentInteraction, ComponentInteractionDataKind, Context, CreateMessage, EditMessage, GuildId, Interaction, RoleId};
|
use serenity::all::{ComponentInteraction, ComponentInteractionDataKind, Context, CreateMessage, EditMessage, GuildId, Interaction, RoleId};
|
||||||
|
|
||||||
use crate::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
pub(crate) async fn component(ctx: &Context, interaction: &Interaction) -> Result<(), Error> {
|
pub(crate) async fn component(ctx: &Context, interaction: &Interaction) -> Result<(), Error> {
|
||||||
let component = interaction.clone().message_component().unwrap();
|
let component = interaction.clone().message_component().unwrap();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serenity::all::{Context, Message};
|
use serenity::all::{Context, Message};
|
||||||
|
|
||||||
use crate::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
pub(crate) async fn on_create(ctx: &Context, msg: &Message) -> Result<(), Error> {
|
pub(crate) async fn on_create(ctx: &Context, msg: &Message) -> Result<(), Error> {
|
||||||
match msg.guild_id.map(|g| g.get()) {
|
match msg.guild_id.map(|g| g.get()) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use serenity::all::{Context, GuildChannel};
|
use serenity::all::{Context, GuildChannel};
|
||||||
use serenity::builder::EditThread;
|
use serenity::builder::EditThread;
|
||||||
|
|
||||||
use crate::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
pub(crate) async fn on_create(ctx: &Context, thread: &GuildChannel) -> Result<(), Error> {
|
pub(crate) async fn on_create(ctx: &Context, thread: &GuildChannel) -> Result<(), Error> {
|
||||||
match thread.parent_id.map(|parent| parent.get()) {
|
match thread.parent_id.map(|parent| parent.get()) {
|
||||||
|
|
20
src/main.rs
20
src/main.rs
|
@ -5,22 +5,25 @@ use std::convert::Into;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use poise::serenity_prelude as serenity;
|
use poise::{CreateReply, FrameworkError, serenity_prelude as serenity};
|
||||||
use serenity::{FullEvent, model::id::UserId};
|
use serenity::{FullEvent, model::id::UserId};
|
||||||
use serenity::all::{ActivityData, InteractionType, RoleId};
|
use serenity::all::{ActivityData, InteractionType, RoleId};
|
||||||
use serenity::prelude::GatewayIntents;
|
use serenity::prelude::GatewayIntents;
|
||||||
use sqlx::Sqlite;
|
use sqlx::Sqlite;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
use error::Error;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod handlers;
|
mod handlers;
|
||||||
|
mod error;
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
bots: Arc<RwLock<u8>>,
|
bots: Arc<RwLock<u8>>,
|
||||||
sqlite_pool: sqlx::Pool<Sqlite>,
|
sqlite_pool: sqlx::Pool<Sqlite>,
|
||||||
hypixel_api_client: reqwest::Client,
|
hypixel_api_client: reqwest::Client,
|
||||||
} // User data, which is stored and accessible in all command invocations
|
} // User data, which is stored and accessible in all command invocations
|
||||||
type Error = Box<dyn std::error::Error + Send + Sync>;
|
|
||||||
|
|
||||||
type Context<'a> = poise::Context<'a, Data, Error>;
|
type Context<'a> = poise::Context<'a, Data, Error>;
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -59,7 +62,18 @@ async fn main() {
|
||||||
on_error: |error| {
|
on_error: |error| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
match error {
|
match error {
|
||||||
other => poise::builtins::on_error(other).await.unwrap(),
|
FrameworkError::CommandStructureMismatch { description, ctx, .. } => {
|
||||||
|
if let Err(e) = ctx.send(CreateReply::default()
|
||||||
|
.content(format!("# Command arguments did not match. The command probably has been updated recently. Try reloading Discord. Description:\n{}", description)))
|
||||||
|
.await {
|
||||||
|
tracing::error!("Fatal error while sending error message: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
if let Err(e) = poise::builtins::on_error(other).await {
|
||||||
|
tracing::error!("Fatal error while sending error message: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue