From c67224c11ada13489b61713df404951157dfcdeb Mon Sep 17 00:00:00 2001 From: Peter Grace Date: Fri, 12 May 2023 19:22:40 +0000 Subject: [PATCH 1/4] so far --- Cargo.lock | 262 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 7 ++ src/controllers/mod.rs | 7 ++ src/main.rs | 1 + src/models/handler.rs | 18 ++- 5 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 src/controllers/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 94d7ea9..ed93fe5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -66,6 +77,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + [[package]] name = "async-stream" version = "0.3.5" @@ -115,12 +132,54 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "attohttpc" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fcf00bc6d5abb29b5f97e3c61a90b6d3caa12f3faf897d4a3e3607c050a35a7" +dependencies = [ + "http", + "log", + "rustls", + "serde", + "serde_json", + "url", + "webpki", + "webpki-roots", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "aws-creds" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3776743bb68d4ad02ba30ba8f64373f1be4e082fe47651767171ce75bb2f6cf5" +dependencies = [ + "attohttpc", + "dirs", + "log", + "quick-xml", + "rust-ini", + "serde", + "thiserror", + "time 0.3.20", + "url", +] + +[[package]] +name = "aws-region" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056557a61427d0e5ba29dd931031c8ffed4ee7a550e7cd55692a9d8deb0a9dba" +dependencies = [ + "thiserror", +] + [[package]] name = "base64" version = "0.13.1" @@ -137,6 +196,7 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" name = "billyjoule" version = "0.4.0" dependencies = [ + "anyhow", "async-stream", "chrono", "clap", @@ -144,6 +204,7 @@ dependencies = [ "duration-string", "futures", "human-duration", + "rust-s3", "serenity", "tokio", "tracing", @@ -380,8 +441,35 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", ] +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + [[package]] name = "dotenv" version = "0.15.0" @@ -583,6 +671,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "heck" @@ -605,6 +696,21 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "0.2.9" @@ -822,6 +928,23 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "maybe-async" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memchr" version = "2.5.0" @@ -844,6 +967,15 @@ dependencies = [ "unicase", ] +[[package]] +name = "minidom" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9ce45d459e358790a285e7609ff5ae4cfab88b75f237e8838e62029dda397b" +dependencies = [ + "rxml", +] + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -919,6 +1051,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list", + "hashbrown", +] + [[package]] name = "overload" version = "0.1.1" @@ -981,6 +1123,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" version = "1.0.26" @@ -1029,6 +1181,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + [[package]] name = "reqwest" version = "0.11.16" @@ -1086,6 +1249,49 @@ dependencies = [ "winapi", ] +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rust-s3" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b2ac5ff6acfbe74226fa701b5ef793aaa054055c13ebb7060ad36942956e027" +dependencies = [ + "async-trait", + "aws-creds", + "aws-region", + "base64 0.13.1", + "bytes", + "cfg-if", + "futures", + "hex", + "hmac", + "http", + "log", + "maybe-async", + "md5", + "minidom", + "percent-encoding", + "quick-xml", + "reqwest", + "serde", + "serde_derive", + "sha2", + "thiserror", + "time 0.3.20", + "tokio", + "tokio-stream", + "url", +] + [[package]] name = "rustix" version = "0.37.11" @@ -1121,6 +1327,25 @@ dependencies = [ "base64 0.21.0", ] +[[package]] +name = "rxml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a071866b8c681dc2cfffa77184adc32b57b0caad4e620b6292609703bceb804" +dependencies = [ + "bytes", + "pin-project-lite", + "rxml_validation", + "smartstring", + "tokio", +] + +[[package]] +name = "rxml_validation" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53bc79743f9a66c2fb1f951cd83735f275d46bfe466259fbc5897bb60a0d00ee" + [[package]] name = "ryu" version = "1.0.13" @@ -1248,6 +1473,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -1272,6 +1508,15 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "smartstring" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e714dff2b33f2321fdcd475b71cec79781a692d846f37f415fb395a1d2bcd48e" +dependencies = [ + "static_assertions", +] + [[package]] name = "socket2" version = "0.4.9" @@ -1300,6 +1545,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.109" @@ -1454,6 +1705,17 @@ dependencies = [ "webpki", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.7" diff --git a/Cargo.toml b/Cargo.toml index 964b64c..cd7a003 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0.71" async-stream = "0.3.5" chrono = "0.4.24" clap = { version = "4.2.2", features = ["derive","env"] } @@ -13,7 +14,13 @@ dotenv = "0.15.0" duration-string = "0.3.0" futures = "0.3.28" human-duration = "0.1.0" + serenity = "0.11.5" tokio = { version = "1.27.0", features = ["tracing", "macros", "rt-multi-thread"] } tracing = "0.1.37" tracing-subscriber = "0.3.16" + +[dependencies.rust-s3] +version ="0.33.0" +default_features = false +features = ["fail-on-err", "futures", "minidom", "reqwest", "tags", "tokio", "tokio-rustls-tls", "tokio-stream", "with-tokio"] diff --git a/src/controllers/mod.rs b/src/controllers/mod.rs new file mode 100644 index 0000000..0a67199 --- /dev/null +++ b/src/controllers/mod.rs @@ -0,0 +1,7 @@ +use anyhow::{bail, Result}; +use tracing::debug; + +pub(crate) async fn upload_emoji(message: &String) -> Result<()> { + debug!("{message}"); + bail!("Not implemented yet."); +} diff --git a/src/main.rs b/src/main.rs index 5335f1d..3e4f2db 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use models::handler::GENERAL_GROUP; use crate::models::sweeper::{run_sweeper, StatsReceiver, Sweeper}; +mod controllers; mod models; #[derive(Debug, Parser)] diff --git a/src/models/handler.rs b/src/models/handler.rs index fd333ca..e3edb52 100644 --- a/src/models/handler.rs +++ b/src/models/handler.rs @@ -1,3 +1,4 @@ +use crate::controllers::upload_emoji; use crate::models::sweeper::{Stats, StatsReceiver}; use chrono::Utc; use human_duration::human_duration; @@ -136,7 +137,7 @@ async fn get_stats(ctx: &Context) -> Option { // command groups #[group] -#[commands(ping, version)] +#[commands(ping, import_emoji, version)] struct General; #[command] @@ -144,6 +145,21 @@ async fn ping(ctx: &Context, msg: &Message) -> CommandResult { msg.reply(ctx, "Pong!").await?; Ok(()) } + +#[command] +async fn import_emoji(ctx: &Context, msg: &Message) -> CommandResult { + match upload_emoji(&msg.content).await { + Ok(_) => { + msg.reply(ctx, format!("response-goes-here")).await?; + Ok(()) + } + Err(e) => { + error!("couldn't upload emoji for {}: {}", msg.content, e); + Ok(()) + } + } +} + #[command] async fn version(ctx: &Context, msg: &Message) -> CommandResult { msg.reply( From c4941de7da5ab6b31343020327864c0a25fa8c10 Mon Sep 17 00:00:00 2001 From: Peter Grace Date: Sat, 13 May 2023 02:25:49 +0000 Subject: [PATCH 2/4] emoji adding --- Cargo.lock | 85 +++++++++++++-- Cargo.toml | 9 +- billyjoule.env.sample | 4 + src/controllers/mod.rs | 31 +++++- src/models/handler.rs | 232 ++++++++++++++++++++++++++++++++--------- 5 files changed, 304 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c413fa..7504a30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,6 +148,22 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "attohttpc" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +dependencies = [ + "http", + "log", + "rustls", + "serde", + "serde_json", + "url", + "webpki", + "webpki-roots", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -160,10 +176,27 @@ version = "0.34.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3776743bb68d4ad02ba30ba8f64373f1be4e082fe47651767171ce75bb2f6cf5" dependencies = [ - "attohttpc", - "dirs", + "attohttpc 0.22.0", + "dirs 4.0.0", "log", - "quick-xml", + "quick-xml 0.26.0", + "rust-ini", + "serde", + "thiserror", + "time 0.3.20", + "url", +] + +[[package]] +name = "aws-creds" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01eb8a458c003bd8fe37badba2d8a5a3839748b6ade5cc2d92c2c6b9c6d5a437" +dependencies = [ + "attohttpc 0.24.1", + "dirs 5.0.1", + "log", + "quick-xml 0.28.2", "rust-ini", "serde", "thiserror", @@ -198,6 +231,9 @@ version = "0.5.0" dependencies = [ "anyhow", "async-stream", + "aws-creds 0.35.0", + "aws-region", + "base64 0.21.0", "chrono", "clap", "dotenv", @@ -450,7 +486,16 @@ version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "dirs-sys", + "dirs-sys 0.3.7", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys 0.4.1", ] [[package]] @@ -464,6 +509,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dlv-list" version = "0.3.0" @@ -1042,6 +1099,12 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-float" version = "2.10.0" @@ -1133,6 +1196,16 @@ dependencies = [ "serde", ] +[[package]] +name = "quick-xml" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" version = "1.0.26" @@ -1266,7 +1339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b2ac5ff6acfbe74226fa701b5ef793aaa054055c13ebb7060ad36942956e027" dependencies = [ "async-trait", - "aws-creds", + "aws-creds 0.34.1", "aws-region", "base64 0.13.1", "bytes", @@ -1280,7 +1353,7 @@ dependencies = [ "md5", "minidom", "percent-encoding", - "quick-xml", + "quick-xml 0.26.0", "reqwest", "serde", "serde_derive", diff --git a/Cargo.toml b/Cargo.toml index 52721ee..94deeda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" [dependencies] anyhow = "1.0.71" async-stream = "0.3.5" +aws-region = "0.25.3" +base64 = "0.21.0" chrono = "0.4.24" clap = { version = "4.2.2", features = ["derive","env"] } dotenv = "0.15.0" @@ -22,5 +24,10 @@ tracing-subscriber = "0.3.16" [dependencies.rust-s3] version ="0.33.0" -default_features = false +default-features = false features = ["fail-on-err", "futures", "minidom", "reqwest", "tags", "tokio", "tokio-rustls-tls", "tokio-stream", "with-tokio"] + +[dependencies.aws-creds] +version = "0.35.0" +default-features = false +features = [ "attohttpc", "http-credentials", "rustls-tls" ] diff --git a/billyjoule.env.sample b/billyjoule.env.sample index 2850a98..f87e0d0 100644 --- a/billyjoule.env.sample +++ b/billyjoule.env.sample @@ -1,2 +1,6 @@ DISCORD_TOKEN=foobar LOG_CHANNEL_ID=-1234568990 +AWS_ACCESS_KEY_ID=yourkey +AWS_SECRET_ACCESS_KEY=yoursecret +EMOJI_S3_ENDPOINT=minio-url +EMOJI_S3_BUCKET=emoji diff --git a/src/controllers/mod.rs b/src/controllers/mod.rs index 0a67199..f407fc1 100644 --- a/src/controllers/mod.rs +++ b/src/controllers/mod.rs @@ -1,7 +1,36 @@ use anyhow::{bail, Result}; +use s3::creds::Credentials; +use s3::error::S3Error; +use s3::{Bucket, Region}; +use serenity::model::guild::Guild; use tracing::debug; pub(crate) async fn upload_emoji(message: &String) -> Result<()> { debug!("{message}"); - bail!("Not implemented yet."); + let args: Vec<&str> = message.split(" ").collect(); + debug!("emoji: {}", args[1]); + let bucket = Bucket::new( + "emoji", + Region::Custom { + region: "us-east-1".to_owned(), + endpoint: "https://s3.vsix.me:9000".to_owned(), + }, + Credentials::default()?, + )? + .with_path_style(); + let file_list = match bucket + .list(format! {"{}/", args[1]}, Some("/".to_owned())) + .await + { + Ok(s) => s, + Err(e) => { + bail!("{}", e); + } + }; + let link = format!( + "https://s3.vsix.me:9000/emoji/{}", + file_list[0].contents[0].key + ); + debug!("{link}"); + bail!("not implemented yet"); } diff --git a/src/models/handler.rs b/src/models/handler.rs index e3edb52..d527328 100644 --- a/src/models/handler.rs +++ b/src/models/handler.rs @@ -3,8 +3,13 @@ use crate::models::sweeper::{Stats, StatsReceiver}; use chrono::Utc; use human_duration::human_duration; use serenity::async_trait; +use serenity::builder::CreateApplicationCommandOption; +use serenity::builder::CreateApplicationCommands; use serenity::framework::standard::macros::{command, group}; use serenity::framework::standard::CommandResult; +use serenity::model::application::interaction::application_command::{ + ApplicationCommandInteraction, CommandDataOption, +}; use serenity::model::application::interaction::Interaction; use serenity::model::application::interaction::Interaction::ApplicationCommand; use serenity::model::channel::Message; @@ -12,10 +17,23 @@ use serenity::model::gateway::Ready; use serenity::model::id::{ChannelId, GuildId}; use serenity::model::prelude::interaction::InteractionResponseType; use serenity::prelude::*; +use std::env; + +use anyhow::{bail, Result}; +use base64::prelude::*; +use s3::creds::Credentials; +use s3::{Bucket, Region}; +use serenity::model::prelude::command::{CommandOption, CommandOptionType}; use serenity::utils::MessageBuilder; use tokio::sync::mpsc; use tracing::{debug, error, info}; +const STATS_COMMAND: &str = "stats"; +const STATS_DESCRIPTION: &str = "show stats about the bot"; + +const EMOJI_COMMAND: &str = "import-emoji"; +const EMOJI_DESCRIPTION: &str = "Import emojis"; + // event handler pub struct Handler { guild_id: GuildId, @@ -55,14 +73,27 @@ impl EventHandler for Handler { env!("GIT_HASH") )) .build(); - channel.say(&ctx.http, init_message).await; + //channel.say(&ctx.http, init_message).await; }; // Configure stats command. self.guild_id .set_application_commands(&ctx.http, |builder| { - builder.create_application_command(|command| { - command.name("stats").description("Get sweeper stats") - }) + builder + .create_application_command(|command| { + command.name(STATS_COMMAND).description(STATS_DESCRIPTION) + }) + .create_application_command(|command| { + command + .name(EMOJI_COMMAND) + .description(EMOJI_DESCRIPTION) + .create_option(|option| { + option + .name("emoji") + .kind(CommandOptionType::String) + .required(true) + .description("Name of emoji to import") + }) + }) }) .await .expect("failed to create app commands"); @@ -73,54 +104,14 @@ impl EventHandler for Handler { .await .expect("failed to send start signal"); } - async fn interaction_create(&self, ctx: Context, interaction: Interaction) { if let ApplicationCommand(command) = interaction { - if command.data.name != "stats" { - debug!(command = command.data.name, "Received unknown command."); - return; - } - - let stats = match get_stats(&ctx).await { - None => { - error!("Stats don't exist, but they should."); + match command.data.name.as_str() { + STATS_COMMAND => do_stats(&ctx, command).await, + EMOJI_COMMAND => do_emoji(&ctx, command).await, + _ => { return; } - Some(stats) => stats, - }; - - if let Err(error) = command - .create_interaction_response(&ctx.http, |resp| { - resp.kind(InteractionResponseType::ChannelMessageWithSource) - .interaction_response_data(|message| { - let uptime = (Utc::now() - stats.started) - .to_std() - .expect("Duration should be in range"); - - message - .content(":wave: Hey there, here are some sweeper stats") - .embed(|embed| { - embed - .field("Version", env!("CARGO_PKG_VERSION"), false) - .field("GitHash", env!("GIT_HASH"), false) - .field("Uptime", human_duration(&uptime), false) - .field("Runs", format!("Ran {} times", stats.runs), false) - .field( - "Last Run", - format!("Cleaned up {} messages.", stats.last_run), - false, - ) - .field( - "All Runs", - format!("Cleaned up {} messages.", stats.all_runs), - false, - ) - }) - }) - }) - .await - { - error!(error = %error, "Failed to respond to status command."); } } } @@ -134,6 +125,147 @@ async fn get_stats(ctx: &Context) -> Option { .map(|sr| sr.borrow().clone()) } +async fn do_stats(ctx: &Context, command: ApplicationCommandInteraction) { + let stats = match get_stats(&ctx).await { + None => { + error!("Stats don't exist, but they should."); + return; + } + Some(stats) => stats, + }; + + if let Err(error) = command + .create_interaction_response(&ctx.http, |resp| { + resp.kind(InteractionResponseType::ChannelMessageWithSource) + .interaction_response_data(|message| { + let uptime = (Utc::now() - stats.started) + .to_std() + .expect("Duration should be in range"); + + message + .content(":wave: Hey there, here are some sweeper stats") + .embed(|embed| { + embed + .field("Version", env!("CARGO_PKG_VERSION"), false) + .field("GitHash", env!("GIT_HASH"), false) + .field("Uptime", human_duration(&uptime), false) + .field("Runs", format!("Ran {} times", stats.runs), false) + .field( + "Last Run", + format!("Cleaned up {} messages.", stats.last_run), + false, + ) + .field( + "All Runs", + format!("Cleaned up {} messages.", stats.all_runs), + false, + ) + }) + }) + }) + .await + { + error!(error = %error, "Failed to respond to status command."); + } +} + +async fn do_emoji(ctx: &Context, command: ApplicationCommandInteraction) { + let guild = match command.guild_id { + Some(g) => g, + None => { + error!("No server associated with emoji invocation...?"); + return; + } + }; + let emoji_option: Vec<&CommandDataOption> = command + .data + .options + .iter() + .filter(|opt| opt.name == "emoji") + .collect(); + let emoji_name = match &emoji_option[0].value { + Some(s) => s, + None => { + error!("Did not receive an emoji name."); + return; + } + }; + + let s3_endpoint = env::var("EMOJI_S3_ENDPOINT").ok(); + let s3_bucket = env::var("EMOJI_S3_BUCKET").ok(); + if s3_endpoint.is_none() { + error!("need an s3 endpoint for emojis"); + return; + } + if s3_bucket.is_none() { + error!("need a bucket name for emojis"); + return; + } + + let bucket = Bucket::new( + &s3_bucket.unwrap(), + Region::Custom { + region: "us-east-1".to_owned(), + endpoint: s3_endpoint.unwrap(), + }, + Credentials::default().unwrap(), + ) + .unwrap() + .with_path_style(); + + let file_list = match bucket + .list( + format!("{}/", emoji_name.as_str().unwrap()), + Some("/".to_owned()), + ) + .await + { + Ok(s) => s, + Err(e) => { + error!("{}", e); + return; + } + }; + + let image_data = match bucket.get_object(&file_list[0].contents[0].key).await { + Ok(rs) => rs, + Err(e) => { + error!("Could not retrieve image from s3 bucket"); + return; + } + }; + + let image_b64 = base64::encode(image_data.as_slice()); + let image_str = format!("data:image/png;base64,{}", image_b64); + let emoji_name_sanitized = emoji_name.as_str().unwrap().replace("-", "_"); + match guild + .create_emoji(&ctx.http, &emoji_name_sanitized, &image_str) + .await + { + Ok(t) => { + if let Err(e) = command + .create_interaction_response(&ctx.http, |resp| { + resp.kind(InteractionResponseType::ChannelMessageWithSource) + .interaction_response_data(|message| { + message.content(format!( + "Emoji :{}: added to server.", + &emoji_name_sanitized + )) + }) + }) + .await + { + error!("Unable to send response to command: {}", e); + return; + } + } + Err(e) => { + error!("Could not add emoji: {}", e); + return; + } + } +} + // command groups #[group] @@ -154,7 +286,9 @@ async fn import_emoji(ctx: &Context, msg: &Message) -> CommandResult { Ok(()) } Err(e) => { - error!("couldn't upload emoji for {}: {}", msg.content, e); + let content = format!("couldn't upload emoji for {}: {}", msg.content, e); + error!("{content}"); + //msg.reply(ctx, &content).await?; Ok(()) } } From 68f1083206cbe33340a26c198bf3009a35f5dd13 Mon Sep 17 00:00:00 2001 From: Peter Grace Date: Sat, 13 May 2023 02:32:08 +0000 Subject: [PATCH 3/4] remove the dot command for import-emoji, it would not work as well as the slash command --- src/controllers/mod.rs | 36 ------------------------------------ src/main.rs | 1 - src/models/handler.rs | 19 +------------------ 3 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 src/controllers/mod.rs diff --git a/src/controllers/mod.rs b/src/controllers/mod.rs deleted file mode 100644 index f407fc1..0000000 --- a/src/controllers/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -use anyhow::{bail, Result}; -use s3::creds::Credentials; -use s3::error::S3Error; -use s3::{Bucket, Region}; -use serenity::model::guild::Guild; -use tracing::debug; - -pub(crate) async fn upload_emoji(message: &String) -> Result<()> { - debug!("{message}"); - let args: Vec<&str> = message.split(" ").collect(); - debug!("emoji: {}", args[1]); - let bucket = Bucket::new( - "emoji", - Region::Custom { - region: "us-east-1".to_owned(), - endpoint: "https://s3.vsix.me:9000".to_owned(), - }, - Credentials::default()?, - )? - .with_path_style(); - let file_list = match bucket - .list(format! {"{}/", args[1]}, Some("/".to_owned())) - .await - { - Ok(s) => s, - Err(e) => { - bail!("{}", e); - } - }; - let link = format!( - "https://s3.vsix.me:9000/emoji/{}", - file_list[0].contents[0].key - ); - debug!("{link}"); - bail!("not implemented yet"); -} diff --git a/src/main.rs b/src/main.rs index 3e4f2db..5335f1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ use models::handler::GENERAL_GROUP; use crate::models::sweeper::{run_sweeper, StatsReceiver, Sweeper}; -mod controllers; mod models; #[derive(Debug, Parser)] diff --git a/src/models/handler.rs b/src/models/handler.rs index d527328..6ce7181 100644 --- a/src/models/handler.rs +++ b/src/models/handler.rs @@ -1,4 +1,3 @@ -use crate::controllers::upload_emoji; use crate::models::sweeper::{Stats, StatsReceiver}; use chrono::Utc; use human_duration::human_duration; @@ -269,7 +268,7 @@ async fn do_emoji(ctx: &Context, command: ApplicationCommandInteraction) { // command groups #[group] -#[commands(ping, import_emoji, version)] +#[commands(ping, version)] struct General; #[command] @@ -278,22 +277,6 @@ async fn ping(ctx: &Context, msg: &Message) -> CommandResult { Ok(()) } -#[command] -async fn import_emoji(ctx: &Context, msg: &Message) -> CommandResult { - match upload_emoji(&msg.content).await { - Ok(_) => { - msg.reply(ctx, format!("response-goes-here")).await?; - Ok(()) - } - Err(e) => { - let content = format!("couldn't upload emoji for {}: {}", msg.content, e); - error!("{content}"); - //msg.reply(ctx, &content).await?; - Ok(()) - } - } -} - #[command] async fn version(ctx: &Context, msg: &Message) -> CommandResult { msg.reply( From bd2c39500f7c4bfa59c8dcc0a0752fbaeb362b3e Mon Sep 17 00:00:00 2001 From: Peter Grace Date: Sat, 13 May 2023 02:40:29 +0000 Subject: [PATCH 4/4] say status message once again --- src/models/handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/handler.rs b/src/models/handler.rs index 6ce7181..4efbf75 100644 --- a/src/models/handler.rs +++ b/src/models/handler.rs @@ -72,7 +72,7 @@ impl EventHandler for Handler { env!("GIT_HASH") )) .build(); - //channel.say(&ctx.http, init_message).await; + channel.say(&ctx.http, init_message).await; }; // Configure stats command. self.guild_id