From ffba60b278162707bc4eb004c3bfb6b2e9595213 Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Wed, 8 May 2024 12:55:35 -0400 Subject: rework to use songbird --- src/util.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 96 insertions(+), 15 deletions(-) (limited to 'src/util.rs') diff --git a/src/util.rs b/src/util.rs index ed5fd54..d59c4da 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,3 +1,4 @@ +use chrono::Duration; use serenity::{ client::Context, model::{ @@ -8,32 +9,31 @@ use serenity::{ permissions::Permissions, }, }; +use std::process::Stdio; use lazy_static::lazy_static; use log::debug; -use serenity::{ - all::CreateMessage, - futures::{ - AsyncReadExt, - StreamExt, - }, +use regex::{ + Match, + Regex, +}; +use serenity::all::{ + CreateMessage, + Message, }; use url::Url; use crate::{ - audio::PlayQueue, + commands::songbird, Result, CONFIG, }; -pub async fn currently_playing(ctx: &Context) -> bool { - let queue_lock = { - let data = ctx.data.read().await; - data.get::().cloned().unwrap() - }; +pub async fn currently_playing(ctx: &Context, msg: &Message) -> bool { + let (_sb, call) = songbird(ctx, msg).await.expect("no songbird"); - let play_queue = queue_lock.read().unwrap(); - play_queue.playing.is_some() + let call = call.lock().await; + call.queue().current().is_some() } pub async fn users_listening(ctx: &Context) -> Result { @@ -77,7 +77,6 @@ pub async fn send_result( lazy_static! { static ref REQUIRED_PERMS: Permissions = Permissions::EMBED_LINKS - | Permissions::READ_MESSAGES | Permissions::ADD_REACTIONS | Permissions::SEND_MESSAGES | Permissions::SEND_TTS_MESSAGES @@ -98,3 +97,85 @@ lazy_static! { )) .unwrap(); } + +pub async fn ytdl_url(uri: &str) -> Result { + use serde_json::Value; + use tokio::process::Command; + + lazy_static! { + static ref YTDL_COMMAND: String = { + let result = CONFIG.ytdl.clone().unwrap_or("youtube-dl".to_owned()); + log::debug!("got ytdl: {}", result); + + result + }; + } + + let args = [ + "-f", + "webm[abr>0]/bestaudio/best", + "--no-playlist", + "--print-json", + "--skip-download", + uri, + ]; + + let out = Command::new(&*YTDL_COMMAND).args(&args).stdin(Stdio::null()).output().await?; + + if !out.status.success() { + return Err(anyhow::anyhow!("running ytdl: {out:?}")); + } + + let value = serde_json::from_reader(&out.stdout[..])?; + let mut obj = match value { + Value::Object(obj) => obj, + other => return Err(anyhow::anyhow!("ytdl output not object: {other:?}")), + }; + + match obj.remove("url") { + Some(v) => match v { + Value::String(uri) => Ok(uri), + other => Err(anyhow::anyhow!("url not string: {other:?}")), + }, + None => Err(anyhow::anyhow!("no url")), + } +} +pub fn parse_times>(s: A) -> (Option, Option) { + lazy_static! { + static ref START_REGEX: Regex = + Regex::new(r"(?:start|begin(?:ning)?)\s*=?\s*(?:(?P\d+)h\s?)?(?:(?P\d+)m\s?)?(?:(?P\d+)s?)?").unwrap(); + + static ref DUR_REGEX: Regex = + Regex::new(r"dur(?:ation)?\s*=?\s*(?:(?P\d+)h\s?)?(?:(?P\d+)m\s?)?(?:(?P\d+)s?)?").unwrap(); + + static ref END_REGEX: Regex = + Regex::new(r"(?:end|term(?:inate|ination)?)\s*=?\s*(?:(?P\d+)h\s?)?(?:(?P\d+)m\s?)?(?:(?P\d+)s?)?").unwrap(); + } + + fn parse_match(m: Option) -> u64 { + m.and_then(|s| s.as_str().parse::().ok()).unwrap_or(0) + } + + fn parse_captures>(r: &Regex, s: B) -> Option { + r.captures(s.as_ref()).map(|capt| { + let hours = parse_match(capt.name("hours")); + let minutes = parse_match(capt.name("minutes")); + let seconds = parse_match(capt.name("seconds")); + + let result = Duration::hours(hours as i64) + + Duration::minutes(minutes as i64) + + Duration::seconds(seconds as i64); + + assert!(result >= Duration::zero()); + + result + }) + } + + let start_time = parse_captures(&START_REGEX, &s); + let dur = parse_captures(&DUR_REGEX, &s); + let end_time = parse_captures(&END_REGEX, s) + .or_else(|| start_time.and_then(|start| dur.map(|d| start + d))); + + (start_time, end_time) +} -- cgit v1.3.1