From 2f6f8414d0d42906435a4a755d00968cf725c4d5 Mon Sep 17 00:00:00 2001 From: Yanis Rigaudeau Date: Wed, 11 Mar 2026 00:21:56 +0100 Subject: [PATCH] search --- Cargo.lock | 45 ++++++++++------------------ apps/master/src/commands/mod.rs | 1 - apps/master/src/commands/modal.rs | 28 ----------------- apps/master/src/commands/ping.rs | 2 +- apps/master/src/commands/testnats.rs | 41 +++++++++++++++++++++++-- apps/master/src/main.rs | 10 +------ apps/worker/Cargo.toml | 6 ++-- apps/worker/src/main.rs | 18 +++++++---- apps/worker/src/workers/download.rs | 9 ++++-- apps/worker/src/workers/mod.rs | 1 + apps/worker/src/workers/search.rs | 34 +++++++++++++++++++++ compose.dev.yml | 2 +- libs/types/src/jobs.rs | 14 ++++++++- 13 files changed, 126 insertions(+), 85 deletions(-) delete mode 100644 apps/master/src/commands/modal.rs create mode 100644 apps/worker/src/workers/search.rs diff --git a/Cargo.lock b/Cargo.lock index 8ed4e07..6e63360 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1004,12 +1004,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - [[package]] name = "equivalent" version = "1.0.2" @@ -2272,9 +2266,9 @@ dependencies = [ [[package]] name = "media-seek" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0725216805b735264e0b9539ade0abbbf2a43f8dfcd4cbdaf4965b23f6e00997" +checksum = "0b04bb6c939d4ce151ab5fe0edf3a1d12e47458839c53f0bcc8e97410e39c50f" dependencies = [ "futures-util", "thiserror 2.0.18", @@ -2963,9 +2957,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "aws-lc-rs", "bytes", @@ -3543,9 +3537,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -5217,13 +5211,11 @@ dependencies = [ [[package]] name = "which" -version = "8.0.1" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a824aeba0fbb27264f815ada4cff43d65b1741b7a4ed7629ff9089148c4a4e0" +checksum = "81995fafaaaf6ae47a7d0cc83c67caf92aeb7e5331650ae6ff856f7c0c60c459" dependencies = [ - "env_home", - "rustix", - "winsafe", + "libc", ] [[package]] @@ -5615,12 +5607,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" -[[package]] -name = "winsafe" -version = "0.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" - [[package]] name = "wit-bindgen" version = "0.51.0" @@ -5789,9 +5775,9 @@ dependencies = [ [[package]] name = "yt-dlp" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e8918ad10557a4100c9dcc02842f08c55a9d25600486259e4a2dc36a4851719" +checksum = "21c453b0ae22daab68b6361dfb7bf37126c4b23dc2f5f6309606e9f6df2b9447" dependencies = [ "async-trait", "cfg-if", @@ -5801,7 +5787,6 @@ dependencies = [ "dyn-clone", "futures-util", "id3", - "lazy_static", "lofty", "media-seek", "moka", @@ -5830,18 +5815,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", diff --git a/apps/master/src/commands/mod.rs b/apps/master/src/commands/mod.rs index 5d04254..f6ddc1f 100644 --- a/apps/master/src/commands/mod.rs +++ b/apps/master/src/commands/mod.rs @@ -1,3 +1,2 @@ -pub mod modal; pub mod ping; pub mod testnats; diff --git a/apps/master/src/commands/modal.rs b/apps/master/src/commands/modal.rs deleted file mode 100644 index baca275..0000000 --- a/apps/master/src/commands/modal.rs +++ /dev/null @@ -1,28 +0,0 @@ -use serenity::{builder::*, model::prelude::*, prelude::*, utils::CreateQuickModal}; - -pub async fn run(ctx: &Context, interaction: &CommandInteraction) -> Result<(), serenity::Error> { - let modal = CreateQuickModal::new("About you") - .timeout(std::time::Duration::from_secs(600)) - .short_field("First name") - .short_field("Last name") - .paragraph_field("Hobbies and interests"); - let response = interaction.quick_modal(ctx, modal).await?.unwrap(); - - let inputs = response.inputs; - let (first_name, last_name, hobbies) = (&inputs[0], &inputs[1], &inputs[2]); - - response - .interaction - .create_response( - ctx, - CreateInteractionResponse::Message(CreateInteractionResponseMessage::new().content( - format!("**Name**: {first_name} {last_name}\n\nHobbies and interests: {hobbies}"), - )), - ) - .await?; - Ok(()) -} - -pub fn register() -> CreateCommand { - CreateCommand::new("modal").description("Asks some details about you") -} diff --git a/apps/master/src/commands/ping.rs b/apps/master/src/commands/ping.rs index 31c28d0..75ea7cb 100644 --- a/apps/master/src/commands/ping.rs +++ b/apps/master/src/commands/ping.rs @@ -1,7 +1,7 @@ use serenity::{builder::CreateCommand, model::application::ResolvedOption}; pub fn run(_options: &[ResolvedOption]) -> String { - "Hey, I'm alive!".to_string() + "Pong!".to_string() } pub fn register() -> CreateCommand { diff --git a/apps/master/src/commands/testnats.rs b/apps/master/src/commands/testnats.rs index 4d5f5e5..7e44af7 100644 --- a/apps/master/src/commands/testnats.rs +++ b/apps/master/src/commands/testnats.rs @@ -14,7 +14,7 @@ use serenity::{ model::application::{CommandOptionType, ResolvedOption, ResolvedValue}, }; use types::{ - jobs::{DownloadJob, JobResponse, Jobs, PlayJob}, + jobs::{DownloadJob, JobResponse, Jobs, PlayJob, SearchJob}, misc::new_uuid_v4, }; @@ -40,9 +40,44 @@ pub async fn run( ) .await?; + let url: String; + 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(Jobs::Search(content)) = search_response.content { + url = content.url; + } else { + interaction + .edit_response(ctx, EditInteractionResponse::new().content("unknown error")) + .await?; + return Err(serenity::Error::Other("unknown error")); + } + } else { + url = value.to_string(); + } + let download_job = DownloadJob { uuid: new_uuid_v4(), - url: value.to_string(), + url, }; println!("job {:?}", download_job); @@ -58,7 +93,7 @@ pub async fn run( Err(_why) => return Err(serenity::Error::Other("send error")), }; - let job_response: JobResponse = from_bytes(&response.payload).unwrap(); + let job_response: JobResponse = from_bytes(&response.payload).unwrap(); println!("response: {:?}", job_response); diff --git a/apps/master/src/main.rs b/apps/master/src/main.rs index bc2975f..c251d10 100644 --- a/apps/master/src/main.rs +++ b/apps/master/src/main.rs @@ -31,10 +31,6 @@ impl EventHandler for Handler { None } "ping" => Some(commands::ping::run(&command.data.options())), - "modal" => { - commands::modal::run(&ctx, &command).await.unwrap(); - None - } _ => Some("not implemented :(".to_string()), }; @@ -53,11 +49,7 @@ impl EventHandler for Handler { if let Err(why) = Command::set_global_commands( &ctx.http, - vec![ - commands::ping::register(), - commands::modal::register(), - commands::testnats::register(), - ], + vec![commands::ping::register(), commands::testnats::register()], ) .await { diff --git a/apps/worker/Cargo.toml b/apps/worker/Cargo.toml index d8ecf9d..d5f31be 100644 --- a/apps/worker/Cargo.toml +++ b/apps/worker/Cargo.toml @@ -8,7 +8,7 @@ async-nats = { version = "0.46.0" } futures = { version = "0.3.32" } futures-executor = { version = "0.3.32" } postcard = { version = "1.1.3", features = ["use-std"] } -rustls = { version = "0.23.37", default-features = false, features = ["ring"] } +rustls = { version = "0.23.37", default-features = false, features = ["aws-lc-rs"] } serenity = { version = "0.12.5", default-features = false, features = [ "cache", "rustls_backend", @@ -18,5 +18,5 @@ songbird = { git = "https://github.com/beerpsi-forks/songbird.git", branch = "da symphonia = { version = "0.5.5" } tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread"] } types = { path = "../../libs/types" } -which = { version = "8.0.1" } -yt-dlp = { version = "2.4.0" } +which = { version = "8.0.2" } +yt-dlp = { version = "2.5.0" } diff --git a/apps/worker/src/main.rs b/apps/worker/src/main.rs index 1b25879..f3b6231 100644 --- a/apps/worker/src/main.rs +++ b/apps/worker/src/main.rs @@ -16,7 +16,7 @@ use yt_dlp::{Downloader, client::Libraries}; struct Handler { nats_client: async_nats::Client, - yt_downloader: Downloader, + downloader: Downloader, } #[async_trait] @@ -40,7 +40,7 @@ impl EventHandler for Handler { let result = match subject { "download" => workers::download::download( - &self.yt_downloader, + &self.downloader, from_bytes(&message.payload).unwrap(), ) .await @@ -56,6 +56,14 @@ impl EventHandler for Handler { error: res.error, }) } + "search" => { + workers::search::search(&self.downloader, from_bytes(&message.payload).unwrap()) + .await + .map(|res| JobResponse { + content: res.content.map(Jobs::Search), + error: res.error, + }) + } _ => Err(format!("subject {subject} does not exists")), }; @@ -81,7 +89,7 @@ impl EventHandler for Handler { #[tokio::main] async fn main() { - rustls::crypto::ring::default_provider() + rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("Failed to install rustls crypto provider"); @@ -91,7 +99,7 @@ async fn main() { .await .expect("Error creating nats client"); - let yt_downloader = Downloader::builder( + let downloader = Downloader::builder( Libraries::new(which("yt-dlp").unwrap(), which("ffmpeg").unwrap()), "output", ) @@ -101,7 +109,7 @@ async fn main() { let handler = Handler { nats_client, - yt_downloader, + downloader, }; let mut discord_client = Client::builder(&discord_token, GatewayIntents::non_privileged()) diff --git a/apps/worker/src/workers/download.rs b/apps/worker/src/workers/download.rs index ebf172e..283d859 100644 --- a/apps/worker/src/workers/download.rs +++ b/apps/worker/src/workers/download.rs @@ -1,5 +1,8 @@ use types::jobs::{DownloadJob, DownloadResponse, JobResponse}; -use yt_dlp::Downloader; +use yt_dlp::{ + Downloader, + model::{AudioCodecPreference, AudioQuality}, +}; pub async fn download( downloader: &Downloader, @@ -16,8 +19,8 @@ pub async fn download( .download_audio_stream_with_quality( &video, format!("{}.ogg", video.id), - yt_dlp::model::AudioQuality::Best, - yt_dlp::model::AudioCodecPreference::Opus, + AudioQuality::Best, + AudioCodecPreference::Opus, ) .await { diff --git a/apps/worker/src/workers/mod.rs b/apps/worker/src/workers/mod.rs index a202527..ee4e94b 100644 --- a/apps/worker/src/workers/mod.rs +++ b/apps/worker/src/workers/mod.rs @@ -1,2 +1,3 @@ pub mod download; pub mod play; +pub mod search; diff --git a/apps/worker/src/workers/search.rs b/apps/worker/src/workers/search.rs new file mode 100644 index 0000000..b0a6cae --- /dev/null +++ b/apps/worker/src/workers/search.rs @@ -0,0 +1,34 @@ +use types::jobs::{JobResponse, SearchJob, SearchResponse}; +use yt_dlp::Downloader; + +pub async fn search( + downloader: &Downloader, + job: SearchJob, +) -> Result, String> { + println!("job: {:?}", job); + + let result = match downloader + .youtube_extractor() + .search_first(&job.query) + .await + { + Ok(result) => match result.webpage_url { + Some(url) => JobResponse { + content: Some(SearchResponse { url }), + error: None, + }, + None => JobResponse { + content: None, + error: Some("url is not defined".to_string()), + }, + }, + Err(why) => JobResponse { + content: None, + error: Some(format!("{why}")), + }, + }; + + println!("reply: {:?}", result.content); + + Ok(result) +} diff --git a/compose.dev.yml b/compose.dev.yml index f46698b..150a481 100644 --- a/compose.dev.yml +++ b/compose.dev.yml @@ -1,5 +1,5 @@ services: nats: - image: nats:2.12.4-alpine3.22 + image: nats:2.12.5-alpine3.22 ports: - 127.0.0.1:4222:4222 diff --git a/libs/types/src/jobs.rs b/libs/types/src/jobs.rs index 4b7c29b..5fe1d72 100644 --- a/libs/types/src/jobs.rs +++ b/libs/types/src/jobs.rs @@ -5,6 +5,7 @@ use uuid::Uuid; #[derive(Debug, Deserialize, Serialize)] pub enum Jobs { + Search(SearchResponse), Download(DownloadResponse), Play(PlayResponse), // Error(String), @@ -13,7 +14,7 @@ pub enum Jobs { pub type JobResult = Result; #[derive(Serialize, Deserialize, Debug)] -pub struct JobResponse { +pub struct JobResponse { pub content: Option, pub error: Option, } @@ -39,3 +40,14 @@ pub struct PlayJob { #[derive(Serialize, Deserialize, Debug)] pub struct PlayResponse {} + +#[derive(Serialize, Deserialize, Debug)] +pub struct SearchJob { + pub uuid: Uuid, + pub query: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct SearchResponse { + pub url: String, +}