reformat LFG message with headline
This commit is contained in:
parent
f44af892b4
commit
86a23a327a
4 changed files with 64 additions and 39 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
use std::ops::Add;
|
||||||
use poise::CreateReply;
|
use poise::CreateReply;
|
||||||
use reqwest::{Client, Response};
|
use reqwest::{Client, Response};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -65,9 +66,9 @@ impl Uuid {
|
||||||
struct DiscordId {
|
struct DiscordId {
|
||||||
id: u64,
|
id: u64,
|
||||||
}
|
}
|
||||||
impl DiscordId {
|
impl Uuid {
|
||||||
async fn matches_fetch(user: &User, uuid: &str, client: &Client) -> Result<bool, Error> {
|
async fn has_discord_user(&self, user: &User, 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={}", 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.links.discord == user.name;
|
||||||
|
@ -142,32 +143,32 @@ pub(crate) async fn add<'a>(
|
||||||
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);
|
let force: bool = force.unwrap_or(false) && ctx.framework().options.owners.contains(&ctx.author().id);
|
||||||
match DiscordId::matches_fetch(&user, uuid.get(), &ctx.data().hypixel_api_client).await? || force {
|
match uuid.has_discord_user(&user, &ctx.data().hypixel_api_client).await? || force {
|
||||||
true => {
|
true => {
|
||||||
let pool: Pool<Sqlite> = ctx.data().sqlite_pool.clone();
|
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 {
|
||||||
None => match link_id_from_discord(&pool, user.id.get()).await {
|
None => 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.inner, user.id.get()).as_str())
|
||||||
.execute(&pool)
|
.execute(pool)
|
||||||
.await?;
|
.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.inner, uuid.get()).as_str())
|
||||||
.execute(&pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
"Linked your Discord and Minecraft account."
|
"Linked your Discord and Minecraft account."
|
||||||
}
|
}
|
||||||
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.inner, uuid.get()).as_str())
|
||||||
.execute(&pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
"Your Discord account has previously had an account linked. Added the new link."
|
"Your Discord account has previously had an account linked. Added the new link."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(mc_id) => match link_id_from_discord(&pool, user.id.get()).await {
|
Some(mc_id) => 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.inner, user.id.get()).as_str())
|
||||||
.execute(&pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
"Your Minecraft account has previously had an account linked. Added the new link."
|
"Your Minecraft account has previously had an account linked. Added the new link."
|
||||||
}
|
}
|
||||||
|
@ -175,22 +176,22 @@ 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.cast_signed(),
|
mc_id.inner,
|
||||||
dc_id.cast_signed()
|
dc_id.inner
|
||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
)
|
)
|
||||||
.execute(&pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
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.cast_signed(),
|
mc_id.inner,
|
||||||
dc_id.cast_signed()
|
dc_id.inner
|
||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
)
|
)
|
||||||
.execute(&pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
"Both your Discord and Minecraft account had linked accounts. Merged all account links."
|
"Both your Discord and Minecraft account had linked accounts. Merged all account links."
|
||||||
}
|
}
|
||||||
|
@ -251,7 +252,8 @@ pub(crate) async fn list(ctx: Context<'_>, user: User) -> Result<(), Error> {
|
||||||
pub(crate) async fn list_string(pool: &Pool<Sqlite>, user: &User) -> Result<String, Error> {
|
pub(crate) async fn list_string(pool: &Pool<Sqlite>, user: &User) -> Result<String, Error> {
|
||||||
let link_id: u16 = link_id_from_discord(pool, user.id.get())
|
let link_id: u16 = link_id_from_discord(pool, user.id.get())
|
||||||
.await
|
.await
|
||||||
.expect("This user has no linked accounts");
|
.expect("This user has no linked accounts")
|
||||||
|
.into();
|
||||||
let link: Link = Link::new(link_id).minecraft(pool).await?.discord(pool).await?;
|
let link: Link = Link::new(link_id).minecraft(pool).await?.discord(pool).await?;
|
||||||
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 {
|
||||||
|
@ -271,17 +273,16 @@ pub(crate) async fn list_string(pool: &Pool<Sqlite>, user: &User) -> Result<Stri
|
||||||
|
|
||||||
#[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> {
|
||||||
todo!()
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
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<LinkId> {
|
||||||
query_as(format!("SELECT link_id FROM minecraft_links WHERE minecraft_uuid = \"{minecraft_uuid}\" LIMIT 1;").as_str())
|
query_as(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())
|
|
||||||
}
|
}
|
||||||
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<LinkId> {
|
||||||
query_as(
|
query_as(
|
||||||
format!(
|
format!(
|
||||||
"SELECT link_id FROM discord_links WHERE discord_id = {} LIMIT 1;",
|
"SELECT link_id FROM discord_links WHERE discord_id = {} LIMIT 1;",
|
||||||
|
@ -292,17 +293,40 @@ async fn link_id_from_discord(pool: &Pool<Sqlite>, snowflake: u64) -> Option<u16
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await
|
.await
|
||||||
.expect("Database error: fetching link_id for discord_id")
|
.expect("Database error: fetching link_id for discord_id")
|
||||||
.map(|link_id: LinkId| link_id.link_id.cast_unsigned())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(sqlx::FromRow)]
|
#[derive(sqlx::FromRow)]
|
||||||
struct LinkId {
|
struct LinkId {
|
||||||
link_id: i16,
|
#[sqlx(rename = "link_id")]
|
||||||
|
inner: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn new_link_id(pool: &Pool<Sqlite>) -> Result<u16, Error> {
|
impl From<u16> for LinkId {
|
||||||
|
fn from(unsigned: u16) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: unsigned.cast_signed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<u16> for LinkId {
|
||||||
|
fn into(self) -> u16 {
|
||||||
|
self.inner.cast_unsigned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<i16> for LinkId {
|
||||||
|
type Output = LinkId;
|
||||||
|
|
||||||
|
fn add(mut self, rhs: i16) -> Self::Output {
|
||||||
|
self.inner += rhs;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn new_link_id(pool: &Pool<Sqlite>) -> Result<LinkId, Error> {
|
||||||
let result: LinkId = 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?;
|
||||||
Ok(result.link_id.cast_unsigned() + 1)
|
Ok(result + 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub(crate) async fn helpstart(
|
||||||
} else {
|
} else {
|
||||||
command_helper::cooldown(&ctx, 1200, 600)?;
|
command_helper::cooldown(&ctx, 1200, 600)?;
|
||||||
reply
|
reply
|
||||||
.content(format!("<@&{ping}>\nneed: {}", needed_players - bots))
|
.content(format!("## <@&{ping}>\nneed: {}", needed_players - bots))
|
||||||
.ephemeral(false)
|
.ephemeral(false)
|
||||||
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping]))
|
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping]))
|
||||||
};
|
};
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub(crate) async fn lfg(
|
||||||
AlienArcadium => Normal,
|
AlienArcadium => Normal,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut reply_content: String = format!("<@&{ping}> {current}/{desired} {map_name}", );
|
let mut reply_content: String = format!("## <@&{ping}> {current}/{desired} {map_name}", );
|
||||||
match difficulty {
|
match difficulty {
|
||||||
Normal => {}
|
Normal => {}
|
||||||
Difficulty::Hard | Difficulty::Rip => {
|
Difficulty::Hard | Difficulty::Rip => {
|
||||||
|
@ -113,7 +113,7 @@ pub(crate) async fn lfg(
|
||||||
match note {
|
match note {
|
||||||
None => {}
|
None => {}
|
||||||
Some(note) => {
|
Some(note) => {
|
||||||
reply_content.push_str(format!("\nNote: {note}").as_str());
|
reply_content.push_str(format!("\n**Note:** {note}").as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let reply: CreateReply = CreateReply::default()
|
let reply: CreateReply = CreateReply::default()
|
||||||
|
@ -193,7 +193,7 @@ pub(crate) async fn expert(
|
||||||
.roles
|
.roles
|
||||||
.iter()
|
.iter()
|
||||||
.any(|user_role: &RoleId| allowed_roles.contains(&user_role.get()));
|
.any(|user_role: &RoleId| allowed_roles.contains(&user_role.get()));
|
||||||
let reply_content: String = format!("{current}/{desired} <@&{ping}>: {note}");
|
let reply_content: String = format!("## {current}/{desired} <@&{ping}>: {note}");
|
||||||
let reply: CreateReply = match is_expert {
|
let reply: CreateReply = match is_expert {
|
||||||
true => CreateReply::default()
|
true => CreateReply::default()
|
||||||
.content(reply_content)
|
.content(reply_content)
|
||||||
|
@ -240,7 +240,7 @@ pub(crate) async fn other(
|
||||||
let ping: u64 = match game {
|
let ping: u64 = match game {
|
||||||
OtherPing::GeoGuessr => 1302249562999885824_u64,
|
OtherPing::GeoGuessr => 1302249562999885824_u64,
|
||||||
};
|
};
|
||||||
let reply_content: String = format!("{current}/{desired} <@&{ping}>: {note}");
|
let reply_content: String = format!("## {current}/{desired} <@&{ping}>: {note}");
|
||||||
|
|
||||||
let reply: CreateReply = CreateReply::default()
|
let reply: CreateReply = CreateReply::default()
|
||||||
.content(reply_content)
|
.content(reply_content)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||||
use poise::{CreateReply, FrameworkError};
|
use poise::{CreateReply, FrameworkError};
|
||||||
|
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
@ -19,8 +20,8 @@ pub enum Error {
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
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::HttpsError(e) => write!(f, "HTTPS Error (Hypixel / Mojang API):\n{}", e),
|
||||||
|
|
Loading…
Add table
Reference in a new issue