diff --git a/Cargo.lock b/Cargo.lock index b4799d0..c6f1723 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1425,6 +1425,7 @@ dependencies = [ "regex", "reqwest 0.13.3", "rust-dsn-parser", + "rustls 0.23.40", "serde", "serde_json", "sha3", @@ -4375,6 +4376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", + "log", "once_cell", "ring", "rustls-pki-types", @@ -5208,9 +5210,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symphonia" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" +checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039" dependencies = [ "lazy_static", "symphonia-bundle-flac", @@ -5227,9 +5229,9 @@ dependencies = [ [[package]] name = "symphonia-bundle-flac" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" +checksum = "c91565e180aea25d9b80a910c546802526ffd0072d0b8974e3ebe59b686c9976" dependencies = [ "log", "symphonia-core", @@ -5239,9 +5241,9 @@ dependencies = [ [[package]] name = "symphonia-bundle-mp3" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" +checksum = "4872dd6bb56bf5eac799e3e957aa1981086c3e613b27e0ac23b176054f7c57ed" dependencies = [ "lazy_static", "log", @@ -5251,9 +5253,9 @@ dependencies = [ [[package]] name = "symphonia-codec-adpcm" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" +checksum = "2dddc50e2bbea4cfe027441eece77c46b9f319748605ab8f3443350129ddd07f" dependencies = [ "log", "symphonia-core", @@ -5261,9 +5263,9 @@ dependencies = [ [[package]] name = "symphonia-codec-pcm" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" +checksum = "4e89d716c01541ad3ebe7c91ce4c8d38a7cf266a3f7b2f090b108fb0cb031d95" dependencies = [ "log", "symphonia-core", @@ -5271,9 +5273,9 @@ dependencies = [ [[package]] name = "symphonia-codec-vorbis" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +checksum = "f025837c309cd69ffef572750b4a2257b59552c5399a5e49707cc5b1b85d1c73" dependencies = [ "log", "symphonia-core", @@ -5282,9 +5284,9 @@ dependencies = [ [[package]] name = "symphonia-core" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" +checksum = "ea00cc4f79b7f6bb7ff87eddc065a1066f3a43fe1875979056672c9ef948c2af" dependencies = [ "arrayvec", "bitflags 1.3.2", @@ -5295,9 +5297,9 @@ dependencies = [ [[package]] name = "symphonia-format-mkv" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f" +checksum = "122d786d2c43a49beb6f397551b4a050d8229eaa54c7ddf9ee4b98899b8742d0" dependencies = [ "lazy_static", "log", @@ -5308,9 +5310,9 @@ dependencies = [ [[package]] name = "symphonia-format-ogg" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" +checksum = "2b4955c67c1ed3aa8ae8428d04ca8397fbef6a19b2b051e73b5da8b1435639cb" dependencies = [ "log", "symphonia-core", @@ -5320,9 +5322,9 @@ dependencies = [ [[package]] name = "symphonia-format-riff" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" +checksum = "c2d7c3df0e7d94efb68401d81906eae73c02b40d5ec1a141962c592d0f11a96f" dependencies = [ "extended", "log", @@ -5332,9 +5334,9 @@ dependencies = [ [[package]] name = "symphonia-metadata" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" +checksum = "36306ff42b9ffe6e5afc99d49e121e0bd62fe79b9db7b9681d48e29fa19e6b16" dependencies = [ "encoding_rs", "lazy_static", @@ -5344,9 +5346,9 @@ dependencies = [ [[package]] name = "symphonia-utils-xiph" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +checksum = "ee27c85ab799a338446b68eec77abf42e1a6f1bb490656e121c6e27bfbab9f16" dependencies = [ "symphonia-core", "symphonia-metadata", diff --git a/Cargo.toml b/Cargo.toml index 5c10a2f..97643d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ thousands = "0.2.0" url = { version = "2.5.7", features = ["serde"] } convert_case = "0.11.0" rust-dsn-parser = { version = "1.0.0", registry = "ahines"} +rustls = "0.23.40" [dependencies.tokio] version = "1.35.1" @@ -48,5 +49,5 @@ version = "0.6.0" features = ["builtin-queue"] [dependencies.symphonia] -version = "0.5" +version = "0.5.5" features = ["mp3", "wav"] diff --git a/src/api/mod.rs b/src/api/mod.rs index aa458be..be6bf7d 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,23 +1,29 @@ +use std::sync::Arc; use crate::config::GlobalData; use crate::discord::voices::speak; use crate::models::api_key::Apikey; use axum::extract::State; use axum::{http::StatusCode, response::IntoResponse, routing::post, Json, Router}; +use log::info; use serde::Deserialize; -use serenity::prelude::Context; -pub async fn web_server(ctx: Context) { - let addr = { - let data = ctx.data.read().await; - let global_data = data.get::().unwrap(); - global_data.cfg.api_addr - }; +#[derive(Clone)] +struct ApiContext { + data: Arc, + ctx: poise::serenity_prelude::Context +} + +pub async fn web_server(data: Arc, ctx: poise::serenity_prelude::Context) { + let addr = data.cfg.api_addr; let app = Router::new() .route("/play", post(play_sound)) - .with_state(ctx); + .with_state(ApiContext { + data, + ctx + }); - println!("Serving bot api on: {}", addr); + info!("Serving bot api on: {}", addr); let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, app).await.unwrap(); } @@ -30,18 +36,17 @@ struct SoundPayload { } async fn play_sound( - State(ctx): State, + State(ctx): State, Json(payload): Json, ) -> impl IntoResponse { - let data = ctx.data.read().await; - let global_data = data.get::().unwrap(); - if let Some(api_key) = Apikey::find_key_from_secret(&global_data.db, &payload.api_key).unwrap() - { - if let Some(user_id) = api_key.user_id { + if let Some(api_key) = Apikey::find_key_from_secret(&ctx.data.db, &payload.api_key).unwrap() + && let Some(user_id) = api_key.user_id { + info!("Playing audio for {user_id}"); speak( - &ctx, - global_data.cfg.guild_id, + &ctx.ctx, + &ctx.data, + ctx.data.cfg.guild_id, user_id, &payload.voice, &payload.phrase, @@ -49,7 +54,6 @@ async fn play_sound( .await .unwrap(); } - } StatusCode::ACCEPTED } diff --git a/src/discord/mod.rs b/src/discord/mod.rs index ca6c86f..cc6832b 100644 --- a/src/discord/mod.rs +++ b/src/discord/mod.rs @@ -39,6 +39,7 @@ use songbird::SerenityInit; use std::sync::Arc; use std::time::Duration; use url::Url; +use crate::api::web_server; pub type Context<'a> = poise::Context<'a, Arc, Error>; @@ -54,15 +55,25 @@ async fn event_handler( { info!("Starting tasks handler..."); - let data = data.clone(); - let ctx = ctx.clone(); + let data_task = data.clone(); + let ctx_task = ctx.clone(); tokio::spawn(async move { - let _ = Task::create_reoccurring_tasks(&data).await.is_ok(); + let _ = Task::create_reoccurring_tasks(&data_task).await.is_ok(); loop { - let _ = Task::run_tasks(&ctx, &data).await.is_ok(); + let _ = Task::run_tasks(&ctx_task, &data_task).await.is_ok(); tokio::time::sleep(Duration::from_secs(5)).await; } }); + + let data_web = data.clone(); + let ctx_web = ctx.clone(); + + tokio::spawn(async move { + web_server( + data_web, + ctx_web + ).await; + }); } } serenity::FullEvent::Message { new_message } => { diff --git a/src/discord/voices.rs b/src/discord/voices.rs index 68b428e..b3616bf 100644 --- a/src/discord/voices.rs +++ b/src/discord/voices.rs @@ -14,6 +14,7 @@ use std::collections::HashMap; use std::fmt::{Display, Formatter}; use std::path::{Path, PathBuf}; use std::sync::Arc; +use crate::config::GlobalData; async fn get_voice_dictionary(path: &Path) -> Result, tokio::io::Error> { let mut dir = tokio::fs::read_dir(path).await?; @@ -124,15 +125,16 @@ impl EventHandler for LeaveHandler { } pub async fn speak( - ctx: Context<'_>, + ctx: &poise::serenity_prelude::Context, + data: &Arc, guild_id: GuildId, user_id: UserId, voice: &str, phrase: &str, ) -> Result<(), VoiceError> { - let _ = ctx.data().speak_lock.lock().await; + let _ = data.speak_lock.lock().await; - let voice_path = match find_voice(&ctx.data().cfg.voice_path, voice).await.unwrap() { + let voice_path = match find_voice(&data.cfg.voice_path, voice).await.unwrap() { None => return Err(VoiceError::VoiceNotFound(voice.to_string())), Some(voice_path) => voice_path, }; @@ -170,7 +172,7 @@ pub async fn speak( } let channel_id = { - let guild = ctx.cache().guild(guild_id).unwrap(); + let guild = guild_id.to_guild_cached(&ctx).unwrap(); guild .voice_states @@ -185,7 +187,7 @@ pub async fn speak( } }; - let manager = songbird::get(ctx.serenity_context()) + let manager = songbird::get(ctx) .await .expect("Songbird not initialized") .clone(); @@ -215,7 +217,7 @@ pub async fn speak( .add_event( Event::Track(TrackEvent::End), LeaveHandler { - guild: ctx.guild_id().unwrap(), + guild: guild_id, manager: manager.clone(), }, ) @@ -238,7 +240,7 @@ pub async fn say( ) -> Result<(), Error> { let guild_id = ctx.guild_id().unwrap(); - if let Err(err) = speak(ctx, guild_id, ctx.author().id, &voice, &phrase).await { + if let Err(err) = speak(ctx.serenity_context(), ctx.data(), guild_id, ctx.author().id, &voice, &phrase).await { match err { VoiceError::VoiceNotFound(_) | VoiceError::WordNotFound(_) diff --git a/src/main.rs b/src/main.rs index f5d7b52..bb89c58 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,12 +9,14 @@ mod migrations; mod models; mod music; mod user; +mod api; use crate::config::{Args, BotConfig, GlobalData}; use crate::discord::run_bot; use log::{error, info}; use magick_rust::magick_wand_genesis; use std::sync::Once; +use rustls::crypto; use structopt::StructOpt; use tracing_core::LevelFilter; use tracing_subscriber::EnvFilter; @@ -25,6 +27,8 @@ static START: Once = Once::new(); #[tokio::main] async fn main() { + crypto::aws_lc_rs::default_provider().install_default().expect("Unable to setup default Rustls provider"); + let args: Args = Args::from_args(); tracing_subscriber::fmt() .with_env_filter(