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

View File

@ -1,9 +1,12 @@
mod funcs;
mod minecraft; mod minecraft;
mod scpsl; mod scpsl;
mod types; mod types;
mod funcs;
use tokio::join;
use dotenvy::{self, dotenv}; use dotenvy::{self, dotenv};
use minecraft::Minecraft;
use scpsl::SCPSL;
use tokio::join;
use url::{self, Url};
#[macro_use] #[macro_use]
extern crate log; extern crate log;
@ -12,5 +15,17 @@ extern crate log;
async fn main() { async fn main() {
dotenv().ok(); dotenv().ok();
pretty_env_logger::init(); 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 poise::serenity_prelude as serenity;
use reqwest::{Client, Request}; use reqwest::{Client, Request};
use serenity::*; use serenity::*;
use url::Url;
use crate::{funcs, types::ServerResponse}; use crate::{funcs, types::ServerResponse};
@ -16,25 +17,66 @@ struct Players {
max: i32, max: i32,
} }
pub struct Data {} pub struct Data {
controller: Minecraft,
}
async fn get_status() -> Result<ServerResponse, anyhow::Error> { #[derive(Clone)]
let http_client = Client::new(); pub struct Minecraft {
let request = Request::new( url: Url,
reqwest::Method::GET, token: String,
"https://api.mcstatus.io/v2/status/java/gamer.shibedrill.site" }
.try_into()?,
); impl Minecraft {
let response = http_client.execute(request).await?; pub fn new(url: Url, token: String) -> Self {
let data: ServerSummary = serde_json::from_str(&response.text().await?)?; Self { url, token }
if let Some(players) = data.players { }
Ok(ServerResponse::new(
data.online, pub async fn get_status(&self) -> Result<ServerResponse, anyhow::Error> {
players.online as u32, let http_client = Client::new();
players.max as u32, let request = Request::new(reqwest::Method::GET, self.url.clone());
)) let response = http_client.execute(request).await?;
} else { let data: ServerSummary = serde_json::from_str(&response.text().await?)?;
Ok(ServerResponse::new(data.online, 0, 0)) 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, ctx: &serenity::Context,
event: &serenity::FullEvent, event: &serenity::FullEvent,
_framework: poise::FrameworkContext<'_, Data, Error>, _framework: poise::FrameworkContext<'_, Data, Error>,
_data: &Data, data: &Data,
) -> Result<(), Error> { ) -> Result<(), Error> {
match event { match event {
serenity::FullEvent::Ready { serenity::FullEvent::Ready {
data_about_bot: _data, data_about_bot: _bot_data,
} => loop { } => loop {
let status = get_status() let status = data
.controller
.get_status()
.await .await
.inspect_err(|e| error!("Failed to get status: {}", e)) .inspect_err(|e| error!("Failed to get status: {}", e))
.unwrap(); .unwrap();
@ -60,34 +104,3 @@ pub async fn event_handler(
_ => Ok(()), _ => 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 crate::{funcs, types::ServerResponse};
use poise::serenity_prelude as serenity; use poise::serenity_prelude as serenity;
use reqwest::{Client, Request}; use reqwest::{Client, Request};
use serenity::*; use serenity::*;
use url::Url;
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -11,40 +11,85 @@ struct ServerSummary {
players: String, players: String,
} }
pub struct Data {} pub struct Data {
controller: SCPSL,
}
async fn get_status() -> Result<ServerResponse, anyhow::Error> { #[derive(Clone)]
let http_client = Client::new(); pub struct SCPSL {
let request = Request::new( url: Url,
reqwest::Method::GET, token: String,
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?)?;
let playercount: Result<Vec<u32>, _> = impl SCPSL {
data.players.split('/').map(|x| x.parse::<u32>()).collect(); 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( let playercount_unwrapped = playercount?;
data.online,
playercount_unwrapped[0], Ok(ServerResponse::new(
playercount_unwrapped[1], 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( pub async fn event_handler(
ctx: &serenity::Context, ctx: &serenity::Context,
event: &serenity::FullEvent, event: &serenity::FullEvent,
_framework: poise::FrameworkContext<'_, Data, Error>, _framework: poise::FrameworkContext<'_, Data, Error>,
_data: &Data, data: &Data,
) -> Result<(), Error> { ) -> Result<(), Error> {
match event { match event {
serenity::FullEvent::Ready { serenity::FullEvent::Ready {
data_about_bot: _data, data_about_bot: _data,
} => loop { } => loop {
let status = get_status() let status = data
.controller
.get_status()
.await .await
.inspect_err(|e| error!("Failed to get status: {}", e)) .inspect_err(|e| error!("Failed to get status: {}", e))
.unwrap(); .unwrap();
@ -56,35 +101,3 @@ pub async fn event_handler(
_ => Ok(()), _ => 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 { pub struct ServerResponse {
online: bool, online: bool,
players: u32, players: Option<u32>,
max: u32, max: Option<u32>,
} }
impl ServerResponse { 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 { ServerResponse {
online, online,
players, players,
@ -17,11 +17,11 @@ impl ServerResponse {
self.online self.online
} }
pub fn players(&self) -> u32 { pub fn players(&self) -> Option<u32> {
self.players self.players
} }
pub fn max(&self) -> u32 { pub fn max(&self) -> Option<u32> {
self.max self.max
} }
@ -30,6 +30,10 @@ impl ServerResponse {
} }
pub fn to_string(&self) -> String { 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)
}
} }
} }