use serde::{Deserialize, Serialize}; use serde::de::DeserializeOwned; use sqlx::{Error, FromRow, Pool, Row, Sqlite}; use serenity::model::id::GuildId; use sqlx::sqlite::SqliteRow; use crate::Config; use crate::set_roles::get_server_member_bulk; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Minecraft { pub discord: GuildId, pub minecraft: String, } impl<'r> FromRow<'r, SqliteRow> for Minecraft { fn from_row(row: &'r SqliteRow) -> Result { let server_tmp: i64 = row.try_get("server_discord")?; let discord = GuildId::from(server_tmp as u64); Ok(Self { discord, minecraft: row.try_get("server_minecraft")?, }) } } /** loop through all members of server get a list of folks with mc accounts that are members and a list that arent members */ pub async fn update_server(server_id: &str, db: &Pool, g_id: &GuildId, config: &Config) { let mut usernames = vec![]; for member in get_server_member_bulk(db, g_id).await { if let Some(x) = member.minecraft { usernames.push(x); } } if !usernames.is_empty() { whitelist_update(&usernames, server_id, &config.discord_token_minecraft).await; } } async fn post(url: &str, bearer: &str, data: &T) { match surf::post(url) .header("Authorization", bearer) .header("Content-Type", "application/json") .header("Accept", "Application/vnd.pterodactyl.v1+json") .body_json(&data) { Ok(req) => { req.await.ok(); } Err(e) => { dbg!(e); } } } #[derive(Deserialize, Serialize, Debug)] pub struct ServerDetailsResSub { pub identifier: String, pub name: String, pub description: String, pub is_suspended: bool, } #[derive(Deserialize, Serialize, Debug)] pub struct ServerDetailsRes { pub attributes: ServerDetailsResSub, } async fn get(url: &str, bearer: &str) -> Option { match surf::get(url) .header("Authorization", bearer) .header("Content-Type", "application/json") .header("Accept", "Application/vnd.pterodactyl.v1+json") .recv_json() .await { Ok(res) => Some(res), Err(e) => { dbg!(e); None } } } #[derive(Deserialize, Serialize, Debug)] struct BodyCommand { command: String, } #[derive(Deserialize, Serialize, Debug)] struct BodyDelete { root: String, files: Vec, } pub async fn whitelist_update(add: &Vec, server: &str, token: &str) { let url_base = format!("http://panel.games.skynet.ie/api/client/servers/{server}"); let bearer = format!("Bearer {token}"); for name in add { let data = BodyCommand { command: format!("whitelist add {name}"), }; post(&format!("{url_base}/command"), &bearer, &data).await; } } pub async fn whitelist_wipe(server: &str, token: &str) { let url_base = format!("http://panel.games.skynet.ie/api/client/servers/{server}"); let bearer = format!("Bearer {token}"); // delete whitelist let deletion = BodyDelete { root: "/".to_string(), files: vec!["whitelist.json".to_string()], }; post(&format!("{url_base}/files/delete"), &bearer, &deletion).await; // recreate teh file, passing in the type here so the compiler knows what type of vec it is post::>(&format!("{url_base}/files/write?file=%2Fwhitelist.json"), &bearer, &vec![]).await; // reload the whitelist let data = BodyCommand { command: "whitelist reload".to_string(), }; post(&format!("{url_base}/command"), &bearer, &data).await; } pub async fn server_information(server: &str, token: &str) -> Option { let url_base = format!("http://panel.games.skynet.ie/api/client/servers/{server}"); let bearer = format!("Bearer {token}"); get::(&format!("{url_base}/"), &bearer).await } pub async fn get_minecraft_config(db: &Pool) -> Vec { sqlx::query_as::<_, Minecraft>( r#" SELECT * FROM minecraft "#, ) .fetch_all(db) .await .unwrap_or_default() } pub async fn get_minecraft_config_server(db: &Pool, g_id: GuildId) -> Vec { sqlx::query_as::<_, Minecraft>( r#" SELECT * FROM minecraft WHERE server_discord = ?1 "#, ) .bind(*g_id.as_u64() as i64) .fetch_all(db) .await .unwrap_or_default() }