Compare commits

...

11 Commits

8 changed files with 485 additions and 173 deletions

320
Cargo.lock generated
View File

@ -43,9 +43,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.90" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
@ -355,6 +355,17 @@ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]] [[package]]
name = "dotenvy" name = "dotenvy"
version = "0.15.7" version = "0.15.7"
@ -842,6 +853,124 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "icu_collections"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
dependencies = [
"displaydoc",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_locid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
dependencies = [
"displaydoc",
"litemap",
"tinystr",
"writeable",
"zerovec",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
[[package]]
name = "icu_properties"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
[[package]]
name = "icu_provider"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]] [[package]]
name = "ident_case" name = "ident_case"
version = "1.0.1" version = "1.0.1"
@ -850,12 +979,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.5.0" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
dependencies = [ dependencies = [
"unicode-bidi", "idna_adapter",
"unicode-normalization", "smallvec",
"utf8_iter",
]
[[package]]
name = "idna_adapter"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
dependencies = [
"icu_normalizer",
"icu_properties",
] ]
[[package]] [[package]]
@ -912,6 +1052,12 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "litemap"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@ -1126,14 +1272,14 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]] [[package]]
name = "playerbot" name = "playerbot"
version = "0.5.0" version = "0.6.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"dotenvy", "dotenvy",
"log", "log",
"poise", "poise",
"pretty_env_logger", "pretty_env_logger",
"reqwest 0.12.8", "reqwest 0.12.9",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
@ -1337,9 +1483,9 @@ dependencies = [
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.8" version = "0.12.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bytes", "bytes",
@ -1580,9 +1726,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.210" version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -1598,9 +1744,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.210" version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1736,6 +1882,12 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@ -1785,6 +1937,17 @@ dependencies = [
"futures-core", "futures-core",
] ]
[[package]]
name = "synstructure"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]
[[package]] [[package]]
name = "system-configuration" name = "system-configuration"
version = "0.5.1" version = "0.5.1"
@ -1907,25 +2070,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "tinyvec" name = "tinystr"
version = "1.8.0" version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
dependencies = [ dependencies = [
"tinyvec_macros", "displaydoc",
"zerovec",
] ]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.40.0" version = "1.41.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -2139,27 +2297,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
[[package]]
name = "unicode-bidi"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.13" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-normalization"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"
@ -2168,9 +2311,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.2" version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna",
@ -2184,6 +2327,18 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"
@ -2532,6 +2687,42 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "write16"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "yoke"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
"synstructure",
]
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.35" version = "0.7.35"
@ -2553,8 +2744,51 @@ dependencies = [
"syn 2.0.82", "syn 2.0.82",
] ]
[[package]]
name = "zerofrom"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
"synstructure",
]
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.8.1" version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zerovec"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
dependencies = [
"yoke",
"zerofrom",
"zerovec-derive",
]
[[package]]
name = "zerovec-derive"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.82",
]

View File

@ -1,16 +1,16 @@
[package] [package]
name = "playerbot" name = "playerbot"
version = "0.5.0" version = "0.6.1"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.90" anyhow = "1.0.93"
dotenvy = "0.15.7" dotenvy = "0.15.7"
log = "0.4.22" log = "0.4.22"
poise = "0.6.1" poise = "0.6.1"
pretty_env_logger = "0.5.0" pretty_env_logger = "0.5.0"
reqwest = {version = "0.12.8", features = ["json"]} reqwest = {version = "0.12.9", features = ["json"]}
serde = {version = "1.0.210", features = ["derive", "serde_derive"]} serde = {version = "1.0.215", features = ["derive", "serde_derive"]}
serde_json = {version = "1.0.132", features = []} serde_json = {version = "1.0.132", features = []}
tokio = {version = "1.40.0", features = ["full"]} tokio = {version = "1.41.1", features = ["full"]}
url = "2.5.2" url = "2.5.3"

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Playerbot
Using Tokio to run two futures simultaneously, I put together two discord bots which each update their statuses/presences with information about a corresponding game server.

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(),
})), })),

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,20 @@ 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/bleat.shibedrill.site").unwrap(),
std::env::var("TOKEN_BOT_MC_BLEAT").unwrap(),
"DeersCord SMP".into(),
);
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(),
"Project MCRV".into(),
);
let scpsl = Scpsl::new(
Url::try_from("https://api.scplist.kr/api/servers/81460").unwrap(),
std::env::var("TOKEN_BOT_SCPSL").unwrap(),
"SCP:SL".into(),
);
join!(scpsl.run(), mchprs.run(), gamerzone.run());
} }

View File

@ -1,67 +1,61 @@
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};
#[derive(serde::Deserialize)] #[derive(serde::Deserialize, Debug)]
struct ServerSummary { struct ServerSummary {
online: bool, online: bool,
players: Option<Players>, players: Option<Players>,
} }
#[derive(serde::Deserialize)] #[derive(serde::Deserialize, Debug)]
struct Players { struct Players {
online: i32, online: i32,
max: i32, max: i32,
} }
pub struct Data {} pub struct Data {
controller: Minecraft,
}
async fn get_status() -> Result<ServerResponse, anyhow::Error> { #[derive(Clone)]
pub struct Minecraft {
url: Url,
token: String,
name: String,
}
impl Minecraft {
pub fn new(url: Url, token: String, name: String) -> Self {
Self { url, token, name }
}
pub async fn get_status(&self) -> Result<ServerResponse, anyhow::Error> {
let http_client = Client::new(); let http_client = Client::new();
let request = Request::new( trace!("Created HTTP client");
reqwest::Method::GET, let request = Request::new(reqwest::Method::GET, self.url.clone());
"https://api.mcstatus.io/v2/status/java/gamer.shibedrill.site" trace!("Created HTTP request");
.try_into()?,
);
let response = http_client.execute(request).await?; let response = http_client.execute(request).await?;
trace!("Ran request using client");
let data: ServerSummary = serde_json::from_str(&response.text().await?)?; let data: ServerSummary = serde_json::from_str(&response.text().await?)?;
trace!("Response JSON for {}: {:#?}", self.name, data); // this
if let Some(players) = data.players { if let Some(players) = data.players {
Ok(ServerResponse::new( Ok(ServerResponse::new(
data.online, data.online,
players.online as u32, Some(players.online as u32),
players.max as u32, Some(players.max as u32),
)) ))
} else { } else {
Ok(ServerResponse::new(data.online, 0, 0)) Ok(ServerResponse::new(data.online, None, None))
} }
} }
pub async fn run(&self) {
pub async fn event_handler( let controller = self.clone();
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 = get_status()
.await
.inspect_err(|e| error!("Failed to get status: {}", e))
.unwrap();
info!("Got status: {}", status.to_string());
funcs::set_presence(&ctx, status);
tokio::time::sleep(std::time::Duration::from_secs(30)).await;
},
_ => Ok(()),
}
}
pub async fn run() {
let framework = poise::Framework::builder() let framework = poise::Framework::builder()
.options(poise::FrameworkOptions { .options(poise::FrameworkOptions {
event_handler: |ctx, event, framework, data| { event_handler: |ctx, event, framework, data| {
@ -72,14 +66,14 @@ pub async fn run() {
.setup(|ctx, _ready, framework| { .setup(|ctx, _ready, framework| {
Box::pin(async move { Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?; poise::builtins::register_globally(ctx, &framework.options().commands).await?;
Ok(Data {}) Ok(Data { controller })
}) })
}) })
.build(); .build();
info!("Built framework successfully."); info!("Built framework successfully.");
let mut discord_client = ClientBuilder::new( let mut discord_client = ClientBuilder::new(
std::env::var("MINECRAFT_BOT_TOKEN").inspect_err(|e| {error!("Failed to get token: {}", e)}).unwrap(), self.token.clone(),
serenity::GatewayIntents::non_privileged(), serenity::GatewayIntents::non_privileged(),
) )
.framework(framework) .framework(framework)
@ -91,3 +85,34 @@ pub async fn run() {
let _ = discord_client.start().await; 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: _bot_data,
} => loop {
trace!("Running loop routine");
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(()),
}
}

View File

@ -1,27 +1,42 @@
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, Debug)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
struct ServerSummary { struct ServerSummary {
online: bool, online: bool,
players: String, players: String,
} }
pub struct Data {} pub struct Data {
controller: Scpsl,
}
async fn get_status() -> Result<ServerResponse, anyhow::Error> { #[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 http_client = Client::new();
let request = Request::new( trace!("Created HTTP client");
reqwest::Method::GET, let request = Request::new(reqwest::Method::GET, self.url.clone());
url::Url::try_from("https://api.scplist.kr/api/servers/81460")?, trace!("Created HTTP request");
);
let response = http_client.execute(request).await?; let response = http_client.execute(request).await?;
trace!("Ran request using client");
let data: ServerSummary = serde_json::from_str(&response.text().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>, _> = let playercount: Result<Vec<u32>, _> =
data.players.split('/').map(|x| x.parse::<u32>()).collect(); data.players.split('/').map(|x| x.parse::<u32>()).collect();
@ -29,35 +44,13 @@ async fn get_status() -> Result<ServerResponse, anyhow::Error> {
Ok(ServerResponse::new( Ok(ServerResponse::new(
data.online, data.online,
playercount_unwrapped[0], playercount_unwrapped.first().copied(),
playercount_unwrapped[1], playercount_unwrapped.get(1).copied(),
)) ))
} }
pub async fn event_handler( pub async fn run(&self) {
ctx: &serenity::Context, let controller = self.clone();
event: &serenity::FullEvent,
_framework: poise::FrameworkContext<'_, Data, Error>,
_data: &Data,
) -> Result<(), Error> {
match event {
serenity::FullEvent::Ready {
data_about_bot: _data,
} => loop {
let status = get_status()
.await
.inspect_err(|e| error!("Failed to get status: {}", e))
.unwrap();
info!("Got status: {}", status.to_string());
funcs::set_presence(ctx, status);
tokio::time::sleep(std::time::Duration::from_secs(30)).await;
},
_ => Ok(()),
}
}
pub async fn run() {
let framework = poise::Framework::builder() let framework = poise::Framework::builder()
.options(poise::FrameworkOptions { .options(poise::FrameworkOptions {
initialize_owners: true, initialize_owners: true,
@ -69,14 +62,14 @@ pub async fn run() {
.setup(|ctx, _ready, framework| { .setup(|ctx, _ready, framework| {
Box::pin(async move { Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?; poise::builtins::register_globally(ctx, &framework.options().commands).await?;
Ok(Data {}) Ok(Data { controller })
}) })
}) })
.build(); .build();
info!("Built framework successfully."); info!("Built framework successfully.");
let mut discord_client = ClientBuilder::new( let mut discord_client = ClientBuilder::new(
std::env::var("SCPSL_BOT_TOKEN").inspect_err(|e| {error!("Failed to get token: {}", e)}).unwrap(), self.token.clone(),
serenity::GatewayIntents::non_privileged(), serenity::GatewayIntents::non_privileged(),
) )
.framework(framework) .framework(framework)
@ -88,3 +81,34 @@ pub async fn run() {
let _ = discord_client.start().await; 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 {
trace!("Running loop routine");
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(()),
}
}

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,19 +17,23 @@ 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
} }
pub fn is_full(&self) -> bool { pub fn is_full(&self) -> bool {
self.players == self.max self.players >= self.max
} }
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)
}
} }
} }