use crate::{funcs, types::ServerResponse}; use poise::serenity_prelude as serenity; use reqwest::{Client, Request}; use serenity::*; use url::Url; #[derive(serde::Deserialize, Debug)] #[allow(non_snake_case)] struct ServerSummary { online: bool, players: String, } pub struct Data { controller: Scpsl, } #[derive(Clone)] pub struct Scpsl { name: String, url: Url, token: String, } impl Scpsl { pub fn new(url: Url, token: String, name: String) -> Self { Self { url, token, name } } async fn get_status(&self) -> Result { let http_client = Client::new(); let request = Request::new(reqwest::Method::GET, self.url.clone()); let response = http_client.execute(request).await?; let data: ServerSummary = serde_json::from_str(&response.text().await?)?; trace!("Response JSON for {}: {:#?}", self.name, data); // this is the only thing I added. let playercount: Result, _> = data.players.split('/').map(|x| x.parse::()).collect(); let playercount_unwrapped = playercount?; Ok(ServerResponse::new( data.online, playercount_unwrapped.first().copied(), playercount_unwrapped.get(1).copied(), )) } pub async fn run(&self) { let controller = self.clone(); let framework = poise::Framework::builder() .options(poise::FrameworkOptions { initialize_owners: true, event_handler: |ctx, event, framework, data| { Box::pin(event_handler(ctx, event, framework, data)) }, ..Default::default() }) .setup(|ctx, _ready, framework| { Box::pin(async move { poise::builtins::register_globally(ctx, &framework.options().commands).await?; Ok(Data { controller }) }) }) .build(); info!("Built framework successfully."); let mut discord_client = ClientBuilder::new( self.token.clone(), serenity::GatewayIntents::non_privileged(), ) .framework(framework) .activity(ActivityData::custom("Waiting on initial status...")) .await .inspect_err(|e| error!("Failed to start client: {}", e)) .unwrap(); info!("Built client successfully."); let _ = discord_client.start().await; } } pub async fn event_handler( ctx: &serenity::Context, event: &serenity::FullEvent, _framework: poise::FrameworkContext<'_, Data, Error>, data: &Data, ) -> Result<(), Error> { match event { serenity::FullEvent::Ready { data_about_bot: _data, } => loop { let status = data .controller .get_status() .await .inspect_err(|e| error!("{}: Failed to get status: {}", data.controller.name, e)) .unwrap(); info!( "{}: Got status: {}", data.controller.name, status.to_string() ); funcs::set_presence(ctx, status); tokio::time::sleep(std::time::Duration::from_secs(30)).await; }, _ => Ok(()), } }