From 8ed01f20499622959f19acb404a8ac1940e65528 Mon Sep 17 00:00:00 2001 From: Yanis Rigaudeau Date: Thu, 12 Mar 2026 01:03:44 +0100 Subject: [PATCH] wip --- Cargo.lock | 9 ++++ apps/master/Cargo.toml | 1 + apps/master/src/commands/mod.rs | 1 + apps/master/src/commands/play.rs | 65 ++++++++++++++++++++++++++++ apps/master/src/commands/testnats.rs | 12 ++--- apps/master/src/main.rs | 19 +++++++- apps/worker/src/workers/search.rs | 19 ++++++-- libs/nats/Cargo.toml | 7 +++ libs/nats/src/functions.rs | 1 + libs/nats/src/lib.rs | 1 + libs/types/Cargo.toml | 1 + libs/types/src/jobs.rs | 26 ++++++++--- libs/types/src/lib.rs | 1 + libs/types/src/misc.rs | 5 +++ libs/types/src/queue.rs | 27 ++++++++++++ 15 files changed, 180 insertions(+), 15 deletions(-) create mode 100644 apps/master/src/commands/play.rs create mode 100644 libs/nats/Cargo.toml create mode 100644 libs/nats/src/functions.rs create mode 100644 libs/nats/src/lib.rs create mode 100644 libs/types/src/queue.rs diff --git a/Cargo.lock b/Cargo.lock index 6e63360..84bdce7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2252,6 +2252,7 @@ dependencies = [ "serenity", "tokio", "types", + "url", "uuid", ] @@ -2353,6 +2354,13 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "nats" +version = "0.1.0" +dependencies = [ + "async-nats", +] + [[package]] name = "nkeys" version = "0.4.5" @@ -4908,6 +4916,7 @@ name = "types" version = "0.1.0" dependencies = [ "serde", + "url", "uuid", ] diff --git a/apps/master/Cargo.toml b/apps/master/Cargo.toml index 0142a59..bc97ec6 100644 --- a/apps/master/Cargo.toml +++ b/apps/master/Cargo.toml @@ -15,4 +15,5 @@ serenity = { version = "0.12.5", default-features = false, features = [ ] } 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 f6ddc1f..88ae699 100644 --- a/apps/master/src/commands/mod.rs +++ b/apps/master/src/commands/mod.rs @@ -1,2 +1,3 @@ pub mod ping; +pub mod play; pub mod testnats; diff --git a/apps/master/src/commands/play.rs b/apps/master/src/commands/play.rs new file mode 100644 index 0000000..fab911a --- /dev/null +++ b/apps/master/src/commands/play.rs @@ -0,0 +1,65 @@ +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, Jobs, 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() + { + let url: Url; + let is_url = value.starts_with("https://") || value.starts_with("http://"); + + if !is_url { + let response = match nats_client + .request( + "corro-dj.search", + to_stdvec(&SearchJob { + uuid: new_uuid_v4(), + query: value.to_string(), + }) + .unwrap() + .into(), + ) + .await + { + Ok(resp) => resp, + Err(_why) => return Err(serenity::Error::Other("send error")), + }; + } + } + Ok(()) +} + +pub fn register() -> CreateCommand { + CreateCommand::new("play") + .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/commands/testnats.rs b/apps/master/src/commands/testnats.rs index 7e44af7..be21bd8 100644 --- a/apps/master/src/commands/testnats.rs +++ b/apps/master/src/commands/testnats.rs @@ -15,8 +15,9 @@ use serenity::{ }; use types::{ jobs::{DownloadJob, JobResponse, Jobs, PlayJob, SearchJob}, - misc::new_uuid_v4, + misc::{new_uuid_v4, parse_url_or_default}, }; +use url::Url; pub async fn run( ctx: &Context, @@ -40,8 +41,9 @@ pub async fn run( ) .await?; - let url: String; + let url: Url; let is_url = value.starts_with("https://"); + if !is_url { let search_job = SearchJob { uuid: new_uuid_v4(), @@ -64,7 +66,7 @@ pub async fn run( .await?; return Err(serenity::Error::Other("Search error")); } else if let Some(Jobs::Search(content)) = search_response.content { - url = content.url; + url = content.song.url; } else { interaction .edit_response(ctx, EditInteractionResponse::new().content("unknown error")) @@ -72,7 +74,7 @@ pub async fn run( return Err(serenity::Error::Other("unknown error")); } } else { - url = value.to_string(); + url = parse_url_or_default(value.to_string()); } let download_job = DownloadJob { @@ -154,7 +156,7 @@ pub async fn run( } pub fn register() -> CreateCommand { - CreateCommand::new("play") + CreateCommand::new("testnats") .description("Play a song") .add_option( CreateCommandOption::new( diff --git a/apps/master/src/main.rs b/apps/master/src/main.rs index c251d10..1295e30 100644 --- a/apps/master/src/main.rs +++ b/apps/master/src/main.rs @@ -2,6 +2,7 @@ mod commands; use std::env; +use async_nats::Client; use serenity::{ Client, all::{Context, EventHandler, GatewayIntents}, @@ -25,12 +26,18 @@ impl EventHandler for Handler { let content = match command.data.name.as_str() { "play" => { - commands::testnats::run(&ctx, &command, &self.nats_client) + 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()), }; @@ -49,7 +56,11 @@ impl EventHandler for Handler { if let Err(why) = Command::set_global_commands( &ctx.http, - vec![commands::ping::register(), commands::testnats::register()], + vec![ + commands::ping::register(), + commands::play::register(), + commands::testnats::register(), + ], ) .await { @@ -58,6 +69,10 @@ impl EventHandler for Handler { } } +impl A for Client { + +} + #[tokio::main] async fn main() { // Configure the client with your Discord bot token in the environment. diff --git a/apps/worker/src/workers/search.rs b/apps/worker/src/workers/search.rs index b0a6cae..5a2893f 100644 --- a/apps/worker/src/workers/search.rs +++ b/apps/worker/src/workers/search.rs @@ -1,4 +1,8 @@ -use types::jobs::{JobResponse, SearchJob, SearchResponse}; +use types::{ + jobs::{JobResponse, SearchJob, SearchResponse}, + misc::parse_url_or_default, + queue::YoutubeSong, +}; use yt_dlp::Downloader; pub async fn search( @@ -13,8 +17,17 @@ pub async fn search( .await { Ok(result) => match result.webpage_url { - Some(url) => JobResponse { - content: Some(SearchResponse { url }), + Some(webpage_url) => JobResponse { + content: Some(SearchResponse { + song: YoutubeSong { + title: result.title, + artist: result.channel.unwrap_or(String::new()), + url: parse_url_or_default(webpage_url), + thumbnail_url: parse_url_or_default( + result.thumbnail.unwrap_or(String::new()), + ), + }, + }), error: None, }, None => JobResponse { diff --git a/libs/nats/Cargo.toml b/libs/nats/Cargo.toml new file mode 100644 index 0000000..f80fc2a --- /dev/null +++ b/libs/nats/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nats" +version = "0.1.0" +edition = "2024" + +[dependencies] +async-nats = { version = "0.46.0" } diff --git a/libs/nats/src/functions.rs b/libs/nats/src/functions.rs new file mode 100644 index 0000000..d24624b --- /dev/null +++ b/libs/nats/src/functions.rs @@ -0,0 +1 @@ +pub fn() \ No newline at end of file diff --git a/libs/nats/src/lib.rs b/libs/nats/src/lib.rs new file mode 100644 index 0000000..014fff1 --- /dev/null +++ b/libs/nats/src/lib.rs @@ -0,0 +1 @@ +pub mod functions; diff --git a/libs/types/Cargo.toml b/libs/types/Cargo.toml index 6b506e6..4820871 100644 --- a/libs/types/Cargo.toml +++ b/libs/types/Cargo.toml @@ -5,4 +5,5 @@ edition = "2024" [dependencies] serde = { version = "1.0.228" } +url = { version = "2.5.8", features = ["serde"] } uuid = { version = "1.22.0", features = ["serde", "v4"] } diff --git a/libs/types/src/jobs.rs b/libs/types/src/jobs.rs index 5fe1d72..3c1bef9 100644 --- a/libs/types/src/jobs.rs +++ b/libs/types/src/jobs.rs @@ -1,18 +1,34 @@ use std::{num::NonZeroU64, path::PathBuf}; use serde::{Deserialize, Serialize}; +use url::Url; use uuid::Uuid; +use crate::queue::YoutubeSong; + + + + +pub enum JobsBody { + +} + +impl Jobs { + fn as_str(&self) -> &'static str { + match self { + Self::Search(self) => "Hello", + Self::Download => "World", + } + } +} + #[derive(Debug, Deserialize, Serialize)] pub enum Jobs { Search(SearchResponse), Download(DownloadResponse), Play(PlayResponse), - // Error(String), } -pub type JobResult = Result; - #[derive(Serialize, Deserialize, Debug)] pub struct JobResponse { pub content: Option, @@ -22,7 +38,7 @@ pub struct JobResponse { #[derive(Serialize, Deserialize, Debug)] pub struct DownloadJob { pub uuid: Uuid, - pub url: String, + pub url: Url, } #[derive(Serialize, Deserialize, Debug)] @@ -49,5 +65,5 @@ pub struct SearchJob { #[derive(Serialize, Deserialize, Debug)] pub struct SearchResponse { - pub url: String, + pub song: YoutubeSong, } diff --git a/libs/types/src/lib.rs b/libs/types/src/lib.rs index c1b809e..6ae21e3 100644 --- a/libs/types/src/lib.rs +++ b/libs/types/src/lib.rs @@ -1,2 +1,3 @@ pub mod jobs; pub mod misc; +pub mod queue; diff --git a/libs/types/src/misc.rs b/libs/types/src/misc.rs index 48ea9a0..f1ce434 100644 --- a/libs/types/src/misc.rs +++ b/libs/types/src/misc.rs @@ -1,5 +1,10 @@ +use url::Url; use uuid::Uuid; pub fn new_uuid_v4() -> Uuid { Uuid::new_v4() } + +pub fn parse_url_or_default(url_string: String) -> Url { + Url::parse(url_string.as_str()).unwrap_or(Url::parse("https://example.com").unwrap()) +} diff --git a/libs/types/src/queue.rs b/libs/types/src/queue.rs new file mode 100644 index 0000000..79d6b8f --- /dev/null +++ b/libs/types/src/queue.rs @@ -0,0 +1,27 @@ +use std::num::NonZeroU64; + +use serde::{Deserialize, Serialize}; +use url::Url; +use uuid::Uuid; + +#[derive(Serialize, Deserialize, Debug)] +pub struct YoutubeSong { + pub title: String, + pub artist: String, + pub url: Url, + pub thumbnail_url: Url, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct YoutubePlaylist { + pub title: String, + pub songs: Vec, + pub url: Url, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Queue { + pub uuid: Uuid, + pub guild_id: NonZeroU64, + pub songs: Vec, +}