Fix API and Voice

This commit is contained in:
Joey Hines 2026-05-03 18:38:06 -06:00
parent 26eabbe275
commit fa4863bfb3
Signed by: joeyahines
GPG Key ID: E99D8FB14855100E
6 changed files with 78 additions and 54 deletions

50
Cargo.lock generated
View File

@ -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",

View File

@ -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"]

View File

@ -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::<GlobalData>().unwrap();
global_data.cfg.api_addr
};
#[derive(Clone)]
struct ApiContext {
data: Arc<GlobalData>,
ctx: poise::serenity_prelude::Context
}
pub async fn web_server(data: Arc<GlobalData>, 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<Context>,
State(ctx): State<ApiContext>,
Json(payload): Json<SoundPayload>,
) -> impl IntoResponse {
let data = ctx.data.read().await;
let global_data = data.get::<GlobalData>().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
}

View File

@ -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<GlobalData>, 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 } => {

View File

@ -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<HashMap<String, PathBuf>, 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<GlobalData>,
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(_)

View File

@ -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(