account list rework + run rustfmt
This commit is contained in:
parent
534576778d
commit
15ab265dbe
14 changed files with 450 additions and 305 deletions
4
.rustfmt.toml
Normal file
4
.rustfmt.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
max_width = 140
|
||||||
|
use_small_heuristics = "Default"
|
||||||
|
reorder_imports = true
|
||||||
|
format_strings = true
|
|
@ -2,21 +2,14 @@ use poise::CreateReply;
|
||||||
use reqwest::{Client, Response};
|
use reqwest::{Client, Response};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
all::{
|
all::{ChannelId, CreateActionRow, CreateAllowedMentions, CreateButton, CreateMessage, ReactionType, User},
|
||||||
ChannelId,
|
|
||||||
CreateActionRow,
|
|
||||||
CreateAllowedMentions,
|
|
||||||
CreateButton,
|
|
||||||
CreateMessage,
|
|
||||||
ReactionType,
|
|
||||||
User,
|
|
||||||
},
|
|
||||||
json::JsonError,
|
json::JsonError,
|
||||||
};
|
};
|
||||||
use sqlx::{Pool, query_as, Sqlite};
|
use sqlx::{query_as, Pool, Sqlite};
|
||||||
|
|
||||||
use crate::Context;
|
use crate::commands::command_helper::cooldown;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Links {
|
struct Links {
|
||||||
|
@ -40,7 +33,7 @@ struct HypixelResponse {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct MojangPlayer {
|
struct MojangPlayer {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
//pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, sqlx::FromRow)]
|
#[derive(PartialEq, sqlx::FromRow)]
|
||||||
|
@ -55,8 +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: Response = reqwest::get(url).await?;
|
let response: Response = reqwest::get(url).await?;
|
||||||
let response_text = response.error_for_status()?.text().await.unwrap();
|
let response_text = response.error_for_status()?.text().await.unwrap();
|
||||||
let uuid = (serde_json::from_str(response_text.as_str())
|
let uuid = (serde_json::from_str(response_text.as_str()) as Result<MojangPlayer, JsonError>)
|
||||||
as Result<MojangPlayer, JsonError>)
|
|
||||||
.map(|mojang_player: MojangPlayer| Uuid { uuid: mojang_player.id })?;
|
.map(|mojang_player: MojangPlayer| Uuid { uuid: mojang_player.id })?;
|
||||||
Ok(uuid)
|
Ok(uuid)
|
||||||
/*match response.error_for_status() {
|
/*match response.error_for_status() {
|
||||||
|
@ -72,6 +64,15 @@ impl Uuid {
|
||||||
Details: {}", why).as_str())),
|
Details: {}", why).as_str())),
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn ign(&self) -> Result<String, Error> {
|
||||||
|
let url: String = format!("https://sessionserver.mojang.com/session/minecraft/profile/{}", self.uuid);
|
||||||
|
let response: Response = reqwest::get(url).await?;
|
||||||
|
let response_text = response.error_for_status()?.text().await.unwrap();
|
||||||
|
let ign = (serde_json::from_str(response_text.as_str()) as Result<MojangPlayer, JsonError>)
|
||||||
|
.map(|mojang_player: MojangPlayer| mojang_player.name)?;
|
||||||
|
Ok(ign)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
struct DiscordId {
|
struct DiscordId {
|
||||||
|
@ -82,8 +83,7 @@ impl DiscordId {
|
||||||
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?;
|
||||||
let response_text = response.error_for_status()?.text().await.unwrap();
|
let response_text = response.error_for_status()?.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)
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ where
|
||||||
fn from_row(row: &'a R) -> sqlx::Result<Self> {
|
fn from_row(row: &'a R) -> sqlx::Result<Self> {
|
||||||
let discord_id: i64 = row.try_get("discord_id")?;
|
let discord_id: i64 = row.try_get("discord_id")?;
|
||||||
Ok(DiscordId {
|
Ok(DiscordId {
|
||||||
id: discord_id.cast_unsigned()
|
id: discord_id.cast_unsigned(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,14 +116,17 @@ impl Link {
|
||||||
}
|
}
|
||||||
async fn minecraft(mut self, pool: &Pool<Sqlite>) -> Result<Self, Error> {
|
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 =
|
||||||
.fetch_all(pool).await?;
|
query_as(format!("SELECT minecraft_uuid AS uuid FROM minecraft_links WHERE link_id = {link_id};").as_str())
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
async fn discord(mut self, pool: &Pool<Sqlite>) -> Result<Self, Error> {
|
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?;
|
.fetch_all(pool)
|
||||||
|
.await?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +136,6 @@ pub(crate) async fn account(_ctx: Context<'_>) -> Result<(), Error> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command)]
|
#[poise::command(slash_command)]
|
||||||
pub(crate) async fn add<'a>(
|
pub(crate) async fn add<'a>(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
|
@ -141,52 +143,70 @@ pub(crate) async fn add<'a>(
|
||||||
#[min_length = 2]
|
#[min_length = 2]
|
||||||
#[max_length = 16]
|
#[max_length = 16]
|
||||||
ign: String,
|
ign: String,
|
||||||
user: Option<User>,
|
#[description = "Discord User"] user: Option<User>,
|
||||||
|
#[description = "Minecraft username"] force: Option<bool>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
ctx.defer_ephemeral().await?;
|
ctx.defer_ephemeral().await?;
|
||||||
let user = user.unwrap_or(ctx.author().clone());
|
let user: User = user.unwrap_or(ctx.author().clone());
|
||||||
let uuid = Uuid::fetch(ign.as_str()).await?;
|
let uuid: Uuid = Uuid::fetch(ign.as_str()).await?;
|
||||||
match DiscordId::matches_fetch(&user, uuid.get(), &ctx.data().hypixel_api_client).await? {
|
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 {
|
||||||
true => {
|
true => {
|
||||||
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: &str = 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?;
|
.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?;
|
.execute(&pool)
|
||||||
("Linked your Discord and Minecraft account.", id)
|
.await?;
|
||||||
|
"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.cast_signed(), uuid.get()).as_str())
|
||||||
.execute(&pool).await?;
|
.execute(&pool)
|
||||||
("Your Discord account has previously had an account linked. Added the new link.", dc_id)
|
.await?;
|
||||||
|
"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.cast_signed(), user.id.get()).as_str())
|
||||||
.execute(&pool).await?;
|
.execute(&pool)
|
||||||
("Your Minecraft account has previously had an account linked. Added the new link.", mc_id)
|
.await?;
|
||||||
|
"Your Minecraft account has previously had an account linked. Added the new link."
|
||||||
}
|
}
|
||||||
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(
|
||||||
.execute(&pool).await?;
|
format!(
|
||||||
sqlx::query(format!("UPDATE discord_links SET link_id = {} WHERE link_id = {};", mc_id.cast_signed(), dc_id.cast_signed()).as_str())
|
"UPDATE minecraft_links SET link_id = {} WHERE link_id = {};",
|
||||||
.execute(&pool).await?;
|
mc_id.cast_signed(),
|
||||||
("Both your Discord and Minecraft account had linked accounts. Merged all account links.", mc_id)
|
dc_id.cast_signed()
|
||||||
}
|
)
|
||||||
}
|
.as_str(),
|
||||||
|
)
|
||||||
|
.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(),
|
||||||
|
)
|
||||||
|
.execute(&pool)
|
||||||
|
.await?;
|
||||||
|
"Both your Discord and Minecraft account had linked accounts. Merged all account links."
|
||||||
}
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let link = Link::new(link_id).minecraft(&pool).await?.discord(&pool).await?;
|
let s = format!("Verification request for {} with IGN `{}`", user.id.get(), ign);
|
||||||
let s = list_string(link, user.id.get());
|
ChannelId::new(1257776992497959075)
|
||||||
ChannelId::new(1257776992497959075).send_message(
|
.send_message(
|
||||||
ctx,
|
ctx,
|
||||||
CreateMessage::new()
|
CreateMessage::new()
|
||||||
.content(s)
|
.content(s)
|
||||||
|
@ -194,61 +214,81 @@ pub(crate) async fn add<'a>(
|
||||||
.components(vec![CreateActionRow::Buttons(vec![
|
.components(vec![CreateActionRow::Buttons(vec![
|
||||||
CreateButton::new("accept_verification").emoji(ReactionType::from('✅')),
|
CreateButton::new("accept_verification").emoji(ReactionType::from('✅')),
|
||||||
CreateButton::new("deny_verification").emoji(ReactionType::from('❌')),
|
CreateButton::new("deny_verification").emoji(ReactionType::from('❌')),
|
||||||
|
CreateButton::new("list_accounts").emoji(ReactionType::from('📜')),
|
||||||
])]),
|
])]),
|
||||||
).await?;
|
)
|
||||||
|
.await?;
|
||||||
ctx.send(CreateReply::default().ephemeral(false).content(status)).await?;
|
ctx.send(CreateReply::default().ephemeral(false).content(status)).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)))
|
|
||||||
}
|
}
|
||||||
|
false => Err(Error::Other(format!(
|
||||||
|
"The Discord account linked on Hypixel does not match the specified discord account.\nPlease set your linked Discord account \
|
||||||
|
on Hypixel to `{}`.",
|
||||||
|
user.name
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[poise::command(slash_command)]
|
#[poise::command(slash_command)]
|
||||||
pub(crate) async fn list(
|
pub(crate) async fn list(ctx: Context<'_>, user: Option<User>) -> Result<(), Error> {
|
||||||
ctx: Context<'_>,
|
ctx.defer_ephemeral().await?;
|
||||||
user: Option<User>,
|
cooldown(&ctx, 600, 300)?;
|
||||||
) -> Result<(), Error> {
|
let user: User = user.unwrap_or(ctx.author().clone());
|
||||||
ctx.defer().await?;
|
let pool: &Pool<Sqlite> = &ctx.data().sqlite_pool;
|
||||||
let user = user.unwrap_or(ctx.author().clone());
|
let s: String = list_string(pool, &user).await?;
|
||||||
let r = CreateReply::default().ephemeral(false);
|
let r: CreateReply = CreateReply::default().ephemeral(false);
|
||||||
let pool: Pool<Sqlite> = ctx.data().sqlite_pool.clone();
|
ctx.send(
|
||||||
let link_id = link_id_from_discord(&pool, user.id.get()).await.expect("This user has no linked accounts");
|
r.content(s)
|
||||||
let link = Link::new(link_id).minecraft(&pool).await?.discord(&pool).await?;
|
.allowed_mentions(CreateAllowedMentions::new().empty_roles().empty_users()),
|
||||||
let s = list_string(link, user.id.get());
|
)
|
||||||
ctx.send(r.content(s).allowed_mentions(CreateAllowedMentions::new().empty_roles().empty_users())).await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
.await
|
||||||
|
.expect("This user has no linked accounts");
|
||||||
|
let link: Link = Link::new(link_id).minecraft(pool).await?.discord(pool).await?;
|
||||||
|
let mut discord_list = String::from("### Discord:");
|
||||||
|
for dc in link.discord_ids {
|
||||||
|
discord_list.push_str(format!("\n- <@{}>", dc.id).as_str());
|
||||||
|
}
|
||||||
|
let mut minecraft_list = String::from("### Minecraft:");
|
||||||
|
for mc in link.minecraft_accounts {
|
||||||
|
minecraft_list.push_str(format!("\n- `{}`", mc.ign().await?).as_str());
|
||||||
|
}
|
||||||
|
Ok(format!(
|
||||||
|
"## Account list for member #{}:\n{}\n{}",
|
||||||
|
link.link_id,
|
||||||
|
discord_list.as_str(),
|
||||||
|
minecraft_list.as_str()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[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> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_string(link: Link, user_id: u64) -> String {
|
|
||||||
let mut discord_list = String::from("### Discord:");
|
|
||||||
for dc in link.discord_ids {
|
|
||||||
discord_list.push_str(format!("\n- <@{}>", dc.id).as_str());
|
|
||||||
}
|
|
||||||
let mut minecraft_list = String::from("### Minecraft:");
|
|
||||||
for mc in link.minecraft_accounts {
|
|
||||||
minecraft_list.push_str(format!("\n- `{}`", mc.get()).as_str());
|
|
||||||
}
|
|
||||||
format!("## Account list for <@{user_id}>:\n{}\n{}", discord_list.as_str(), minecraft_list.as_str())
|
|
||||||
}
|
|
||||||
|
|
||||||
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> {
|
||||||
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.expect("Database error: fetching link id by uuid")
|
.await
|
||||||
|
.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> {
|
||||||
query_as(format!("SELECT link_id FROM discord_links WHERE discord_id = {} LIMIT 1;", snowflake.cast_signed()).as_str())
|
query_as(
|
||||||
|
format!(
|
||||||
|
"SELECT link_id FROM discord_links WHERE discord_id = {} LIMIT 1;",
|
||||||
|
snowflake.cast_signed()
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await.expect("Database error: fetching link id by discord")
|
.await
|
||||||
|
.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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
|
|
||||||
use poise::CreateReply;
|
use poise::CreateReply;
|
||||||
use crate::Context;
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
#[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(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::Context;
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use poise::CreateReply;
|
use poise::CreateReply;
|
||||||
use serenity::all::CreateAllowedMentions;
|
use serenity::all::CreateAllowedMentions;
|
||||||
|
|
||||||
use crate::Context;
|
|
||||||
use crate::commands::command_helper;
|
use crate::commands::command_helper;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
#[poise::command(slash_command, guild_only)]
|
#[poise::command(slash_command, guild_only)]
|
||||||
pub(crate) async fn helpstart(
|
pub(crate) async fn helpstart(
|
||||||
|
@ -20,23 +20,19 @@ pub(crate) async fn helpstart(
|
||||||
let mut reply = CreateReply::default();
|
let mut reply = CreateReply::default();
|
||||||
let ping = match g {
|
let ping = match g {
|
||||||
1256217633959841853_u64 => 1257411572092113017_u64,
|
1256217633959841853_u64 => 1257411572092113017_u64,
|
||||||
_ => 0_u64
|
_ => 0_u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
reply = if bots >= needed_players {
|
reply = if bots >= needed_players {
|
||||||
reply.content("Bots available. Please use <@424767825001971715> in the bot-commands channel instead.")
|
reply
|
||||||
|
.content("Bots available. Please use <@424767825001971715> in the bot-commands channel instead.")
|
||||||
.ephemeral(true)
|
.ephemeral(true)
|
||||||
} else {
|
} else {
|
||||||
match command_helper::cooldown(&ctx, 1200, 600) {
|
command_helper::cooldown(&ctx, 1200, 600)?;
|
||||||
Ok(_) => reply
|
reply
|
||||||
.content(format!(
|
.content(format!("<@&{ping}>\nneed: {}", needed_players - bots))
|
||||||
"<@&{ping}>\nneed: {}",
|
|
||||||
needed_players - bots
|
|
||||||
))
|
|
||||||
.ephemeral(false)
|
.ephemeral(false)
|
||||||
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping])),
|
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping]))
|
||||||
Err(why) => reply.content(why.to_string()).ephemeral(true),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if let Err(why) = ctx.send(reply).await {
|
if let Err(why) = ctx.send(reply).await {
|
||||||
println!("Error sending message: {why}")
|
println!("Error sending message: {why}")
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use poise::{ChoiceParameter, CreateReply};
|
use poise::{ChoiceParameter, CreateReply};
|
||||||
use serenity::all::{CreateAllowedMentions, RoleId};
|
use serenity::all::{CreateAllowedMentions, RoleId};
|
||||||
|
|
||||||
use crate::Context;
|
|
||||||
//from main.rs
|
//from main.rs
|
||||||
use crate::commands::command_helper::cooldown;
|
use crate::commands::command_helper::cooldown;
|
||||||
//
|
//
|
||||||
|
@ -9,6 +8,7 @@ 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;
|
use crate::error::Error;
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
#[derive(Debug, poise::ChoiceParameter, PartialEq)]
|
#[derive(Debug, poise::ChoiceParameter, PartialEq)]
|
||||||
pub enum Map {
|
pub enum Map {
|
||||||
|
@ -68,9 +68,7 @@ pub(crate) async fn lfg(
|
||||||
note: Option<String>,
|
note: Option<String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let guild_id = ctx.guild_id().unwrap().get();
|
let guild_id = ctx.guild_id().unwrap().get();
|
||||||
let mut reply: CreateReply = CreateReply::default();
|
cooldown(&ctx, 600, 300)?;
|
||||||
reply = match cooldown(&ctx, 600, 300) {
|
|
||||||
Ok(_) => {
|
|
||||||
let current: u8 = current_players.unwrap_or(1);
|
let current: u8 = current_players.unwrap_or(1);
|
||||||
let mut desired: u8 = desired_players.unwrap_or(4);
|
let mut desired: u8 = desired_players.unwrap_or(4);
|
||||||
if current >= desired {
|
if current >= desired {
|
||||||
|
@ -98,7 +96,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 => {
|
||||||
|
@ -112,13 +110,10 @@ pub(crate) async fn lfg(
|
||||||
reply_content.push_str(format!("\nNote: {note}").as_str());
|
reply_content.push_str(format!("\nNote: {note}").as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply
|
let reply: CreateReply = CreateReply::default()
|
||||||
.content(reply_content)
|
.content(reply_content)
|
||||||
.ephemeral(false)
|
.ephemeral(false)
|
||||||
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping]))
|
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping]));
|
||||||
}
|
|
||||||
Err(why) => reply.content(why.to_string()).ephemeral(true),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(why) = ctx.send(reply).await {
|
if let Err(why) = ctx.send(reply).await {
|
||||||
println!("Error sending message: {why}");
|
println!("Error sending message: {why}");
|
||||||
|
@ -156,8 +151,7 @@ pub(crate) async fn expert(
|
||||||
#[rename = "message"]
|
#[rename = "message"]
|
||||||
note: String,
|
note: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let reply: CreateReply = match cooldown(&ctx, 600, 300) {
|
cooldown(&ctx, 600, 300)?;
|
||||||
Ok(_) => {
|
|
||||||
let current: u8 = current_players.unwrap_or(1);
|
let current: u8 = current_players.unwrap_or(1);
|
||||||
let mut desired: u8 = desired_players.unwrap_or(4);
|
let mut desired: u8 = desired_players.unwrap_or(4);
|
||||||
if current >= desired {
|
if current >= desired {
|
||||||
|
@ -166,19 +160,19 @@ pub(crate) async fn expert(
|
||||||
let (ping, allowed_roles): (u64, Vec<u64>) = match mode {
|
let (ping, allowed_roles): (u64, Vec<u64>) = match mode {
|
||||||
ExpertMap::Speedrun => (
|
ExpertMap::Speedrun => (
|
||||||
1295322375637958716,
|
1295322375637958716,
|
||||||
ROLE_LIST.iter().skip(2).map(|tier| [tier[4], tier[5]]).flatten().collect()
|
ROLE_LIST.iter().skip(2).map(|tier| [tier[4], tier[5]]).flatten().collect(),
|
||||||
),
|
),
|
||||||
ExpertMap::DeadEnd => (
|
ExpertMap::DeadEnd => (
|
||||||
1295321319344177172,
|
1295321319344177172,
|
||||||
ROLE_LIST.iter().skip(2).map(|tier| [tier[1], tier[5]]).flatten().collect()
|
ROLE_LIST.iter().skip(2).map(|tier| [tier[1], tier[5]]).flatten().collect(),
|
||||||
),
|
),
|
||||||
ExpertMap::BadBlood => (
|
ExpertMap::BadBlood => (
|
||||||
1295322259631640607,
|
1295322259631640607,
|
||||||
ROLE_LIST.iter().skip(2).map(|tier| [tier[2], tier[5]]).flatten().collect()
|
ROLE_LIST.iter().skip(2).map(|tier| [tier[2], tier[5]]).flatten().collect(),
|
||||||
),
|
),
|
||||||
ExpertMap::AlienArcadium => (
|
ExpertMap::AlienArcadium => (
|
||||||
1295322327910842441,
|
1295322327910842441,
|
||||||
ROLE_LIST.iter().skip(2).map(|tier| [tier[3], tier[5]]).flatten().collect()
|
ROLE_LIST.iter().skip(2).map(|tier| [tier[3], tier[5]]).flatten().collect(),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let is_expert: bool = ctx
|
let is_expert: bool = ctx
|
||||||
|
@ -189,8 +183,7 @@ pub(crate) async fn expert(
|
||||||
.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 {
|
||||||
match is_expert {
|
|
||||||
true => CreateReply::default()
|
true => CreateReply::default()
|
||||||
.content(reply_content)
|
.content(reply_content)
|
||||||
.ephemeral(false)
|
.ephemeral(false)
|
||||||
|
@ -198,13 +191,7 @@ pub(crate) async fn expert(
|
||||||
false => CreateReply::default()
|
false => CreateReply::default()
|
||||||
.content("You do not have any of the required expert ranks.")
|
.content("You do not have any of the required expert ranks.")
|
||||||
.ephemeral(true),
|
.ephemeral(true),
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(why) => {
|
|
||||||
CreateReply::default().content(why.to_string()).ephemeral(true)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(why) = ctx.send(reply).await {
|
if let Err(why) = ctx.send(reply).await {
|
||||||
println!("Error sending message: {why}");
|
println!("Error sending message: {why}");
|
||||||
}
|
}
|
||||||
|
@ -219,8 +206,7 @@ enum OtherPing {
|
||||||
#[poise::command(slash_command, guild_only, rename = "lfg-other")]
|
#[poise::command(slash_command, guild_only, rename = "lfg-other")]
|
||||||
pub(crate) async fn other(
|
pub(crate) async fn other(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[rename = "game"]
|
#[rename = "game"] game: OtherPing,
|
||||||
game: OtherPing,
|
|
||||||
#[min = 1_u8]
|
#[min = 1_u8]
|
||||||
#[max = 3_u8]
|
#[max = 3_u8]
|
||||||
#[description = "default: 1"]
|
#[description = "default: 1"]
|
||||||
|
@ -230,8 +216,7 @@ pub(crate) async fn other(
|
||||||
#[rename = "message"]
|
#[rename = "message"]
|
||||||
note: String,
|
note: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let reply: CreateReply = match cooldown(&ctx, 0, 7200) {
|
cooldown(&ctx, 0, 7200)?;
|
||||||
Ok(_) => {
|
|
||||||
let current: u8 = current_players.unwrap_or(1);
|
let current: u8 = current_players.unwrap_or(1);
|
||||||
let desired: u8 = match game {
|
let desired: u8 = match game {
|
||||||
OtherPing::GeoGuessr => 20_u8,
|
OtherPing::GeoGuessr => 20_u8,
|
||||||
|
@ -241,15 +226,10 @@ pub(crate) async fn other(
|
||||||
};
|
};
|
||||||
let reply_content: String = format!("{current}/{desired} <@&{ping}>: {note}");
|
let reply_content: String = format!("{current}/{desired} <@&{ping}>: {note}");
|
||||||
|
|
||||||
CreateReply::default()
|
let reply: CreateReply = CreateReply::default()
|
||||||
.content(reply_content)
|
.content(reply_content)
|
||||||
.ephemeral(false)
|
.ephemeral(false)
|
||||||
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping]))
|
.allowed_mentions(CreateAllowedMentions::new().roles(vec![ping]));
|
||||||
}
|
|
||||||
Err(why) => {
|
|
||||||
CreateReply::default().content(why.to_string()).ephemeral(true)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(why) = ctx.send(reply).await {
|
if let Err(why) = ctx.send(reply).await {
|
||||||
println!("Error sending message: {why}");
|
println!("Error sending message: {why}");
|
||||||
|
@ -257,15 +237,78 @@ pub(crate) async fn other(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ROLE_LIST: [[u64; 6]; 9] = [
|
||||||
const ROLE_LIST: [[u64; 6]; 9] = [ // [[basic, de, bb, aa, sr, star]; 9]
|
// [[basic, de, bb, aa, sr, star]; 9]
|
||||||
[1256229103678259311, 1256229192744304670, 1256229223450935377, 1256229498899271754, 1256229540900900996, 1256229575269154866], //novice
|
[
|
||||||
[1256230831131983932, 1256230750827577447, 1256230776828334143, 1256230793630715975, 1256230818444214333, 1256230734642024468], //seasoned
|
1256229103678259311,
|
||||||
[1256230723455553556, 1256230653083521045, 1256230666786443310, 1256230686214324255, 1256230704061353995, 1256230636721537097], //expert
|
1256229192744304670,
|
||||||
[1256230625635995718, 1256230573203128370, 1256230582908747776, 1256230600025706506, 1256230610998005872, 1256230557897986068], //pro
|
1256229223450935377,
|
||||||
[1256230543532626002, 1256230480823582861, 1256230502273126421, 1256230515355160597, 1256230531478065243, 1256230463241191494], //master
|
1256229498899271754,
|
||||||
[1256230442907074703, 1256230359419588700, 1256230396719403141, 1256230416516649012, 1256230429212545025, 1256230346848997396], //grandmaster
|
1256229540900900996,
|
||||||
[1256230332169060362, 1256230266889044020, 1256230288888168458, 1256230416516649012, 1256230316528631870, 1256230242943766651], //legend
|
1256229575269154866,
|
||||||
[1256230231732387950, 1256230157967163495, 1256230181199151254, 1256230194499420223, 1256230207099244646, 1256230102627258449], //divine
|
], //novice
|
||||||
[1256230002597302322, 1256229873064869939, 1256229929247440906, 1256229963166646314, 1256229982569627792, 1256229672598110218], //goat
|
[
|
||||||
|
1256230831131983932,
|
||||||
|
1256230750827577447,
|
||||||
|
1256230776828334143,
|
||||||
|
1256230793630715975,
|
||||||
|
1256230818444214333,
|
||||||
|
1256230734642024468,
|
||||||
|
], //seasoned
|
||||||
|
[
|
||||||
|
1256230723455553556,
|
||||||
|
1256230653083521045,
|
||||||
|
1256230666786443310,
|
||||||
|
1256230686214324255,
|
||||||
|
1256230704061353995,
|
||||||
|
1256230636721537097,
|
||||||
|
], //expert
|
||||||
|
[
|
||||||
|
1256230625635995718,
|
||||||
|
1256230573203128370,
|
||||||
|
1256230582908747776,
|
||||||
|
1256230600025706506,
|
||||||
|
1256230610998005872,
|
||||||
|
1256230557897986068,
|
||||||
|
], //pro
|
||||||
|
[
|
||||||
|
1256230543532626002,
|
||||||
|
1256230480823582861,
|
||||||
|
1256230502273126421,
|
||||||
|
1256230515355160597,
|
||||||
|
1256230531478065243,
|
||||||
|
1256230463241191494,
|
||||||
|
], //master
|
||||||
|
[
|
||||||
|
1256230442907074703,
|
||||||
|
1256230359419588700,
|
||||||
|
1256230396719403141,
|
||||||
|
1256230416516649012,
|
||||||
|
1256230429212545025,
|
||||||
|
1256230346848997396,
|
||||||
|
], //grandmaster
|
||||||
|
[
|
||||||
|
1256230332169060362,
|
||||||
|
1256230266889044020,
|
||||||
|
1256230288888168458,
|
||||||
|
1256230416516649012,
|
||||||
|
1256230316528631870,
|
||||||
|
1256230242943766651,
|
||||||
|
], //legend
|
||||||
|
[
|
||||||
|
1256230231732387950,
|
||||||
|
1256230157967163495,
|
||||||
|
1256230181199151254,
|
||||||
|
1256230194499420223,
|
||||||
|
1256230207099244646,
|
||||||
|
1256230102627258449,
|
||||||
|
], //divine
|
||||||
|
[
|
||||||
|
1256230002597302322,
|
||||||
|
1256229873064869939,
|
||||||
|
1256229929247440906,
|
||||||
|
1256229963166646314,
|
||||||
|
1256229982569627792,
|
||||||
|
1256229672598110218,
|
||||||
|
], //goat
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
pub(crate) mod accountv2;
|
||||||
pub(crate) mod bots;
|
pub(crate) mod bots;
|
||||||
pub(crate) mod command_helper;
|
pub(crate) mod command_helper;
|
||||||
pub(crate) mod helpstart;
|
pub(crate) mod helpstart;
|
||||||
pub(crate) mod lfg;
|
pub(crate) mod lfg;
|
||||||
pub(crate) mod xd;
|
pub(crate) mod xd;
|
||||||
pub(crate) mod accountv2;
|
|
|
@ -1,7 +1,14 @@
|
||||||
use crate::Context;
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
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";
|
||||||
|
|
||||||
#[poise::command(slash_command)]
|
#[poise::command(slash_command)]
|
||||||
pub(crate) async fn xd(ctx: Context<'_>) -> Result<(), Error> {
|
pub(crate) async fn xd(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
|
|
@ -5,7 +5,7 @@ pub enum Error {
|
||||||
ParsingError(serde_json::Error),
|
ParsingError(serde_json::Error),
|
||||||
SerenityError(serenity::Error),
|
SerenityError(serenity::Error),
|
||||||
OnCooldown(std::time::Duration),
|
OnCooldown(std::time::Duration),
|
||||||
Other(String)
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Error {
|
impl std::fmt::Display for Error {
|
||||||
|
@ -15,7 +15,9 @@ impl std::fmt::Display for Error {
|
||||||
Error::HttpsError(e) => write!(f, "HTTPS Error (Hypixel / Mojang API):\n{}", e),
|
Error::HttpsError(e) => write!(f, "HTTPS Error (Hypixel / Mojang API):\n{}", e),
|
||||||
Error::ParsingError(e) => write!(f, "Parsing Error:\n {}", e),
|
Error::ParsingError(e) => write!(f, "Parsing Error:\n {}", e),
|
||||||
Error::SerenityError(e) => write!(f, "Serenity 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::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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,93 @@
|
||||||
use serenity::all::{ComponentInteraction, ComponentInteractionDataKind, Context, CreateMessage, EditMessage, GuildId, Interaction, RoleId};
|
use serenity::all::ButtonStyle::Success;
|
||||||
|
use serenity::all::ComponentInteractionDataKind;
|
||||||
|
use serenity::all::Context;
|
||||||
|
use serenity::all::CreateActionRow;
|
||||||
|
use serenity::all::CreateButton;
|
||||||
|
use serenity::all::CreateInteractionResponse::Message;
|
||||||
|
use serenity::all::CreateInteractionResponseMessage;
|
||||||
|
use serenity::all::CreateMessage;
|
||||||
|
use serenity::all::EditMessage;
|
||||||
|
use serenity::all::GuildId;
|
||||||
|
use serenity::all::Interaction;
|
||||||
|
use serenity::all::ReactionType;
|
||||||
|
use serenity::all::RoleId;
|
||||||
|
use serenity::all::{ButtonStyle, ComponentInteraction};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
use crate::Data;
|
||||||
|
|
||||||
pub(crate) async fn component(ctx: &Context, interaction: &Interaction) -> Result<(), Error> {
|
pub(crate) async fn component(ctx: &Context, interaction: &Interaction, data: &Data) -> Result<(), Error> {
|
||||||
let component = interaction.clone().message_component().unwrap();
|
let component = interaction.clone().message_component().unwrap();
|
||||||
match component.data.kind {
|
match component.data.kind {
|
||||||
ComponentInteractionDataKind::Button => button(ctx, component).await,
|
ComponentInteractionDataKind::Button => button(ctx, component, data).await,
|
||||||
_ => Ok(())
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn button(ctx: &Context, mut component: ComponentInteraction) -> Result<(), Error> {
|
async fn button(ctx: &Context, mut interaction: ComponentInteraction, data: &Data) -> Result<(), Error> {
|
||||||
let m = component.message.clone();
|
let m = &interaction.message;
|
||||||
let u = m.mentions.first().expect("Message did not mention a user.");
|
let u = m.mentions.first().expect("Message did not mention a user.");
|
||||||
match component.data.custom_id.as_str() {
|
match interaction.data.custom_id.as_str() {
|
||||||
"accept_verification" => {
|
"accept_verification" => {
|
||||||
let _dm = u.direct_message(ctx, CreateMessage::new()
|
let _dm = u
|
||||||
.content("Your verified minecraft account was approved.")).await?;
|
.direct_message(ctx, CreateMessage::new().content("Your verified minecraft account was approved."))
|
||||||
let member = m.guild_id.unwrap_or(GuildId::new(1256217633959841853_u64)).member(ctx, u.id).await?;
|
.await?;
|
||||||
|
let member = m
|
||||||
|
.guild_id
|
||||||
|
.unwrap_or(GuildId::new(1256217633959841853_u64))
|
||||||
|
.member(ctx, u.id)
|
||||||
|
.await?;
|
||||||
member.add_role(ctx, RoleId::new(1256218805911425066_u64)).await?;
|
member.add_role(ctx, RoleId::new(1256218805911425066_u64)).await?;
|
||||||
member.remove_role(ctx, RoleId::new(1256253358701023232_u64)).await?;
|
member.remove_role(ctx, RoleId::new(1256253358701023232_u64)).await?;
|
||||||
component.message.edit(ctx, EditMessage::new().components(vec![])).await?;
|
interaction
|
||||||
|
.message
|
||||||
|
.edit(
|
||||||
|
ctx,
|
||||||
|
EditMessage::new().components(vec![CreateActionRow::Buttons(vec![
|
||||||
|
CreateButton::new("accept_verification")
|
||||||
|
.emoji(ReactionType::from('✅'))
|
||||||
|
.style(Success)
|
||||||
|
.disabled(true),
|
||||||
|
CreateButton::new("deny_verification")
|
||||||
|
.emoji(ReactionType::from('❌'))
|
||||||
|
.disabled(true),
|
||||||
|
CreateButton::new("list_accounts").emoji(ReactionType::from('📜')),
|
||||||
|
])]),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
"deny_verification" => {
|
"deny_verification" => {
|
||||||
let _dm = u.direct_message(ctx, CreateMessage::new()
|
let _dm = u
|
||||||
.content("Your verified minecraft account was denied.")).await?;
|
.direct_message(ctx, CreateMessage::new().content("Your verified minecraft account was denied."))
|
||||||
component.message.edit(ctx, EditMessage::new().components(vec![])).await?;
|
.await?;
|
||||||
|
interaction
|
||||||
|
.message
|
||||||
|
.edit(
|
||||||
|
ctx,
|
||||||
|
EditMessage::new().components(vec![CreateActionRow::Buttons(vec![
|
||||||
|
CreateButton::new("accept_verification")
|
||||||
|
.emoji(ReactionType::from('✅'))
|
||||||
|
.disabled(true),
|
||||||
|
CreateButton::new("deny_verification")
|
||||||
|
.emoji(ReactionType::from('❌'))
|
||||||
|
.style(ButtonStyle::Danger)
|
||||||
|
.disabled(true),
|
||||||
|
CreateButton::new("list_accounts").emoji(ReactionType::from('📜')),
|
||||||
|
])]),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Ok(())
|
"list_accounts" => {
|
||||||
|
let user = interaction.message.mentions.first().unwrap();
|
||||||
|
let s: String = crate::commands::accountv2::list_string(&data.sqlite_pool, user).await?;
|
||||||
|
interaction
|
||||||
|
.create_response(ctx, Message(CreateInteractionResponseMessage::new().content(s).ephemeral(true)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,10 +5,8 @@ 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()) {
|
||||||
None => Ok(()),
|
None => Ok(()),
|
||||||
Some(1256217633959841853_u64) => {
|
Some(1256217633959841853_u64) => zmp_create(ctx, msg).await,
|
||||||
zmp_create(ctx, msg).await
|
_ => Ok(()),
|
||||||
}
|
|
||||||
_ => Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +17,6 @@ async fn zmp_create(ctx: &Context, msg: &Message) -> Result<(), Error> {
|
||||||
msg.react(ctx, '🇱').await?;
|
msg.react(ctx, '🇱').await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Ok(())
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ 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()) {
|
||||||
Some(1295108216388325386) => {
|
Some(1295108216388325386) => {
|
||||||
thread.id.edit_thread(ctx, EditThread::new().rate_limit_per_user(7200_u16)).await?;
|
thread.id.edit_thread(ctx, EditThread::new().rate_limit_per_user(60_u16)).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(_) => Ok(()),
|
Some(_) => Ok(()),
|
||||||
None => Ok(())
|
None => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
43
src/main.rs
43
src/main.rs
|
@ -5,17 +5,18 @@ use std::convert::Into;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use poise::{CreateReply, FrameworkError, serenity_prelude as serenity};
|
use poise::{serenity_prelude as serenity, CreateReply, FrameworkError};
|
||||||
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 serenity::{model::id::UserId, FullEvent};
|
||||||
use sqlx::Sqlite;
|
use sqlx::Sqlite;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod handlers;
|
|
||||||
mod error;
|
mod error;
|
||||||
|
mod handlers;
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
bots: Arc<RwLock<u8>>,
|
bots: Arc<RwLock<u8>>,
|
||||||
|
@ -23,7 +24,6 @@ struct Data {
|
||||||
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 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() {
|
||||||
|
@ -35,14 +35,8 @@ async fn main() {
|
||||||
let hypixel_api: String = std::env::var("HYPIXEL_API_KEY").unwrap();
|
let hypixel_api: String = std::env::var("HYPIXEL_API_KEY").unwrap();
|
||||||
let hypixel_api_client = {
|
let hypixel_api_client = {
|
||||||
let mut headers = reqwest::header::HeaderMap::new();
|
let mut headers = reqwest::header::HeaderMap::new();
|
||||||
headers.insert(
|
headers.insert("API-Key", reqwest::header::HeaderValue::try_from(hypixel_api).unwrap());
|
||||||
"API-Key",
|
reqwest::ClientBuilder::new().default_headers(headers).build().unwrap()
|
||||||
reqwest::header::HeaderValue::try_from(hypixel_api).unwrap(),
|
|
||||||
);
|
|
||||||
reqwest::ClientBuilder::new()
|
|
||||||
.default_headers(headers)
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let options = poise::FrameworkOptions {
|
let options = poise::FrameworkOptions {
|
||||||
|
@ -64,9 +58,14 @@ async fn main() {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
match error {
|
match error {
|
||||||
FrameworkError::CommandStructureMismatch { description, ctx, .. } => {
|
FrameworkError::CommandStructureMismatch { description, ctx, .. } => {
|
||||||
if let Err(e) = ctx.send(CreateReply::default()
|
if let Err(e) = ctx
|
||||||
.content(format!("# Command arguments did not match. The command probably has been updated recently. Try reloading Discord. Description:\n{}", description)))
|
.send(CreateReply::default().content(format!(
|
||||||
.await {
|
"# 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);
|
tracing::error!("Fatal error while sending error message: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,9 +78,7 @@ async fn main() {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
owners: { HashSet::from([UserId::new(449579075531440128_u64), UserId::new(659112817508745216_u64)]) },
|
owners: { HashSet::from([UserId::new(449579075531440128_u64), UserId::new(659112817508745216_u64)]) },
|
||||||
event_handler: |_ctx, event, _framework, _data| {
|
event_handler: |ctx, event, framework, data| Box::pin(event_handler(ctx, event, framework, data)),
|
||||||
Box::pin(event_handler(_ctx, event, _framework, _data))
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,8 +97,7 @@ async fn main() {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let token = std::env::var("DISCORD_TOKEN").unwrap();
|
let token = std::env::var("DISCORD_TOKEN").unwrap();
|
||||||
let intents =
|
let intents = GatewayIntents::non_privileged() | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
||||||
GatewayIntents::non_privileged() | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
|
||||||
let client = serenity::ClientBuilder::new(token, intents)
|
let client = serenity::ClientBuilder::new(token, intents)
|
||||||
.framework(framework)
|
.framework(framework)
|
||||||
.activity(ActivityData::custom("NPC moment..."))
|
.activity(ActivityData::custom("NPC moment..."))
|
||||||
|
@ -112,7 +108,7 @@ async fn event_handler(
|
||||||
ctx: &serenity::Context,
|
ctx: &serenity::Context,
|
||||||
event: &FullEvent,
|
event: &FullEvent,
|
||||||
_framework: poise::FrameworkContext<'_, Data, Error>,
|
_framework: poise::FrameworkContext<'_, Data, Error>,
|
||||||
_data: &Data,
|
data: &Data,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match event {
|
match event {
|
||||||
FullEvent::Ready { data_about_bot, .. } => {
|
FullEvent::Ready { data_about_bot, .. } => {
|
||||||
|
@ -126,9 +122,8 @@ async fn event_handler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FullEvent::InteractionCreate { interaction } => {
|
FullEvent::InteractionCreate { interaction } => {
|
||||||
if interaction.application_id().get() == 1165594074473037824
|
if interaction.application_id().get() == 1165594074473037824 && interaction.kind() == InteractionType::Component {
|
||||||
&& interaction.kind() == InteractionType::Component {
|
handlers::bot_interaction::component(ctx, interaction, data).await?;
|
||||||
handlers::bot_interaction::component(ctx, interaction).await?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FullEvent::Message { new_message } => {
|
FullEvent::Message { new_message } => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue