diff --git a/Cargo.lock b/Cargo.lock index 8a429a9..c7e5844 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,6 +223,21 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "flate2" version = "1.0.27" @@ -364,7 +379,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -467,7 +482,10 @@ version = "0.1.0" dependencies = [ "anyhow", "dotenvy", + "envy", "once_cell", + "serde", + "serde_yaml", "serenity", "tokio", "tracing", @@ -494,6 +512,16 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.1", +] + [[package]] name = "ipnet" version = "2.8.0" @@ -930,6 +958,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +dependencies = [ + "indexmap 2.0.2", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "serenity" version = "0.11.6" @@ -1323,6 +1364,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" + [[package]] name = "untrusted" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index a4bd92d..3d27e74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,9 @@ dotenvy = { version = "0.15.7" } once_cell = { version = "1.18.0" } tracing = { version = "0.1.37" } tracing-subscriber = { version = "0.3.17" } +serde = { version = "1.0.188", features = ["derive"] } +serde_yaml = { version = "0.9.25" } +envy = { version = "0.4.2" } [dependencies.serenity] version = "0.11.6" diff --git a/assets/config.yaml b/assets/config.yaml new file mode 100644 index 0000000..3cd9666 --- /dev/null +++ b/assets/config.yaml @@ -0,0 +1 @@ +reactions: ["๐Ÿ‘", "๐Ÿ‘Ž"] diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..6b2ee4d --- /dev/null +++ b/src/config.rs @@ -0,0 +1,36 @@ +use anyhow::Context; +use once_cell::sync::OnceCell; +use serde::{Deserialize, Serialize}; +use std::fs::File; +use std::io::BufReader; +use tracing::log::info; + +#[derive(Default, Deserialize, Debug)] +pub struct IdeaReactionConfig { + pub reactions: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct IdeaReactionEnv { + pub discord_api_token: String, + pub target_channel_id: u64, + pub target_guild_id: u64, + pub target_webhook_id: u64, +} + +pub fn load_config() -> anyhow::Result { + let config: IdeaReactionConfig = serde_yaml::from_reader(BufReader::new( + File::open("./assets/config.yaml").context("Failed to open config file")?, + )) + .context("Failed to parse config file")?; + + // TODO: ใ“ใฎใƒใ‚งใƒƒใ‚ฏใ‚’ๅŽณๆ ผๅŒ–ใ™ใ‚‹ + if config.reactions.is_empty() { + panic!("No reactions found in config file"); + } + + info!("Loaded config: {:?}", config.reactions); + Ok(config) +} + +pub static ENV_CONFIG: OnceCell = OnceCell::new(); diff --git a/src/events.rs b/src/events.rs index c33b24c..d2048e9 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,6 +1,8 @@ +use crate::config::ENV_CONFIG; use serenity::async_trait; use serenity::client::Context; -use serenity::model::gateway::Ready; +use serenity::model::gateway::{Activity, Ready}; +use serenity::model::prelude::{ChannelId, GuildId, Webhook}; use serenity::prelude::EventHandler; use tracing::log::info; @@ -9,6 +11,37 @@ pub struct EvHandler; #[async_trait] impl EventHandler for EvHandler { async fn ready(&self, ctx: Context, bot: Ready) { - info!("{} is connected!", bot.user.name); + let env_config = ENV_CONFIG.get().unwrap(); + info!( + "{name}({id}) is connected!", + name = bot.user.name, + id = bot.user.id + ); + + let guild = GuildId(env_config.target_guild_id); + let channel = guild.channels(&ctx.http).await.unwrap(); + + match channel.get(&ChannelId(env_config.target_channel_id)) { + Some(channel) => { + info!("Watching channel: {}", channel.name); + ctx.set_activity(Activity::watching(&channel.name)).await; + + let webhook = channel.webhooks(&ctx.http).await.unwrap(); + let target_webhook = webhook + .iter() + .find(|webhook| webhook.id == env_config.target_webhook_id); + match target_webhook { + Some(w) => { + info!("Watching webhook: {}", w.name.clone().unwrap()); + } + None => { + panic!("Target webhook is not found"); + } + } + } + None => { + panic!("Target channel is not found"); + } + } } } diff --git a/src/main.rs b/src/main.rs index 45680d9..e69f95e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,10 @@ use crate::client::discord::create_discord_client; +use crate::config::{load_config, IdeaReactionEnv, ENV_CONFIG}; use dotenvy::dotenv; use std::env; mod client; +mod config; mod events; #[tokio::main] @@ -10,8 +12,13 @@ async fn main() -> anyhow::Result<()> { dotenv().ok(); tracing_subscriber::fmt().compact().init(); - let token = env::var("DISCORD_API_TOKEN").expect("Expected a token in the environment"); - let mut client = create_discord_client(&token).await?; + ENV_CONFIG + .set(envy::from_env::().expect("Failed to load environment variables")) + .unwrap(); + + let mut client = create_discord_client(&ENV_CONFIG.get().unwrap().discord_api_token).await?; + + load_config()?; if let Err(why) = client.start().await { println!("Failed run discord client: {:?}", why);