make things into types

This commit is contained in:
August 2024-10-21 22:50:52 -04:00
parent 00f8253ee1
commit b04157e4ae
Signed by: shibedrill
GPG Key ID: 5FE0CB25945EFAA2
5 changed files with 164 additions and 115 deletions

View File

@ -6,7 +6,11 @@ pub fn set_presence(ctx: &poise::serenity_prelude::Context, status: ServerRespon
ctx.set_presence(
Some(ActivityData::custom(match status.online() {
true => {
format!("{}/{} players online", status.players(), status.max())
format!(
"{}/{} players online",
status.players().unwrap(),
status.max().unwrap()
)
}
false => "Server offline!".to_string(),
})),
@ -18,4 +22,4 @@ pub fn set_presence(ctx: &poise::serenity_prelude::Context, status: ServerRespon
false => OnlineStatus::DoNotDisturb,
},
);
}
}

View File

@ -1,9 +1,12 @@
mod funcs;
mod minecraft;
mod scpsl;
mod types;
mod funcs;
use tokio::join;
use dotenvy::{self, dotenv};
use minecraft::Minecraft;
use scpsl::SCPSL;
use tokio::join;
use url::{self, Url};
#[macro_use]
extern crate log;
@ -12,5 +15,17 @@ extern crate log;
async fn main() {
dotenv().ok();
pretty_env_logger::init();
join!(scpsl::run(), minecraft::run());
let gamerzone = Minecraft::new(
Url::try_from("https://api.mcstatus.io/v2/status/java/gamer.shibedrill.site").unwrap(),
std::env::var("TOKEN_BOT_MC_GAMER").unwrap(),
);
let mchprs = Minecraft::new(
Url::try_from("https://api.mcstatus.io/v2/status/java/mchprs.shibedrill.site").unwrap(),
std::env::var("TOKEN_BOT_MC_MCHPRS").unwrap(),
);
let scpsl = SCPSL::new(
Url::try_from("https://api.scplist.kr/api/servers/81460").unwrap(),
std::env::var("TOKEN_BOT_SCPSL").unwrap(),
);
join!(scpsl.run(), mchprs.run(), gamerzone.run());
}

View File

@ -1,6 +1,7 @@
use poise::serenity_prelude as serenity;
use reqwest::{Client, Request};
use serenity::*;
use url::Url;
use crate::{funcs, types::ServerResponse};
@ -16,25 +17,66 @@ struct Players {
max: i32,
}
pub struct Data {}
pub struct Data {
controller: Minecraft,
}
async fn get_status() -> Result<ServerResponse, anyhow::Error> {
let http_client = Client::new();
let request = Request::new(
reqwest::Method::GET,
"https://api.mcstatus.io/v2/status/java/gamer.shibedrill.site"
.try_into()?,
);
let response = http_client.execute(request).await?;
let data: ServerSummary = serde_json::from_str(&response.text().await?)?;
if let Some(players) = data.players {
Ok(ServerResponse::new(
data.online,
players.online as u32,
players.max as u32,
))
} else {
Ok(ServerResponse::new(data.online, 0, 0))
#[derive(Clone)]
pub struct Minecraft {
url: Url,
token: String,
}
impl Minecraft {
pub fn new(url: Url, token: String) -> Self {
Self { url, token }
}
pub 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?)?;
if let Some(players) = data.players {
Ok(ServerResponse::new(
data.online,
Some(players.online as u32),
Some(players.max as u32),
))
} else {
Ok(ServerResponse::new(data.online, None, None))
}
}
pub async fn run(&self) {
let controller = self.clone();
let framework = poise::Framework::builder()
.options(poise::FrameworkOptions {
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;
}
}
@ -42,13 +84,15 @@ pub async fn event_handler(
ctx: &serenity::Context,
event: &serenity::FullEvent,
_framework: poise::FrameworkContext<'_, Data, Error>,
_data: &Data,
data: &Data,
) -> Result<(), Error> {
match event {
serenity::FullEvent::Ready {
data_about_bot: _data,
data_about_bot: _bot_data,
} => loop {
let status = get_status()
let status = data
.controller
.get_status()
.await
.inspect_err(|e| error!("Failed to get status: {}", e))
.unwrap();
@ -60,34 +104,3 @@ pub async fn event_handler(
_ => Ok(()),
}
}
pub async fn run() {
let framework = poise::Framework::builder()
.options(poise::FrameworkOptions {
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 {})
})
})
.build();
info!("Built framework successfully.");
let mut discord_client = ClientBuilder::new(
std::env::var("MINECRAFT_BOT_TOKEN").inspect_err(|e| {error!("Failed to get token: {}", e)}).unwrap(),
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;
}

View File

@ -1,8 +1,8 @@
use crate::{funcs, types::ServerResponse};
use poise::serenity_prelude as serenity;
use reqwest::{Client, Request};
use serenity::*;
use url::Url;
#[derive(serde::Deserialize)]
#[allow(non_snake_case)]
@ -11,40 +11,85 @@ struct ServerSummary {
players: String,
}
pub struct Data {}
pub struct Data {
controller: SCPSL,
}
async fn get_status() -> Result<ServerResponse, anyhow::Error> {
let http_client = Client::new();
let request = Request::new(
reqwest::Method::GET,
url::Url::try_from("https://api.scplist.kr/api/servers/81460")?,
);
let response = http_client.execute(request).await?;
let data: ServerSummary = serde_json::from_str(&response.text().await?)?;
#[derive(Clone)]
pub struct SCPSL {
url: Url,
token: String,
}
let playercount: Result<Vec<u32>, _> =
data.players.split('/').map(|x| x.parse::<u32>()).collect();
impl SCPSL {
pub fn new(url: Url, token: String) -> Self {
Self { url, token }
}
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?)?;
let playercount_unwrapped = playercount?;
let playercount: Result<Vec<u32>, _> =
data.players.split('/').map(|x| x.parse::<u32>()).collect();
Ok(ServerResponse::new(
data.online,
playercount_unwrapped[0],
playercount_unwrapped[1],
))
let playercount_unwrapped = playercount?;
Ok(ServerResponse::new(
data.online,
playercount_unwrapped.get(0).map(|u| u.clone()),
playercount_unwrapped.get(1).map(|u| u.clone()),
))
}
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,
data: &Data,
) -> Result<(), Error> {
match event {
serenity::FullEvent::Ready {
data_about_bot: _data,
} => loop {
let status = get_status()
let status = data
.controller
.get_status()
.await
.inspect_err(|e| error!("Failed to get status: {}", e))
.unwrap();
@ -56,35 +101,3 @@ pub async fn event_handler(
_ => Ok(()),
}
}
pub async fn run() {
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 {})
})
})
.build();
info!("Built framework successfully.");
let mut discord_client = ClientBuilder::new(
std::env::var("SCPSL_BOT_TOKEN").inspect_err(|e| {error!("Failed to get token: {}", e)}).unwrap(),
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;
}

View File

@ -1,11 +1,11 @@
pub struct ServerResponse {
online: bool,
players: u32,
max: u32,
players: Option<u32>,
max: Option<u32>,
}
impl ServerResponse {
pub fn new(online: bool, players: u32, max: u32) -> Self {
pub fn new(online: bool, players: Option<u32>, max: Option<u32>) -> Self {
ServerResponse {
online,
players,
@ -17,11 +17,11 @@ impl ServerResponse {
self.online
}
pub fn players(&self) -> u32 {
pub fn players(&self) -> Option<u32> {
self.players
}
pub fn max(&self) -> u32 {
pub fn max(&self) -> Option<u32> {
self.max
}
@ -30,6 +30,10 @@ impl ServerResponse {
}
pub fn to_string(&self) -> String {
format!("{}/{} ({})", self.players, self.max, self.online)
if let (Some(players), Some(max)) = (self.players, self.max) {
format!("{}/{} ({})", players, max, self.online)
} else {
format!("N/A ({})", self.online)
}
}
}