From 8d4a002b738bb5e7df15206363dfadf4fecc4f53 Mon Sep 17 00:00:00 2001 From: Yanis Rigaudeau Date: Sat, 14 Mar 2026 19:21:56 +0100 Subject: [PATCH] lot of refactor --- Cargo.lock | 18 ++- Dockerfile | 6 +- apps/master/Cargo.toml | 5 +- apps/master/src/commands/mod.rs | 1 - apps/master/src/commands/ping.rs | 14 +- apps/master/src/commands/play.rs | 75 +++++----- apps/master/src/commands/testnats.rs | 169 ---------------------- apps/master/src/main.rs | 55 ++++--- apps/worker/Cargo.toml | 5 +- apps/worker/src/main.rs | 10 +- apps/worker/src/workers/download.rs | 25 +++- apps/worker/src/workers/play.rs | 65 ++++----- apps/worker/src/workers/search.rs | 17 ++- libs/{nats => nats-libs}/Cargo.toml | 2 +- libs/{nats => nats-libs}/src/functions.rs | 21 ++- libs/{nats => nats-libs}/src/lib.rs | 0 libs/serenity-libs/Cargo.toml | 9 ++ libs/serenity-libs/src/functions.rs | 49 +++++++ libs/serenity-libs/src/lib.rs | 1 + libs/types/src/error.rs | 17 +++ libs/types/src/jobs.rs | 4 +- libs/types/src/lib.rs | 1 + 22 files changed, 256 insertions(+), 313 deletions(-) delete mode 100644 apps/master/src/commands/testnats.rs rename libs/{nats => nats-libs}/Cargo.toml (92%) rename libs/{nats => nats-libs}/src/functions.rs (68%) rename libs/{nats => nats-libs}/src/lib.rs (100%) create mode 100644 libs/serenity-libs/Cargo.toml create mode 100644 libs/serenity-libs/src/functions.rs create mode 100644 libs/serenity-libs/src/lib.rs create mode 100644 libs/types/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index 0f740ad..838b149 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2248,13 +2248,12 @@ name = "master" version = "0.1.0" dependencies = [ "async-nats", - "nats", - "postcard", + "nats-libs", "serenity", + "serenity-libs", "tokio", "types", "url", - "uuid", ] [[package]] @@ -2356,7 +2355,7 @@ dependencies = [ ] [[package]] -name = "nats" +name = "nats-libs" version = "0.1.0" dependencies = [ "async-nats", @@ -3847,6 +3846,15 @@ dependencies = [ "url", ] +[[package]] +name = "serenity-libs" +version = "0.1.0" +dependencies = [ + "async-trait", + "serenity", + "types", +] + [[package]] name = "serenity-voice-model" version = "0.2.1" @@ -5714,8 +5722,6 @@ version = "0.1.0" dependencies = [ "async-nats", "futures", - "futures-executor", - "nats", "postcard", "rustls 0.23.37", "serenity", diff --git a/Dockerfile b/Dockerfile index c9015ac..507cf6c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,12 @@ -FROM rust:1.93.1-alpine3.23 AS builder +FROM rust:1.94.0-alpine3.23 AS builder RUN --mount=type=cache,target=/root/.cargo \ rustup component add clippy && \ rustup component add rustfmt --toolchain nightly RUN \ - cargo install cargo-sort + cargo install cargo-sort && \ + cargo install machete WORKDIR /build @@ -13,6 +14,7 @@ COPY . . RUN --mount=type=cache,target=/build/target \ cargo sort ./**/Cargo.toml --check && \ + cargo machete --with-metadata && \ cargo clippy && \ cargo +nightly fmt --check diff --git a/apps/master/Cargo.toml b/apps/master/Cargo.toml index 64ad384..73f38ea 100644 --- a/apps/master/Cargo.toml +++ b/apps/master/Cargo.toml @@ -5,8 +5,7 @@ edition = "2024" [dependencies] async-nats = { version = "0.46.0" } -nats = { path = "../../libs/nats" } -postcard = { version = "1.1.3", features = ["use-std"] } +nats-libs = { path = "../../libs/nats-libs" } serenity = { version = "0.12.5", default-features = false, features = [ "cache", "client", @@ -14,7 +13,7 @@ serenity = { version = "0.12.5", default-features = false, features = [ "gateway", "rustls_backend", ] } +serenity-libs = { path = "../../libs/serenity-libs" } tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread"] } types = { path = "../../libs/types" } url = { version = "2.5.8", features = ["serde"] } -uuid = { version = "1.22.0" } diff --git a/apps/master/src/commands/mod.rs b/apps/master/src/commands/mod.rs index 88ae699..9d5ba79 100644 --- a/apps/master/src/commands/mod.rs +++ b/apps/master/src/commands/mod.rs @@ -1,3 +1,2 @@ pub mod ping; pub mod play; -pub mod testnats; diff --git a/apps/master/src/commands/ping.rs b/apps/master/src/commands/ping.rs index 75ea7cb..81ca067 100644 --- a/apps/master/src/commands/ping.rs +++ b/apps/master/src/commands/ping.rs @@ -1,7 +1,15 @@ -use serenity::{builder::CreateCommand, model::application::ResolvedOption}; +use serenity::{ + all::{CommandInteraction, Context}, + builder::CreateCommand, +}; +use serenity_libs::functions::CustomInteraction; +use types::error::CorroError; -pub fn run(_options: &[ResolvedOption]) -> String { - "Pong!".to_string() +pub async fn run(ctx: &Context, interaction: &CommandInteraction) -> Result<(), CorroError> { + let _ = interaction + .create_text_response(ctx, "Pong!".to_string()) + .await; + Ok(()) } pub fn register() -> CreateCommand { diff --git a/apps/master/src/commands/play.rs b/apps/master/src/commands/play.rs index 3d54edd..0326db0 100644 --- a/apps/master/src/commands/play.rs +++ b/apps/master/src/commands/play.rs @@ -1,17 +1,12 @@ -use nats::functions::JobClient; +use nats_libs::functions::JobClient; use serenity::{ - all::{ - CommandInteraction, - Context, - CreateCommandOption, - CreateInteractionResponse, - CreateInteractionResponseMessage, - EditInteractionResponse, - }, + all::{CommandInteraction, Context, CreateCommandOption}, builder::CreateCommand, model::application::{CommandOptionType, ResolvedOption, ResolvedValue}, }; +use serenity_libs::functions::CustomInteraction; use types::{ + error::{CorroError, CorroErrorType}, jobs::{DownloadJob, JobsMap, JobsResponseMap, PlayJob, SearchJob}, misc::{new_uuid_v4, parse_url_or_default}, }; @@ -21,7 +16,7 @@ pub async fn run( ctx: &Context, interaction: &CommandInteraction, nats_client: &async_nats::Client, -) -> Result<(), serenity::Error> { +) -> Result<(), CorroError> { let options = interaction.data.options(); if let Some(ResolvedOption { @@ -29,15 +24,13 @@ pub async fn run( .. }) = options.first() { - interaction - .create_response( - ctx, - CreateInteractionResponse::Message( - CreateInteractionResponseMessage::new() - .content(format!("Searching: {value}...")), - ), - ) - .await?; + match interaction + .create_text_response(ctx, format!("Searching: {value}...")) + .await + { + Ok(_) => {} + Err(why) => return Err(why), + }; let url: Url; let is_url = value.starts_with("https://") || value.starts_with("http://"); @@ -52,13 +45,16 @@ pub async fn run( { Ok(resp) => match resp { JobsResponseMap::Search(resp) => resp, - _ => return Err(serenity::Error::Other("Unexpected return type")), + _ => { + return Err(CorroError { + error_type: CorroErrorType::JobError, + message: "Unexpected return type".to_string(), + }); + } }, - Err(_why) => return Err(serenity::Error::Other("send error")), + Err(why) => return Err(why), }; - println!("{:?}", &search_response); - url = search_response.song.url; } else { url = parse_url_or_default(value.to_string()); @@ -73,13 +69,16 @@ pub async fn run( { Ok(resp) => match resp { JobsResponseMap::Download(resp) => resp, - _ => return Err(serenity::Error::Other("Unexpected return type")), + _ => { + return Err(CorroError { + error_type: CorroErrorType::JobError, + message: "Unexpected return type".to_string(), + }); + } }, - Err(_why) => return Err(serenity::Error::Other("send error")), + Err(why) => return Err(why), }; - println!("{:?}", &download_response); - let guild_id = interaction.guild_id.unwrap(); let channel_id = guild_id @@ -89,7 +88,7 @@ pub async fn run( .channel_id .unwrap(); - let _ = match nats_client + match nats_client .send_job(JobsMap::Play(PlayJob { uuid: new_uuid_v4(), path: download_response.path, @@ -100,15 +99,25 @@ pub async fn run( { Ok(resp) => match resp { JobsResponseMap::Play(resp) => resp, - _ => return Err(serenity::Error::Other("Unexpected return type")), + _ => { + return Err(CorroError { + error_type: CorroErrorType::JobError, + message: "Unexpected return type".to_string(), + }); + } }, - Err(_why) => return Err(serenity::Error::Other("send error")), + Err(why) => return Err(why), }; - interaction - .edit_response(ctx, EditInteractionResponse::new().content("Playing...")) - .await?; + match interaction + .edit_text_response(ctx, "Playing...".to_string()) + .await + { + Ok(_) => {} + Err(why) => return Err(why), + }; } + Ok(()) } diff --git a/apps/master/src/commands/testnats.rs b/apps/master/src/commands/testnats.rs deleted file mode 100644 index d6f0618..0000000 --- a/apps/master/src/commands/testnats.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::path::PathBuf; - -use postcard::{from_bytes, to_stdvec}; -use serenity::{ - all::{ - CommandInteraction, - Context, - CreateCommandOption, - CreateInteractionResponse, - CreateInteractionResponseMessage, - EditInteractionResponse, - }, - builder::CreateCommand, - model::application::{CommandOptionType, ResolvedOption, ResolvedValue}, -}; -use types::{ - jobs::{DownloadJob, JobResponse, JobsResponseMap, PlayJob, SearchJob}, - misc::{new_uuid_v4, parse_url_or_default}, -}; -use url::Url; - -pub async fn run( - ctx: &Context, - interaction: &CommandInteraction, - nats_client: &async_nats::Client, -) -> Result<(), serenity::Error> { - let options = interaction.data.options(); - - if let Some(ResolvedOption { - value: ResolvedValue::String(value), - .. - }) = options.first() - { - interaction - .create_response( - ctx, - CreateInteractionResponse::Message( - CreateInteractionResponseMessage::new() - .content(format!("Searching: {value}...")), - ), - ) - .await?; - - let url: Url; - let is_url = value.starts_with("https://"); - - if !is_url { - let search_job = SearchJob { - uuid: new_uuid_v4(), - query: value.to_string(), - }; - - let response = match nats_client - .request("corro-dj.search", to_stdvec(&search_job).unwrap().into()) - .await - { - Ok(resp) => resp, - Err(_why) => return Err(serenity::Error::Other("send error")), - }; - - let search_response: JobResponse = from_bytes(&response.payload).unwrap(); - - if let Some(error) = search_response.error { - interaction - .edit_response(ctx, EditInteractionResponse::new().content(error)) - .await?; - return Err(serenity::Error::Other("Search error")); - } else if let Some(JobsResponseMap::Search(content)) = search_response.content { - url = content.song.url; - } else { - interaction - .edit_response(ctx, EditInteractionResponse::new().content("unknown error")) - .await?; - return Err(serenity::Error::Other("unknown error")); - } - } else { - url = parse_url_or_default(value.to_string()); - } - - let download_job = DownloadJob { - uuid: new_uuid_v4(), - url, - }; - - println!("job {:?}", download_job); - - let response = match nats_client - .request( - "corro-dj.download", - to_stdvec(&download_job).unwrap().into(), - ) - .await - { - Ok(resp) => resp, - Err(_why) => return Err(serenity::Error::Other("send error")), - }; - - let job_response: JobResponse = from_bytes(&response.payload).unwrap(); - - println!("response: {:?}", job_response); - - let text_response: String; - if let Some(error) = job_response.error { - text_response = error; - } else if let Some(JobsResponseMap::Download(content)) = job_response.content { - text_response = content.path.display().to_string(); - } else { - text_response = "unkown".to_string(); - } - - interaction - .edit_response(ctx, EditInteractionResponse::new().content(&text_response)) - .await?; - - let guild_id = interaction.guild_id.unwrap(); - - let channel_id = guild_id - .get_user_voice_state(&ctx.http, interaction.user.id) - .await - .unwrap() - .channel_id - .unwrap(); - - let play_job = PlayJob { - uuid: new_uuid_v4(), - path: PathBuf::from(&text_response), - guild_id: guild_id.into(), - channel_id: channel_id.into(), - }; - - println!("job {:?}", play_job); - - let _ = match nats_client - .request("corro-dj.play", to_stdvec(&play_job).unwrap().into()) - .await - { - Ok(resp) => resp, - Err(_why) => return Err(serenity::Error::Other("send error")), - }; - - interaction - .edit_response(ctx, EditInteractionResponse::new().content("playing...")) - .await?; - } else { - interaction - .create_response( - ctx, - CreateInteractionResponse::Message( - CreateInteractionResponseMessage::new() - .content("Please provide a valid string"), - ), - ) - .await?; - } - Ok(()) -} - -pub fn register() -> CreateCommand { - CreateCommand::new("testnats") - .description("Play a song") - .add_option( - CreateCommandOption::new( - CommandOptionType::String, - "song", - "Name or url of the song to play", - ) - .required(false), - ) -} diff --git a/apps/master/src/main.rs b/apps/master/src/main.rs index 8038dd6..a77f389 100644 --- a/apps/master/src/main.rs +++ b/apps/master/src/main.rs @@ -6,12 +6,13 @@ use serenity::{ Client, all::{Context, EventHandler, GatewayIntents}, async_trait, - builder::{CreateInteractionResponse, CreateInteractionResponseMessage}, model::{ application::{Command, Interaction}, gateway::Ready, }, }; +use serenity_libs::functions::CustomInteraction; +use types::error::{CorroError, CorroErrorType}; struct Handler { nats_client: async_nats::Client, @@ -21,30 +22,28 @@ struct Handler { impl EventHandler for Handler { async fn interaction_create(&self, ctx: Context, interaction: Interaction) { if let Interaction::Command(command) = interaction { - println!("Received command interaction: {command:#?}"); + println!("Received command interaction: {command:?}"); - let content = match command.data.name.as_str() { - "play" => { - commands::play::run(&ctx, &command, &self.nats_client) - .await - .unwrap(); - None - } - "ping" => Some(commands::ping::run(&command.data.options())), - "testnats" => { - commands::testnats::run(&ctx, &command, &self.nats_client) - .await - .unwrap(); - None - } - _ => Some("not implemented :(".to_string()), - }; + if let Err(why) = match command.data.name.as_str() { + "play" => commands::play::run(&ctx, &command, &self.nats_client).await, + "ping" => commands::ping::run(&ctx, &command).await, + _ => Err(CorroError { + error_type: CorroErrorType::CommandError, + message: format!("Command {} not implemented", &command.data.name), + }), + } { + println!("{:?}: {}", why.error_type, why.message); - if let Some(content) = content { - let data = CreateInteractionResponseMessage::new().content(content); - let builder = CreateInteractionResponse::Message(data); - if let Err(why) = command.create_response(&ctx.http, builder).await { - println!("Cannot respond to slash command: {why}"); + match why.error_type { + CorroErrorType::CommandError | CorroErrorType::SerenityError => {} + _ => { + let _ = command + .edit_text_response( + &ctx, + format!("{:?}: {}", why.error_type, why.message), + ) + .await; + } } } } @@ -55,15 +54,11 @@ impl EventHandler for Handler { if let Err(why) = Command::set_global_commands( &ctx.http, - vec![ - commands::ping::register(), - commands::play::register(), - commands::testnats::register(), - ], + vec![commands::ping::register(), commands::play::register()], ) .await { - println!("Client error: {why:?}"); + println!("Set commands error: {why:?}"); } } } @@ -90,6 +85,6 @@ async fn main() { // Shards will automatically attempt to reconnect, and will perform exponential backoff until // it reconnects. if let Err(why) = discord_client.start().await { - println!("Client error: {why:?}"); + println!("Client start error: {why:?}"); } } diff --git a/apps/worker/Cargo.toml b/apps/worker/Cargo.toml index 96341dc..64f564d 100644 --- a/apps/worker/Cargo.toml +++ b/apps/worker/Cargo.toml @@ -3,11 +3,12 @@ name = "worker" version = "0.1.0" edition = "2024" +[package.metadata.cargo-machete] +ignored = ["symphonia"] + [dependencies] async-nats = { version = "0.46.0" } futures = { version = "0.3.32" } -futures-executor = { version = "0.3.32" } -nats = { path = "../../libs/nats" } postcard = { version = "1.1.3", features = ["use-std"] } rustls = { version = "0.23.37", default-features = false, features = [ "aws-lc-rs", diff --git a/apps/worker/src/main.rs b/apps/worker/src/main.rs index c82d973..4dafee3 100644 --- a/apps/worker/src/main.rs +++ b/apps/worker/src/main.rs @@ -24,7 +24,9 @@ impl EventHandler for Handler { async fn ready(&self, ctx: Context, ready: Ready) { println!("{} is connected!", ready.user.name); - let voice_manager = songbird::get(&ctx).await; + let voice_manager = songbird::get(&ctx) + .await + .expect("Cannot init voice manager"); let mut subscriber = self .nats_client @@ -65,9 +67,9 @@ impl EventHandler for Handler { let response = match result { Ok(response) => response, - Err(err) => JobResponse { + Err(why) => JobResponse { content: None, - error: Some(err), + error: Some(why), }, }; @@ -115,6 +117,6 @@ async fn main() { .expect("Error creating discord client"); if let Err(why) = discord_client.start().await { - println!("Client error: {why:?}"); + println!("Client start error: {why:?}"); } } diff --git a/apps/worker/src/workers/download.rs b/apps/worker/src/workers/download.rs index ff32338..8942a26 100644 --- a/apps/worker/src/workers/download.rs +++ b/apps/worker/src/workers/download.rs @@ -1,4 +1,7 @@ -use types::jobs::{DownloadJob, DownloadResponse, JobResponse}; +use types::{ + error::{CorroError, CorroErrorType}, + jobs::{DownloadJob, DownloadResponse, JobResponse}, +}; use yt_dlp::{ Downloader, model::{AudioCodecPreference, AudioQuality}, @@ -7,12 +10,15 @@ use yt_dlp::{ pub async fn download( downloader: &Downloader, job: DownloadJob, -) -> Result, String> { - println!("job: {:?}", job); - +) -> Result, CorroError> { let video = match downloader.fetch_video_infos(job.url).await { Ok(video) => video, - Err(err) => return Err(err.to_string()), + Err(why) => { + return Err(CorroError { + error_type: CorroErrorType::YtdlpError, + message: why.to_string(), + }); + } }; let audio_path = match downloader @@ -25,11 +31,14 @@ pub async fn download( .await { Ok(path) => path, - Err(err) => return Err(err.to_string()), + Err(why) => { + return Err(CorroError { + error_type: CorroErrorType::YtdlpError, + message: why.to_string(), + }); + } }; - println!("audio_path: {:?}", &audio_path); - Ok(JobResponse { content: Some(DownloadResponse { path: audio_path.clone(), diff --git a/apps/worker/src/workers/play.rs b/apps/worker/src/workers/play.rs index e62d230..e8d47ce 100644 --- a/apps/worker/src/workers/play.rs +++ b/apps/worker/src/workers/play.rs @@ -6,46 +6,41 @@ use songbird::{ events::{Event, EventContext, EventHandler as VoiceEventHandler, TrackEvent}, input::File, }; -use types::jobs::{JobResponse, PlayJob, PlayResponse}; +use types::{ + error::CorroError, + jobs::{JobResponse, PlayJob, PlayResponse}, +}; pub async fn play( - voice_manager: &Option>, + voice_manager: &Arc, job: PlayJob, -) -> Result, String> { - println!("job: {:?}", job); - - if let Some(voice_manager) = voice_manager { - if let Ok(handler_lock) = voice_manager.join(job.guild_id, job.channel_id).await { - // Attach an event handler to see notifications of all track errors. - let mut handler = handler_lock.lock().await; - handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); - } - - let handler_lock = match voice_manager.get(job.guild_id) { - Some(handler) => handler, - None => { - return Ok(JobResponse { - content: Some(PlayResponse {}), - error: None, - }); - } - }; - +) -> Result, CorroError> { + if let Ok(handler_lock) = voice_manager.join(job.guild_id, job.channel_id).await { + // Attach an event handler to see notifications of all track errors. let mut handler = handler_lock.lock().await; - - let src = File::new(job.path).clone(); - - let track_handle = handler.play_input(src.into()); - - println!("{:?}", track_handle.get_info().await); - - Ok(JobResponse { - content: Some(PlayResponse {}), - error: None, - }) - } else { - Err("No voice_manager defined".to_string()) + handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); } + + let handler_lock = match voice_manager.get(job.guild_id) { + Some(handler) => handler, + None => { + return Ok(JobResponse { + content: Some(PlayResponse {}), + error: None, + }); + } + }; + + let mut handler = handler_lock.lock().await; + + let src = File::new(job.path).clone(); + + let _ = handler.play_input(src.into()); + + Ok(JobResponse { + content: Some(PlayResponse {}), + error: None, + }) } struct TrackErrorNotifier; diff --git a/apps/worker/src/workers/search.rs b/apps/worker/src/workers/search.rs index 5a2893f..bacc392 100644 --- a/apps/worker/src/workers/search.rs +++ b/apps/worker/src/workers/search.rs @@ -1,4 +1,5 @@ use types::{ + error::{CorroError, CorroErrorType}, jobs::{JobResponse, SearchJob, SearchResponse}, misc::parse_url_or_default, queue::YoutubeSong, @@ -8,9 +9,7 @@ use yt_dlp::Downloader; pub async fn search( downloader: &Downloader, job: SearchJob, -) -> Result, String> { - println!("job: {:?}", job); - +) -> Result, CorroError> { let result = match downloader .youtube_extractor() .search_first(&job.query) @@ -32,16 +31,20 @@ pub async fn search( }, None => JobResponse { content: None, - error: Some("url is not defined".to_string()), + error: Some(CorroError { + error_type: CorroErrorType::JobError, + message: "webpage_url is not defined".to_string(), + }), }, }, Err(why) => JobResponse { content: None, - error: Some(format!("{why}")), + error: Some(CorroError { + error_type: CorroErrorType::JobError, + message: why.to_string(), + }), }, }; - println!("reply: {:?}", result.content); - Ok(result) } diff --git a/libs/nats/Cargo.toml b/libs/nats-libs/Cargo.toml similarity index 92% rename from libs/nats/Cargo.toml rename to libs/nats-libs/Cargo.toml index a0746fa..ddfc8c1 100644 --- a/libs/nats/Cargo.toml +++ b/libs/nats-libs/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "nats" +name = "nats-libs" version = "0.1.0" edition = "2024" diff --git a/libs/nats/src/functions.rs b/libs/nats-libs/src/functions.rs similarity index 68% rename from libs/nats/src/functions.rs rename to libs/nats-libs/src/functions.rs index 511cca7..3680583 100644 --- a/libs/nats/src/functions.rs +++ b/libs/nats-libs/src/functions.rs @@ -1,16 +1,19 @@ use async_nats::Client; use async_trait::async_trait; use postcard::{from_bytes, to_stdvec}; -use types::jobs::{JobResponse, JobsMap, JobsResponseMap}; +use types::{ + error::{CorroError, CorroErrorType}, + jobs::{JobResponse, JobsMap, JobsResponseMap}, +}; #[async_trait] pub trait JobClient { - async fn send_job(&self, job: JobsMap) -> Result; + async fn send_job(&self, job: JobsMap) -> Result; } #[async_trait] impl JobClient for Client { - async fn send_job(&self, job: JobsMap) -> Result { + async fn send_job(&self, job: JobsMap) -> Result { let subject = match &job { JobsMap::Download(_job) => "download", JobsMap::Play(_job) => "play", @@ -25,8 +28,6 @@ impl JobClient for Client { .await { Ok(response) => { - println!("{:?}", &response.payload); - let parsed: JobResponse = from_bytes(&response.payload).unwrap(); if let Some(error) = parsed.error { @@ -34,10 +35,16 @@ impl JobClient for Client { } else if let Some(content) = parsed.content { Ok(content) } else { - Err("Unknown content".to_string()) + Err(CorroError { + error_type: CorroErrorType::ParseError, + message: "Unknown payload".to_owned(), + }) } } - Err(why) => Err(why.to_string()), + Err(why) => Err(CorroError { + error_type: CorroErrorType::NatsError, + message: why.to_string(), + }), } } } diff --git a/libs/nats/src/lib.rs b/libs/nats-libs/src/lib.rs similarity index 100% rename from libs/nats/src/lib.rs rename to libs/nats-libs/src/lib.rs diff --git a/libs/serenity-libs/Cargo.toml b/libs/serenity-libs/Cargo.toml new file mode 100644 index 0000000..fb15e02 --- /dev/null +++ b/libs/serenity-libs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "serenity-libs" +version = "0.1.0" +edition = "2024" + +[dependencies] +async-trait = { version = "0.1.89" } +serenity = { version = "0.12.5", default-features = false } +types = { path = "../../libs/types" } diff --git a/libs/serenity-libs/src/functions.rs b/libs/serenity-libs/src/functions.rs new file mode 100644 index 0000000..5daabc7 --- /dev/null +++ b/libs/serenity-libs/src/functions.rs @@ -0,0 +1,49 @@ +use async_trait::async_trait; +use serenity::all::{ + CommandInteraction, + Context, + CreateInteractionResponse, + CreateInteractionResponseMessage, + EditInteractionResponse, +}; +use types::error::{CorroError, CorroErrorType}; + +#[async_trait] +pub trait CustomInteraction { + async fn create_text_response(&self, ctx: &Context, content: String) -> Result<(), CorroError>; + async fn edit_text_response(&self, ctx: &Context, content: String) -> Result<(), CorroError>; +} + +#[async_trait] +impl CustomInteraction for CommandInteraction { + async fn create_text_response(&self, ctx: &Context, content: String) -> Result<(), CorroError> { + match self + .create_response( + &ctx, + CreateInteractionResponse::Message( + CreateInteractionResponseMessage::new().content(&content), + ), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => Err(CorroError { + error_type: CorroErrorType::SerenityError, + message: why.to_string(), + }), + } + } + + async fn edit_text_response(&self, ctx: &Context, content: String) -> Result<(), CorroError> { + match self + .edit_response(&ctx, EditInteractionResponse::new().content(&content)) + .await + { + Ok(_) => Ok(()), + Err(why) => Err(CorroError { + error_type: CorroErrorType::SerenityError, + message: why.to_string(), + }), + } + } +} diff --git a/libs/serenity-libs/src/lib.rs b/libs/serenity-libs/src/lib.rs new file mode 100644 index 0000000..014fff1 --- /dev/null +++ b/libs/serenity-libs/src/lib.rs @@ -0,0 +1 @@ +pub mod functions; diff --git a/libs/types/src/error.rs b/libs/types/src/error.rs new file mode 100644 index 0000000..182b42f --- /dev/null +++ b/libs/types/src/error.rs @@ -0,0 +1,17 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub enum CorroErrorType { + JobError, + ParseError, + NatsError, + YtdlpError, + CommandError, + SerenityError, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct CorroError { + pub error_type: CorroErrorType, + pub message: String, +} diff --git a/libs/types/src/jobs.rs b/libs/types/src/jobs.rs index 9148526..ff1757f 100644 --- a/libs/types/src/jobs.rs +++ b/libs/types/src/jobs.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use url::Url; use uuid::Uuid; -use crate::queue::YoutubeSong; +use crate::{error::CorroError, queue::YoutubeSong}; #[derive(Debug, Deserialize, Serialize)] pub enum JobsResponseMap { @@ -23,7 +23,7 @@ pub enum JobsMap { #[derive(Serialize, Deserialize, Debug)] pub struct JobResponse { pub content: Option, - pub error: Option, + pub error: Option, } #[derive(Serialize, Deserialize, Debug)] diff --git a/libs/types/src/lib.rs b/libs/types/src/lib.rs index 6ae21e3..c4af69f 100644 --- a/libs/types/src/lib.rs +++ b/libs/types/src/lib.rs @@ -1,3 +1,4 @@ +pub mod error; pub mod jobs; pub mod misc; pub mod queue;