111 lines
3.3 KiB
Rust
111 lines
3.3 KiB
Rust
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<ServerResponse, anyhow::Error> {
|
|
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<Vec<u32>, _> =
|
|
data.players.split('/').map(|x| x.parse::<u32>()).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(()),
|
|
}
|
|
}
|