From 5417dcaa1d5d8bf10f1976bcf4c36d3a64470230 Mon Sep 17 00:00:00 2001 From: toast Date: Sat, 7 Dec 2024 01:33:55 +1100 Subject: [PATCH] Repository restructure --- .dockerignore | 2 + .gitattributes | 2 +- Cargo.lock | 128 +++++++++++++----- Cargo.toml | 27 +++- Dockerfile | 2 +- cmds/Cargo.toml | 16 +++ cmds/src/dispatch.rs | 42 ++++++ {src/commands => cmds/src/dispatch}/ilo.rs | 21 ++- {src/commands => cmds/src/dispatch}/midi.rs | 22 ++- {src/commands => cmds/src/dispatch}/status.rs | 24 ++-- {src/commands => cmds/src/dispatch}/uptime.rs | 20 +-- cmds/src/lib.rs | 2 + libs/Cargo.toml | 12 ++ {src/internals => libs}/assets/FluidR3_GM.sf2 | 0 build.rs => libs/build.rs | 0 {src/internals => libs/src}/config.rs | 0 libs/src/data.rs | 1 + {src/internals => libs/src}/http.rs | 6 +- src/internals/utils.rs => libs/src/lib.rs | 40 ++++-- libs/src/types.rs | 9 ++ repo/Cargo.toml | 10 ++ {src/controllers => repo/src}/cache.rs | 2 +- repo/src/lib.rs | 2 + src/commands.rs | 16 --- src/commands/ping.rs | 8 -- src/controllers.rs | 1 - src/internals.rs | 5 - src/internals/tsclient.rs | 21 --- src/main.rs | 61 +++------ tasks/Cargo.toml | 17 +++ src/internals/tasks.rs => tasks/src/lib.rs | 3 +- {src/internals/tasks => tasks/src}/rss.rs | 27 ++-- .../internals/tasks => tasks/src}/rss/esxi.rs | 22 ++- .../tasks => tasks/src}/rss/github.rs | 28 ++-- .../tasks => tasks/src}/rss/gportal.rs | 28 ++-- .../tasks => tasks/src}/rss/processor.rs | 8 +- .../internals/tasks => tasks/src}/rss/rust.rs | 20 ++- tokens/Cargo.toml | 8 ++ tokens/src/lib.rs | 42 ++++++ 39 files changed, 436 insertions(+), 269 deletions(-) create mode 100644 cmds/Cargo.toml create mode 100644 cmds/src/dispatch.rs rename {src/commands => cmds/src/dispatch}/ilo.rs (95%) rename {src/commands => cmds/src/dispatch}/midi.rs (86%) rename {src/commands => cmds/src/dispatch}/status.rs (86%) rename {src/commands => cmds/src/dispatch}/uptime.rs (89%) create mode 100644 cmds/src/lib.rs create mode 100644 libs/Cargo.toml rename {src/internals => libs}/assets/FluidR3_GM.sf2 (100%) rename build.rs => libs/build.rs (100%) rename {src/internals => libs/src}/config.rs (100%) create mode 100644 libs/src/data.rs rename {src/internals => libs/src}/http.rs (83%) rename src/internals/utils.rs => libs/src/lib.rs (67%) create mode 100644 libs/src/types.rs create mode 100644 repo/Cargo.toml rename {src/controllers => repo/src}/cache.rs (98%) create mode 100644 repo/src/lib.rs delete mode 100644 src/commands.rs delete mode 100644 src/commands/ping.rs delete mode 100644 src/controllers.rs delete mode 100644 src/internals.rs delete mode 100644 src/internals/tsclient.rs create mode 100644 tasks/Cargo.toml rename src/internals/tasks.rs => tasks/src/lib.rs (93%) rename {src/internals/tasks => tasks/src}/rss.rs (91%) rename {src/internals/tasks => tasks/src}/rss/esxi.rs (90%) rename {src/internals/tasks => tasks/src}/rss/github.rs (91%) rename {src/internals/tasks => tasks/src}/rss/gportal.rs (91%) rename {src/internals/tasks => tasks/src}/rss/processor.rs (98%) rename {src/internals/tasks => tasks/src}/rss/rust.rs (88%) create mode 100644 tokens/Cargo.toml create mode 100644 tokens/src/lib.rs diff --git a/.dockerignore b/.dockerignore index c87c920..677d1ae 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,3 +7,5 @@ docker-compose.yml Dockerfile renovate.json run.sh +target/debug/ +target/release/ diff --git a/.gitattributes b/.gitattributes index d1f793d..9a777c5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -src/internals/assets/FluidR3_GM.sf2 filter=lfs diff=lfs merge=lfs -text +libs/assets/FluidR3_GM.sf2 filter=lfs diff=lfs merge=lfs -text diff --git a/Cargo.lock b/Cargo.lock index 072b793..c490bfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,9 +207,9 @@ dependencies = [ [[package]] name = "cargo_toml" -version = "0.20.5" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88da5a13c620b4ca0078845707ea9c3faf11edbc3ffd8497d11d686211cd1ac0" +checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" dependencies = [ "serde", "toml", @@ -698,7 +698,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", + "http 1.2.0", "indexmap", "slab", "tokio", @@ -748,9 +748,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -775,7 +775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -786,7 +786,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -837,7 +837,7 @@ dependencies = [ "futures-channel", "futures-util", "h2 0.4.7", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "httparse", "itoa", @@ -868,13 +868,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 1.1.0", + "http 1.2.0", "hyper 1.5.1", "hyper-util", "rustls 0.23.19", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tower-service", ] @@ -903,7 +903,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "hyper 1.5.1", "pin-project-lite", @@ -1119,6 +1119,15 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.14" @@ -1137,24 +1146,73 @@ dependencies = [ [[package]] name = "kon" -version = "0.5.1" +version = "0.6.0" dependencies = [ - "bb8", - "bb8-redis", - "cargo_toml", - "feed-rs", - "once_cell", + "kon_cmds", + "kon_libs", + "kon_tasks", + "kon_tokens", + "poise", + "tokio", +] + +[[package]] +name = "kon_cmds" +version = "0.1.0" +dependencies = [ + "kon_libs", + "kon_tokens", "poise", "regex", "reqwest 0.12.9", "serde", "serde_json", "sysinfo", - "tokenservice-client", "tokio", "uptime_lib", ] +[[package]] +name = "kon_libs" +version = "0.1.0" +dependencies = [ + "cargo_toml", + "poise", + "reqwest 0.12.9", +] + +[[package]] +name = "kon_repo" +version = "0.1.0" +dependencies = [ + "bb8", + "bb8-redis", + "kon_tokens", + "tokio", +] + +[[package]] +name = "kon_tasks" +version = "0.1.0" +dependencies = [ + "feed-rs", + "kon_libs", + "kon_repo", + "once_cell", + "poise", + "regex", + "reqwest 0.12.9", + "tokio", +] + +[[package]] +name = "kon_tokens" +version = "0.1.0" +dependencies = [ + "tokenservice-client", + "tokio", +] + [[package]] name = "libc" version = "0.2.167" @@ -1593,15 +1651,16 @@ dependencies = [ [[package]] name = "redis" -version = "0.27.5" +version = "0.27.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cccf17a692ce51b86564334614d72dcae1def0fd5ecebc9f02956da74352b5" +checksum = "09d8f99a4090c89cc489a94833c901ead69bfbf3877b4867d5482e321ee875bc" dependencies = [ "arc-swap", "async-trait", "bytes", "combine", "futures-util", + "itertools", "itoa", "num-bigint", "percent-encoding", @@ -1706,7 +1765,7 @@ dependencies = [ "futures-core", "futures-util", "h2 0.4.7", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "hyper 1.5.1", @@ -2188,9 +2247,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" +checksum = "948512566b1895f93b1592c7574baeb2de842f224f2aab158799ecadb8ebbb46" dependencies = [ "core-foundation-sys", "libc", @@ -2283,9 +2342,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -2304,9 +2363,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -2352,9 +2411,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -2412,12 +2471,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls 0.23.19", - "rustls-pki-types", "tokio", ] @@ -2439,9 +2497,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -2595,7 +2653,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http 1.2.0", "httparse", "log", "rand", diff --git a/Cargo.toml b/Cargo.toml index 5922601..8674d45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,15 @@ [package] name = "kon" -version = "0.5.1" +version = "0.6.0" edition = "2024" -[dependencies] +[workspace] +members = ["cmds", "libs", "repo", "tasks", "tokens"] + +[workspace.dependencies] bb8 = "0.8.6" bb8-redis = "0.17.0" -cargo_toml = "0.20.5" +cargo_toml = "0.21.0" feed-rs = "2.2.0" once_cell = "1.20.2" poise = "0.6.1" @@ -14,16 +17,26 @@ regex = "1.11.1" reqwest = { version = "0.12.9", features = ["json", "native-tls-vendored"] } serde = "1.0.215" serde_json = "1.0.133" -sysinfo = "0.32.1" -tokenservice-client = { version = "0.4.1", registry = "gitea" } -tokio = { version = "1.41.1", features = ["macros", "signal", "rt-multi-thread"] } +sysinfo = "0.33.0" +tokio = { version = "1.42.0", features = ["macros", "signal", "rt-multi-thread"] } uptime_lib = "0.3.1" +kon_libs = { path = "libs" } +kon_tokens = { path = "tokens" } +kon_repo = { path = "repo" } + +[dependencies] +kon_cmds = { path = "cmds" } +kon_libs = { workspace = true } +kon_tasks = { path = "tasks" } +kon_tokens = { workspace = true } +poise = { workspace = true } +tokio = { workspace = true } [patch.crates-io] poise = { git = "https://github.com/serenity-rs/poise", branch = "next" } [features] -production = [] +production = ["kon_libs/production", "kon_tasks/production"] [[bin]] name = "kon" diff --git a/Dockerfile b/Dockerfile index b56530b..37b7f92 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM scratch AS base WORKDIR /builder COPY . . -FROM alpine:3.20 +FROM alpine:3.21 LABEL org.opencontainers.image.source="https://git.toast-server.net/toast/Kon" RUN apk add --no-cache libgcc fluidsynth WORKDIR /kon diff --git a/cmds/Cargo.toml b/cmds/Cargo.toml new file mode 100644 index 0000000..42e9a62 --- /dev/null +++ b/cmds/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "kon_cmds" +version = "0.1.0" +edition = "2024" + +[dependencies] +kon_libs = { workspace = true } +kon_tokens = { workspace = true } +poise = { workspace = true } +regex = { workspace = true } +reqwest = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +sysinfo = { workspace = true } +tokio = { workspace = true } +uptime_lib = { workspace = true } diff --git a/cmds/src/dispatch.rs b/cmds/src/dispatch.rs new file mode 100644 index 0000000..566c345 --- /dev/null +++ b/cmds/src/dispatch.rs @@ -0,0 +1,42 @@ +use kon_libs::{ + KonData, + KonError, + KonResult, + PoiseCtx +}; + +use poise::Command; + +mod ilo; +mod midi; +mod status; +mod uptime; + +use { + ilo::ilo, + midi::midi_to_wav, + status::status, + uptime::uptime +}; + +macro_rules! commands { + ($($cmd:ident),*) => { + vec![$($cmd()),*] + } +} + +pub fn register_cmds() -> Vec> { commands!(deploy, ping, midi_to_wav, status, ilo, uptime) } + +/// Deploy the commands globally or in a guild +#[poise::command(prefix_command, owners_only, guild_only)] +pub async fn deploy(ctx: PoiseCtx<'_>) -> KonResult<()> { + poise::builtins::register_application_commands_buttons(ctx).await?; + Ok(()) +} + +/// Check if the bot is alive +#[poise::command(slash_command)] +pub async fn ping(ctx: PoiseCtx<'_>) -> KonResult<()> { + ctx.reply(format!("Powong! `{:.2?}`", ctx.ping().await)).await?; + Ok(()) +} diff --git a/src/commands/ilo.rs b/cmds/src/dispatch/ilo.rs similarity index 95% rename from src/commands/ilo.rs rename to cmds/src/dispatch/ilo.rs index b0f774a..fcb40c2 100644 --- a/src/commands/ilo.rs +++ b/cmds/src/dispatch/ilo.rs @@ -1,12 +1,9 @@ -use crate::{ - Error, - internals::{ - config::BINARY_PROPERTIES, - utils::token_path - } -}; - use { + kon_libs::{ + BINARY_PROPERTIES, + KonResult + }, + kon_tokens::token_path, poise::{ CreateReply, serenity_prelude::{ @@ -190,11 +187,11 @@ async fn ilo_data(endpoint: RedfishEndpoint) -> Result) -> Result<(), Error> { Ok(()) } +pub async fn ilo(_: super::PoiseCtx<'_>) -> KonResult<()> { Ok(()) } /// Retrieve the server's temperature data #[poise::command(slash_command)] -pub async fn temperature(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { +pub async fn temperature(ctx: super::PoiseCtx<'_>) -> KonResult<()> { ctx.defer().await?; let ilo = ilo_data(RedfishEndpoint::Thermal).await.unwrap(); let data = ilo.downcast_ref::().unwrap(); @@ -242,7 +239,7 @@ pub async fn temperature(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { /// Retrieve the server's power data #[poise::command(slash_command)] -pub async fn power(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { +pub async fn power(ctx: super::PoiseCtx<'_>) -> KonResult<()> { ctx.defer().await?; let ilo = ilo_data(RedfishEndpoint::Power).await.unwrap(); let data = ilo.downcast_ref::().unwrap(); @@ -272,7 +269,7 @@ pub async fn power(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { /// Retrieve the server's system data #[poise::command(slash_command)] -pub async fn system(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { +pub async fn system(ctx: super::PoiseCtx<'_>) -> KonResult<()> { ctx.defer().await?; let (ilo_sys, ilo_event) = tokio::join!(ilo_data(RedfishEndpoint::System), ilo_data(RedfishEndpoint::EventService)); diff --git a/src/commands/midi.rs b/cmds/src/dispatch/midi.rs similarity index 86% rename from src/commands/midi.rs rename to cmds/src/dispatch/midi.rs index f998045..7c969d0 100644 --- a/src/commands/midi.rs +++ b/cmds/src/dispatch/midi.rs @@ -1,12 +1,10 @@ -use crate::{ - Error, - internals::utils::{ +use { + kon_libs::{ + KonError, + KonResult, format_bytes, mention_dev - } -}; - -use { + }, poise::{ CreateReply, serenity_prelude::CreateAttachment @@ -31,7 +29,7 @@ use { pub async fn midi_to_wav( ctx: super::PoiseCtx<'_>, #[description = "MIDI file to be converted"] message: poise::serenity_prelude::Message -) -> Result<(), Error> { +) -> KonResult<()> { let re = Regex::new(r"(?i)\.mid$").unwrap(); if !message.embeds.is_empty() || message.attachments.is_empty() || !re.is_match(&message.attachments[0].filename) { @@ -52,7 +50,7 @@ pub async fn midi_to_wav( .await .unwrap(); - return Err(Error::from(format!("Failed to download the file: {y}"))) + return Err(KonError::from(format!("Failed to download the file: {y}"))) } }; @@ -62,14 +60,14 @@ pub async fn midi_to_wav( let wav_path = re.replace(midi_path, ".wav"); let sf2_path = "/tmp/FluidR3_GM.sf2"; - write(sf2_path, include_bytes!("../internals/assets/FluidR3_GM.sf2"))?; + write(sf2_path, include_bytes!("../../../libs/assets/FluidR3_GM.sf2"))?; let output = std::process::Command::new("fluidsynth") .args(["-ni", sf2_path, midi_path, "-F", &wav_path]) .output(); // Just to add an info to console to tell what the bot is doing when MIDI file is downloaded. - println!("Discord[{}]: Processing MIDI file: \"{}\"", ctx.command().qualified_name, midi_path); + println!("Discord[{}]: Processing MIDI file: \"{midi_path}\"", ctx.command().qualified_name); match output { Ok(_) => { @@ -102,7 +100,7 @@ pub async fn midi_to_wav( .await .unwrap(); - return Err(Error::from(format!("Midi conversion failed: {y}"))) + return Err(KonError::from(format!("Midi conversion failed: {y}"))) } } diff --git a/src/commands/status.rs b/cmds/src/dispatch/status.rs similarity index 86% rename from src/commands/status.rs rename to cmds/src/dispatch/status.rs index f81cd27..b4ebd21 100644 --- a/src/commands/status.rs +++ b/cmds/src/dispatch/status.rs @@ -1,13 +1,5 @@ -use crate::{ - Error, - internals::{ - config::BINARY_PROPERTIES, - http::HttpClient, - utils::token_path - } -}; - use { + kon_tokens::token_path, poise::{ CreateReply, serenity_prelude::builder::CreateEmbed @@ -17,7 +9,13 @@ use { tokio::join }; -async fn pms_serverstatus(url: &str) -> Result)>, Error> { +use kon_libs::{ + BINARY_PROPERTIES, + HttpClient, + KonResult +}; + +async fn pms_serverstatus(url: &str) -> KonResult)>> { let client = HttpClient::new(); let req = client.get(url, "PMS-Status").await?; @@ -66,7 +64,7 @@ fn process_pms_statuses(servers: Vec<(String, Vec)>) -> Vec<(String, Stri for (title, servers) in server_map { let servers_str = servers .iter() - .map(|(name, status)| format!("{}: {}", name, status)) + .map(|(name, status)| format!("{name}: {status}")) .collect::>() .join("\n"); statuses.push((title, servers_str, true)); @@ -76,11 +74,11 @@ fn process_pms_statuses(servers: Vec<(String, Vec)>) -> Vec<(String, Stri /// Query the server statuses #[poise::command(slash_command, subcommands("wg"))] -pub async fn status(_: super::PoiseCtx<'_>) -> Result<(), Error> { Ok(()) } +pub async fn status(_: super::PoiseCtx<'_>) -> KonResult<()> { Ok(()) } /// Retrieve the server statuses from Wargaming #[poise::command(slash_command)] -pub async fn wg(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { +pub async fn wg(ctx: super::PoiseCtx<'_>) -> KonResult<()> { let pms_asia = token_path().await.wg_pms; let pms_eu = pms_asia.replace("asia", "eu"); let embed = CreateEmbed::new().color(BINARY_PROPERTIES.embed_color); diff --git a/src/commands/uptime.rs b/cmds/src/dispatch/uptime.rs similarity index 89% rename from src/commands/uptime.rs rename to cmds/src/dispatch/uptime.rs index 52b392b..3ee1cb7 100644 --- a/src/commands/uptime.rs +++ b/cmds/src/dispatch/uptime.rs @@ -1,14 +1,14 @@ -use crate::{ - Error, +use kon_libs::{ GIT_COMMIT_BRANCH, - GIT_COMMIT_HASH, - internals::utils::{ - BOT_VERSION, - format_duration - } + GIT_COMMIT_HASH }; use { + kon_libs::{ + BOT_VERSION, + KonResult, + format_duration + }, std::{ fs::File, io::{ @@ -47,8 +47,8 @@ fn get_os_info() -> String { /// Retrieve host and bot uptimes #[poise::command(slash_command)] -pub async fn uptime(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { - let _bot = ctx.http().get_current_user().await.unwrap(); +pub async fn uptime(ctx: super::PoiseCtx<'_>) -> KonResult<()> { + let bot = ctx.http().get_current_user().await.unwrap(); let mut sys = System::new_all(); sys.refresh_all(); @@ -68,7 +68,7 @@ pub async fn uptime(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { } let stat_msg = [ - format!("**{} {}** `{GIT_COMMIT_HASH}:{GIT_COMMIT_BRANCH}`", _bot.name, BOT_VERSION.as_str()), + format!("**{} {}** `{GIT_COMMIT_HASH}:{GIT_COMMIT_BRANCH}`", bot.name, BOT_VERSION.as_str()), format!(">>> System: `{}`", format_duration(sys_uptime)), format!("Process: `{}`", format_duration(proc_uptime)), format!("CPU: `{}`", cpu[0].brand()), diff --git a/cmds/src/lib.rs b/cmds/src/lib.rs new file mode 100644 index 0000000..0b23e04 --- /dev/null +++ b/cmds/src/lib.rs @@ -0,0 +1,2 @@ +mod dispatch; +pub use dispatch::*; diff --git a/libs/Cargo.toml b/libs/Cargo.toml new file mode 100644 index 0000000..1a714e7 --- /dev/null +++ b/libs/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "kon_libs" +version = "0.1.0" +edition = "2024" + +[dependencies] +cargo_toml = { workspace = true } +poise = { workspace = true } +reqwest = { workspace = true } + +[features] +production = [] diff --git a/src/internals/assets/FluidR3_GM.sf2 b/libs/assets/FluidR3_GM.sf2 similarity index 100% rename from src/internals/assets/FluidR3_GM.sf2 rename to libs/assets/FluidR3_GM.sf2 diff --git a/build.rs b/libs/build.rs similarity index 100% rename from build.rs rename to libs/build.rs diff --git a/src/internals/config.rs b/libs/src/config.rs similarity index 100% rename from src/internals/config.rs rename to libs/src/config.rs diff --git a/libs/src/data.rs b/libs/src/data.rs new file mode 100644 index 0000000..236c506 --- /dev/null +++ b/libs/src/data.rs @@ -0,0 +1 @@ +pub struct KonData {} diff --git a/src/internals/http.rs b/libs/src/http.rs similarity index 83% rename from src/internals/http.rs rename to libs/src/http.rs index 15c150f..e9b7a90 100644 --- a/src/internals/http.rs +++ b/libs/src/http.rs @@ -11,6 +11,10 @@ const ERROR_PREFIX: &str = "HTTPClient[Error]:"; pub struct HttpClient(Client); +impl Default for HttpClient { + fn default() -> Self { Self::new() } +} + impl HttpClient { pub fn new() -> Self { Self(Client::new()) } @@ -24,7 +28,7 @@ impl HttpClient { .get(url) .header( reqwest::header::USER_AGENT, - format!("Kon ({}-{}) - {ua}/reqwest", super::utils::BOT_VERSION.as_str(), crate::GIT_COMMIT_HASH) + format!("Kon ({}-{}) - {ua}/reqwest", crate::BOT_VERSION.as_str(), crate::GIT_COMMIT_HASH) ) .timeout(Duration::from_secs(30)) .send() diff --git a/src/internals/utils.rs b/libs/src/lib.rs similarity index 67% rename from src/internals/utils.rs rename to libs/src/lib.rs index 228d010..e26f0f9 100644 --- a/src/internals/utils.rs +++ b/libs/src/lib.rs @@ -1,27 +1,39 @@ +mod config; +pub use config::BINARY_PROPERTIES; + +mod types; +pub use types::*; + +mod data; +pub use data::KonData; + +mod http; +pub use http::HttpClient; + use { - super::tsclient::TSClient, + cargo_toml::Manifest, poise::serenity_prelude::UserId, - std::sync::LazyLock, - tokenservice_client::TokenServiceApi, - tokio::sync::Mutex + std::sync::LazyLock }; +#[cfg(feature = "production")] +pub static GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH"); +pub static GIT_COMMIT_BRANCH: &str = env!("GIT_COMMIT_BRANCH"); + +#[cfg(not(feature = "production"))] +pub static GIT_COMMIT_HASH: &str = "devel"; + pub static BOT_VERSION: LazyLock = LazyLock::new(|| { - let cargo_version = cargo_toml::Manifest::from_str(include_str!("../../Cargo.toml")) + Manifest::from_str(include_str!("../../Cargo.toml")) .unwrap() .package .unwrap() .version - .unwrap(); - format!("v{cargo_version}") + .unwrap() }); -static TSCLIENT: LazyLock> = LazyLock::new(|| Mutex::new(TSClient::new())); - -pub async fn token_path() -> TokenServiceApi { TSCLIENT.lock().await.get().await.unwrap() } - -pub fn mention_dev(ctx: poise::Context<'_, (), crate::Error>) -> Option { - let devs = super::config::BINARY_PROPERTIES.developers.clone(); +pub fn mention_dev(ctx: PoiseCtx<'_>) -> Option { + let devs = BINARY_PROPERTIES.developers.clone(); let app_owners = ctx.framework().options().owners.clone(); let mut mentions = Vec::new(); @@ -57,7 +69,7 @@ pub fn format_duration(secs: u64) -> String { } pub fn format_bytes(bytes: u64) -> String { - let units = ["B", "KB", "MB", "GB", "TB", "PB"]; + let units = ["B", "KB", "MB", "GB"]; let mut value = bytes as f64; let mut unit = units[0]; diff --git a/libs/src/types.rs b/libs/src/types.rs new file mode 100644 index 0000000..e46837e --- /dev/null +++ b/libs/src/types.rs @@ -0,0 +1,9 @@ +use { + super::KonData, + std::error::Error +}; + +pub type KonError = Box; +pub type KonResult = Result; +pub type PoiseCtx<'a> = poise::Context<'a, KonData, KonError>; +pub type PoiseFwCtx<'a> = poise::FrameworkContext<'a, KonData, KonError>; diff --git a/repo/Cargo.toml b/repo/Cargo.toml new file mode 100644 index 0000000..fd46725 --- /dev/null +++ b/repo/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "kon_repo" +version = "0.1.0" +edition = "2024" + +[dependencies] +bb8 = { workspace = true } +bb8-redis = { workspace = true } +kon_tokens = { workspace = true } +tokio = { workspace = true } diff --git a/src/controllers/cache.rs b/repo/src/cache.rs similarity index 98% rename from src/controllers/cache.rs rename to repo/src/cache.rs index aef9d92..7f5290b 100644 --- a/src/controllers/cache.rs +++ b/repo/src/cache.rs @@ -1,4 +1,4 @@ -use crate::internals::utils::token_path; +use kon_tokens::token_path; use { bb8_redis::{ diff --git a/repo/src/lib.rs b/repo/src/lib.rs new file mode 100644 index 0000000..b7000df --- /dev/null +++ b/repo/src/lib.rs @@ -0,0 +1,2 @@ +mod cache; +pub use cache::RedisController; diff --git a/src/commands.rs b/src/commands.rs deleted file mode 100644 index 1b445d8..0000000 --- a/src/commands.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::Error; - -pub mod ilo; -pub mod midi; -pub mod ping; -pub mod status; -pub mod uptime; - -type PoiseCtx<'a> = poise::Context<'a, (), Error>; - -/// Deploy the commands globally or in a guild -#[poise::command(prefix_command, owners_only, guild_only)] -pub async fn deploy(ctx: PoiseCtx<'_>) -> Result<(), Error> { - poise::builtins::register_application_commands_buttons(ctx).await?; - Ok(()) -} diff --git a/src/commands/ping.rs b/src/commands/ping.rs deleted file mode 100644 index 763aa99..0000000 --- a/src/commands/ping.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::Error; - -/// Check if the bot is alive -#[poise::command(slash_command)] -pub async fn ping(ctx: super::PoiseCtx<'_>) -> Result<(), Error> { - ctx.reply(format!("Powong! `{:?}`", ctx.ping().await)).await?; - Ok(()) -} diff --git a/src/controllers.rs b/src/controllers.rs deleted file mode 100644 index a5c08fd..0000000 --- a/src/controllers.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod cache; diff --git a/src/internals.rs b/src/internals.rs deleted file mode 100644 index b3288b4..0000000 --- a/src/internals.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod config; -pub mod http; -pub mod tasks; -pub mod tsclient; -pub mod utils; diff --git a/src/internals/tsclient.rs b/src/internals/tsclient.rs deleted file mode 100644 index 9290ea8..0000000 --- a/src/internals/tsclient.rs +++ /dev/null @@ -1,21 +0,0 @@ -use tokenservice_client::{ - TokenService, - TokenServiceApi -}; - -pub struct TSClient(TokenService); - -impl TSClient { - pub fn new() -> Self { - let args: Vec = std::env::args().collect(); - let service = if args.len() > 1 { &args[1] } else { "kon" }; - Self(TokenService::new(service)) - } - - pub async fn get(&self) -> Result { - match self.0.connect().await { - Ok(api) => Ok(api), - Err(e) => Err(e) - } - } -} diff --git a/src/main.rs b/src/main.rs index f4b98fe..cb5c17a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,23 +1,23 @@ -mod commands; -mod controllers; -mod internals; // https://cdn.toast-server.net/RustFSHiearchy.png // Using the new filesystem hierarchy -use crate::internals::{ - config::BINARY_PROPERTIES, - tasks::{ +use { + kon_cmds::register_cmds, + kon_libs::{ + BINARY_PROPERTIES, + BOT_VERSION, + GIT_COMMIT_BRANCH, + GIT_COMMIT_HASH, + KonData, + KonResult, + PoiseFwCtx, + mention_dev + }, + kon_tasks::{ rss, run_task }, - utils::{ - BOT_VERSION, - mention_dev, - token_path - } -}; - -use { + kon_tokens::token_path, poise::serenity_prelude::{ ChannelId, ClientBuilder, @@ -38,20 +38,10 @@ use { } }; -type Error = Box; - -#[cfg(feature = "production")] -pub static GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH"); -pub static GIT_COMMIT_BRANCH: &str = env!("GIT_COMMIT_BRANCH"); - -#[cfg(not(feature = "production"))] -pub static GIT_COMMIT_HASH: &str = "devel"; - async fn on_ready( ctx: &Context, - ready: &Ready, - _framework: &poise::Framework<(), Error> -) -> Result<(), Error> { + ready: &Ready +) -> KonResult { #[cfg(not(feature = "production"))] { println!("Event[Ready][Notice]: Detected a non-production environment!"); @@ -73,13 +63,13 @@ async fn on_ready( .send_message(&ctx.http, message.add_embed(ready_embed)) .await?; - Ok(()) + Ok(KonData {}) } async fn event_processor( - framework: poise::FrameworkContext<'_, (), Error>, + framework: PoiseFwCtx<'_>, event: &FullEvent -) -> Result<(), Error> { +) -> KonResult<()> { if let FullEvent::Ready { .. } = event { let thread_id = format!("{:?}", current().id()); let thread_num: String = thread_id.chars().filter(|c| c.is_ascii_digit()).collect(); @@ -102,14 +92,7 @@ async fn main() { let framework = poise::Framework::builder() .options(poise::FrameworkOptions { - commands: vec![ - commands::deploy(), - commands::ilo::ilo(), - commands::ping::ping(), - commands::status::status(), - commands::midi::midi_to_wav(), - commands::uptime::uptime(), - ], + commands: register_cmds(), prefix_options: poise::PrefixFrameworkOptions { prefix, mention_as_prefix: false, @@ -122,7 +105,7 @@ async fn main() { Box::pin(async move { let get_guild_name = match ctx.guild() { Some(guild) => guild.name.clone(), - None => String::from("Direct Message") + None => String::from("DM/User-App") }; println!("Discord[{get_guild_name}]: {} ran /{}", ctx.author().name, ctx.command().qualified_name); }) @@ -153,7 +136,7 @@ async fn main() { event_handler: |framework, event| Box::pin(event_processor(framework, event)), ..Default::default() }) - .setup(|ctx, ready, framework| Box::pin(on_ready(ctx, ready, framework))) + .setup(|ctx, ready, _| Box::pin(on_ready(ctx, ready))) .build(); let mut client = ClientBuilder::new( diff --git a/tasks/Cargo.toml b/tasks/Cargo.toml new file mode 100644 index 0000000..8e2f675 --- /dev/null +++ b/tasks/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "kon_tasks" +version = "0.1.0" +edition = "2024" + +[dependencies] +feed-rs = { workspace = true } +kon_libs = { workspace = true } +kon_repo = { workspace = true } +once_cell = { workspace = true } +poise = { workspace = true } +regex = { workspace = true } +reqwest = { workspace = true } +tokio = { workspace = true } + +[features] +production = ["kon_libs/production"] diff --git a/src/internals/tasks.rs b/tasks/src/lib.rs similarity index 93% rename from src/internals/tasks.rs rename to tasks/src/lib.rs index a69ef96..3e9d233 100644 --- a/src/internals/tasks.rs +++ b/tasks/src/lib.rs @@ -3,6 +3,7 @@ mod rss; pub use rss::rss; use { + kon_libs::KonResult, poise::serenity_prelude::Context, std::{ future::Future, @@ -38,7 +39,7 @@ pub async fn run_task( task: F ) where F: Fn(Arc) -> T + Send + 'static, - T: Future> + Send + 'static + T: Future> + Send + 'static { let ctx_cl = Arc::clone(&ctx); diff --git a/src/internals/tasks/rss.rs b/tasks/src/rss.rs similarity index 91% rename from src/internals/tasks/rss.rs rename to tasks/src/rss.rs index 84f9190..11a86c9 100644 --- a/src/internals/tasks/rss.rs +++ b/tasks/src/rss.rs @@ -5,23 +5,18 @@ mod github; mod gportal; mod rust; -use { - super::{ - super::{ - config::BINARY_PROPERTIES, - http::HttpClient - }, - task_err, - task_info - }, - crate::{ - Error, - controllers::cache::RedisController - } +use super::{ + task_err, + task_info }; use { feed_rs::parser::parse, + kon_libs::{ + HttpClient, + KonResult + }, + kon_repo::RedisController, once_cell::sync::OnceCell, poise::serenity_prelude::{ Context, @@ -82,7 +77,7 @@ fn format_html_to_discord(input: String) -> String { output } -async fn fetch_feed(url: &str) -> Result { +async fn fetch_feed(url: &str) -> KonResult { let http = HttpClient::new(); let res = match http.get(url, "RSS-Monitor").await { Ok(res) => res, @@ -95,7 +90,7 @@ async fn fetch_feed(url: &str) -> Result { async fn save_to_redis( key: &str, value: &str -) -> Result<(), Error> { +) -> KonResult<()> { let redis = get_redis().await; redis.set(key, value).await.unwrap(); if let Err(y) = redis.expire(key, REDIS_EXPIRY_SECS).await { @@ -148,7 +143,7 @@ impl IncidentColorMap { } } -pub async fn rss(ctx: Arc) -> Result<(), Error> { +pub async fn rss(ctx: Arc) -> KonResult<()> { #[cfg(feature = "production")] let mut interval = interval(Duration::from_secs(300)); // Check feeds every 5 mins #[cfg(not(feature = "production"))] diff --git a/src/internals/tasks/rss/esxi.rs b/tasks/src/rss/esxi.rs similarity index 90% rename from src/internals/tasks/rss/esxi.rs rename to tasks/src/rss/esxi.rs index 51a2e9a..d7d60cf 100644 --- a/src/internals/tasks/rss/esxi.rs +++ b/tasks/src/rss/esxi.rs @@ -1,17 +1,15 @@ -use { - super::{ - super::task_err, - REDIS_EXPIRY_SECS, - fetch_feed, - format_href_to_discord, - get_redis, - parse, - save_to_redis - }, - crate::Error +use super::{ + super::task_err, + REDIS_EXPIRY_SECS, + fetch_feed, + format_href_to_discord, + get_redis, + parse, + save_to_redis }; use { + kon_libs::KonResult, poise::serenity_prelude::{ CreateEmbed, CreateEmbedAuthor, @@ -21,7 +19,7 @@ use { std::io::Cursor }; -pub async fn esxi_embed() -> Result, Error> { +pub async fn esxi_embed() -> KonResult> { let redis = get_redis().await; let rkey = "RSS_ESXi"; let url = "https://esxi-patches.v-front.de/atom/ESXi-7.0.0.xml"; diff --git a/src/internals/tasks/rss/github.rs b/tasks/src/rss/github.rs similarity index 91% rename from src/internals/tasks/rss/github.rs rename to tasks/src/rss/github.rs index d5fedcb..d72f1c2 100644 --- a/src/internals/tasks/rss/github.rs +++ b/tasks/src/rss/github.rs @@ -1,20 +1,18 @@ -use { - super::{ - super::task_err, - IncidentColorMap, - REDIS_EXPIRY_SECS, - embed, - fetch_feed, - format_html_to_discord, - get_redis, - parse, - save_to_redis, - trim_old_content - }, - crate::Error +use super::{ + super::task_err, + IncidentColorMap, + REDIS_EXPIRY_SECS, + embed, + fetch_feed, + format_html_to_discord, + get_redis, + parse, + save_to_redis, + trim_old_content }; use { + kon_libs::KonResult, poise::serenity_prelude::{ CreateEmbed, Timestamp @@ -23,7 +21,7 @@ use { std::io::Cursor }; -pub async fn github_embed() -> Result, Error> { +pub async fn github_embed() -> KonResult> { let redis = get_redis().await; let rkey = "RSS_GitHub"; let rkey_content = format!("{}_Content", rkey); diff --git a/src/internals/tasks/rss/gportal.rs b/tasks/src/rss/gportal.rs similarity index 91% rename from src/internals/tasks/rss/gportal.rs rename to tasks/src/rss/gportal.rs index 72e29c1..bfe7a59 100644 --- a/src/internals/tasks/rss/gportal.rs +++ b/tasks/src/rss/gportal.rs @@ -1,20 +1,18 @@ -use { - super::{ - super::task_err, - IncidentColorMap, - REDIS_EXPIRY_SECS, - embed, - fetch_feed, - format_html_to_discord, - get_redis, - parse, - save_to_redis, - trim_old_content - }, - crate::Error +use super::{ + super::task_err, + IncidentColorMap, + REDIS_EXPIRY_SECS, + embed, + fetch_feed, + format_html_to_discord, + get_redis, + parse, + save_to_redis, + trim_old_content }; use { + kon_libs::KonResult, poise::serenity_prelude::{ CreateEmbed, Timestamp @@ -23,7 +21,7 @@ use { std::io::Cursor }; -pub async fn gportal_embed() -> Result, Error> { +pub async fn gportal_embed() -> KonResult> { let redis = get_redis().await; let rkey = "RSS_GPortal"; let rkey_content = format!("{}_Content", rkey); diff --git a/src/internals/tasks/rss/processor.rs b/tasks/src/rss/processor.rs similarity index 98% rename from src/internals/tasks/rss/processor.rs rename to tasks/src/rss/processor.rs index 06f7197..87e0bfb 100644 --- a/src/internals/tasks/rss/processor.rs +++ b/tasks/src/rss/processor.rs @@ -1,5 +1,9 @@ -use super::{ +use kon_libs::{ BINARY_PROPERTIES, + KonResult +}; + +use super::{ TASK_NAME, esxi::esxi_embed, get_redis, @@ -36,7 +40,7 @@ async fn process_embed( embed: Option, redis_key: &str, content_key: &str -) -> Result<(), crate::Error> { +) -> KonResult<()> { if let Some(embed) = embed { let redis = get_redis().await; let channel = ChannelId::new(BINARY_PROPERTIES.rss_channel); diff --git a/src/internals/tasks/rss/rust.rs b/tasks/src/rss/rust.rs similarity index 88% rename from src/internals/tasks/rss/rust.rs rename to tasks/src/rss/rust.rs index f5d54f9..bddb381 100644 --- a/src/internals/tasks/rss/rust.rs +++ b/tasks/src/rss/rust.rs @@ -1,21 +1,19 @@ -use { - super::{ - REDIS_EXPIRY_SECS, - fetch_feed, - get_redis, - parse, - save_to_redis, - task_err - }, - crate::Error +use super::{ + REDIS_EXPIRY_SECS, + fetch_feed, + get_redis, + parse, + save_to_redis, + task_err }; use { + kon_libs::KonResult, regex::Regex, std::io::Cursor }; -pub async fn rust_message() -> Result, Error> { +pub async fn rust_message() -> KonResult> { let redis = get_redis().await; let rkey = "RSS_RustBlog"; let url = "https://blog.rust-lang.org/feed.xml"; diff --git a/tokens/Cargo.toml b/tokens/Cargo.toml new file mode 100644 index 0000000..523c2f3 --- /dev/null +++ b/tokens/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "kon_tokens" +version = "0.1.0" +edition = "2024" + +[dependencies] +tokenservice-client = { version = "0.4.1", registry = "gitea" } +tokio = { workspace = true } diff --git a/tokens/src/lib.rs b/tokens/src/lib.rs new file mode 100644 index 0000000..91a6236 --- /dev/null +++ b/tokens/src/lib.rs @@ -0,0 +1,42 @@ +use { + std::{ + env::args, + error::Error, + sync::LazyLock + }, + tokenservice_client::{ + TokenService, + TokenServiceApi + }, + tokio::sync::Mutex +}; + +static TSCLIENT: LazyLock> = LazyLock::new(|| Mutex::new(TSClient::default())); + +pub struct TSClient(TokenService); + +impl Default for TSClient { + fn default() -> Self { Self::new() } +} + +impl TSClient { + pub fn new() -> Self { + let args: Vec = args().collect(); + let service = if args.len() > 1 { &args[1] } else { "kon" }; + Self(TokenService::new(service)) + } + + pub async fn get(&self) -> Result> { + match self.0.connect().await { + Ok(a) => Ok(a), + Err(e) => Err(e) + } + } +} + +pub async fn token_path() -> TokenServiceApi { + match TSCLIENT.lock().await.get().await { + Ok(a) => a, + Err(e) => panic!("TSClient[Error]: {e}") + } +}