diff --git a/src/commands/add_minecraft.rs b/src/commands/add_minecraft.rs index a987a0a..11d09a3 100644 --- a/src/commands/add_minecraft.rs +++ b/src/commands/add_minecraft.rs @@ -10,7 +10,111 @@ use serenity::{ use skynet_discord_bot::{get_server_config, DataBase, Servers}; use sqlx::{Pool, Sqlite}; -pub(crate) mod user {} +pub(crate) mod user { + use super::*; + use crate::commands::add_minecraft::server::update_whitelist; + use crate::commands::link_email::link::get_server_member_discord; + use serenity::model::id::UserId; + use skynet_discord_bot::{Config, Wolves}; + use sqlx::Error; + + pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { + command.name("link_minecraft").description("Link your minecraft account").create_option(|option| { + option + .name("minecraft_id") + .description("Your Minecraft username") + .kind(CommandOptionType::String) + .required(true) + }) + } + + pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String { + let db_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Databse in TypeMap.").clone() + }; + let db = db_lock.read().await; + + let config_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + let config = config_lock.read().await; + + // user has to have previously linked with wolves + if get_server_member_discord(&db, &command.user.id).await.is_none() { + return "Not linked with wolves, please use ``/link_wolves`` with your wolves email.".to_string(); + } + + let username = if let CommandDataOptionValue::String(username) = command + .data + .options + .get(0) + .expect("Expected username option") + .resolved + .as_ref() + .expect("Expected username object") + { + username.trim() + } else { + return "Please provide a valid username".to_string(); + }; + + // insert the username into the database + match add_minecraft(&db, &command.user.id, username).await { + Ok(_) => {} + Err(e) => { + dbg!("{:?}", e); + return format!("Failure to minecraft username {:?}", username); + } + } + + // get a list of servers that the user is a member of + if let Ok(servers) = get_servers(&db, &command.user.id).await { + for server in servers { + if let Some(server_minecraft) = server.server_minecraft { + // activate the user on all linked servers + update_whitelist(&vec![username.to_string()], &server_minecraft, &config.discord_minecraft, false).await; + } + } + } + + "Added/Updated minecraft_user info".to_string() + } + + async fn add_minecraft(db: &Pool, user: &UserId, minecraft: &str) -> Result, Error> { + sqlx::query_as::<_, Wolves>( + " + UPDATE wolves + SET minecraft = ?2 + WHERE discord = ?1; + ", + ) + .bind(*user.as_u64() as i64) + .bind(minecraft) + .fetch_optional(db) + .await + } + + async fn get_servers(db: &Pool, discord: &UserId) -> Result, Error> { + sqlx::query_as::<_, Servers>( + " + SELECT servers.* + FROM servers + JOIN ( + SELECT server + FROM server_members + JOIN wolves USING (id_wolves) + WHERE discord = ?1 + ) USING (server) + WHERE server_minecraft IS NOT NULL + ", + ) + .bind(*discord.as_u64() as i64) + .fetch_all(db) + .await + } +} pub(crate) mod server { use serde::{Deserialize, Serialize}; @@ -121,12 +225,12 @@ pub(crate) mod server { } } if !usernames.is_empty() { - update_whitelist(&usernames, &server_id, &config.discord_minecraft).await; + update_whitelist(&usernames, &server_id, &config.discord_minecraft, true).await; } } } - pub async fn update_whitelist(add: &Vec, server: &str, token: &str) { + pub async fn update_whitelist(add: &Vec, server: &str, token: &str, wipe_reset: bool) { let url_base = format!("http://panel.games.skynet.ie/api/client/servers/{server}"); let bearer = format!("Bearer {token}"); @@ -157,18 +261,20 @@ pub(crate) mod server { files: Vec, } - // delete whitelist - let deletion = BodyDelete { - root: "/".to_string(), - files: vec!["whitelist.json".to_string()], - }; - post(&format!("{url_base}/files/delete"), &bearer, &deletion).await; + if wipe_reset { + // delete whitelist + let deletion = BodyDelete { + root: "/".to_string(), + files: vec!["whitelist.json".to_string()], + }; + post(&format!("{url_base}/files/delete"), &bearer, &deletion).await; - // reload the whitelist - let data = BodyCommand { - command: "whitelist reload".to_string(), - }; - post(&format!("{url_base}/command"), &bearer, &data).await; + // reload the whitelist + let data = BodyCommand { + command: "whitelist reload".to_string(), + }; + post(&format!("{url_base}/command"), &bearer, &data).await; + } for name in add { let data = BodyCommand { diff --git a/src/commands/link_email.rs b/src/commands/link_email.rs index 700e853..bb065ab 100644 --- a/src/commands/link_email.rs +++ b/src/commands/link_email.rs @@ -92,7 +92,7 @@ pub(crate) mod link { .create_option(|option| option.name("email").description("UL Wolves Email").kind(CommandOptionType::String).required(true)) } - async fn get_server_member_discord(db: &Pool, user: &UserId) -> Option { + pub async fn get_server_member_discord(db: &Pool, user: &UserId) -> Option { sqlx::query_as::<_, Wolves>( r#" SELECT *