mod workers; use std::env; use futures::StreamExt; use postcard::{from_bytes, to_stdvec}; use serenity::{ Client, all::{Context, EventHandler, GatewayIntents, Ready}, async_trait, }; use songbird::SerenityInit; use types::jobs::{JobResponse, JobsMap, JobsResponseMap}; use which::which; use yt_dlp::{Downloader, client::Libraries}; struct Handler { nats_client: async_nats::Client, downloader: Downloader, } #[async_trait] 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 .expect("Cannot init voice manager"); let mut subscriber = self .nats_client .queue_subscribe("corro-dj.*", "group1".to_string()) .await .unwrap(); // Receive and process messages while let Some(message) = subscriber.next().await { println!("Received message {:?}", message); // let subject = message.subject.split(".").collect::>()[1]; let payload: JobsMap = from_bytes(&message.payload).unwrap(); let result = match payload { JobsMap::Download(payload) => { workers::download::download(&self.downloader, payload) .await .map(|res| JobResponse { content: res.content.map(JobsResponseMap::Download), error: res.error, }) } JobsMap::Play(payload) => workers::play::play(&voice_manager, payload) .await .map(|res| JobResponse { content: res.content.map(JobsResponseMap::Play), error: res.error, }), JobsMap::Search(payload) => workers::search::search(&self.downloader, payload) .await .map(|res| JobResponse { content: res.content.map(JobsResponseMap::Search), error: res.error, }), }; let response = match result { Ok(response) => response, Err(why) => JobResponse { content: None, error: Some(why), }, }; println!("response {:?}", response); if let Some(reply) = message.reply { self.nats_client .publish(reply, to_stdvec(&response).unwrap().into()) .await .unwrap(); } } } } #[tokio::main] async fn main() { rustls::crypto::aws_lc_rs::default_provider() .install_default() .expect("Failed to install rustls crypto provider"); let discord_token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment"); let nats_client = async_nats::connect("nats://localhost:4222") .await .expect("Error creating nats client"); let downloader = Downloader::builder( Libraries::new(which("yt-dlp").unwrap(), which("ffmpeg").unwrap()), "output", ) .build() .await .unwrap(); let handler = Handler { nats_client, downloader, }; let mut discord_client = Client::builder(&discord_token, GatewayIntents::non_privileged()) .event_handler(handler) .register_songbird() .await .expect("Error creating discord client"); if let Err(why) = discord_client.start().await { println!("Client start error: {why:?}"); } }