From 0f8a4402c344efd67443f96b9a4f614d65c7f405 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 6 Oct 2024 16:53:12 +0200 Subject: [PATCH 01/19] feat: implemented new slash commands --- src/commands/mod.rs | 9 ++++- src/commands/moover/mod.rs | 7 ++++ src/commands/{ => moover}/moove.rs | 0 src/commands/{ => moover}/say.rs | 0 src/commands/notice/birthday.rs | 0 src/commands/notice/events.rs | 0 src/commands/notice/mod.rs | 2 + src/commands/user_interactions/headpat.rs | 20 ++++++++++ src/commands/user_interactions/hug.rs | 20 ++++++++++ src/commands/user_interactions/interaction.rs | 38 +++++++++++++++++++ src/commands/user_interactions/mod.rs | 6 +++ src/message_handler.rs | 2 +- src/other/notice.rs | 4 +- src/types.rs | 2 +- src/util/gifs.rs | 9 +++++ src/util/mod.rs | 3 +- src/util/utilities.rs | 2 +- 17 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 src/commands/moover/mod.rs rename src/commands/{ => moover}/moove.rs (100%) rename src/commands/{ => moover}/say.rs (100%) create mode 100644 src/commands/notice/birthday.rs create mode 100644 src/commands/notice/events.rs create mode 100644 src/commands/notice/mod.rs create mode 100644 src/commands/user_interactions/headpat.rs create mode 100644 src/commands/user_interactions/hug.rs create mode 100644 src/commands/user_interactions/interaction.rs create mode 100644 src/commands/user_interactions/mod.rs create mode 100644 src/util/gifs.rs diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 98ea7cd..440afec 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,2 +1,7 @@ -pub mod moove; -pub mod say; \ No newline at end of file +pub use moover::*; +pub use notice::*; +pub use user_interactions::*; + +pub mod moover; +pub mod notice; +pub mod user_interactions; diff --git a/src/commands/moover/mod.rs b/src/commands/moover/mod.rs new file mode 100644 index 0000000..4b6fd56 --- /dev/null +++ b/src/commands/moover/mod.rs @@ -0,0 +1,7 @@ +pub use moove::*; +pub use say::*; +pub use gif::*; + +pub mod moove; +pub mod say; +pub mod gif; \ No newline at end of file diff --git a/src/commands/moove.rs b/src/commands/moover/moove.rs similarity index 100% rename from src/commands/moove.rs rename to src/commands/moover/moove.rs diff --git a/src/commands/say.rs b/src/commands/moover/say.rs similarity index 100% rename from src/commands/say.rs rename to src/commands/moover/say.rs diff --git a/src/commands/notice/birthday.rs b/src/commands/notice/birthday.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/commands/notice/events.rs b/src/commands/notice/events.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/commands/notice/mod.rs b/src/commands/notice/mod.rs new file mode 100644 index 0000000..ef275cb --- /dev/null +++ b/src/commands/notice/mod.rs @@ -0,0 +1,2 @@ +pub mod birthday; +pub mod events; \ No newline at end of file diff --git a/src/commands/user_interactions/headpat.rs b/src/commands/user_interactions/headpat.rs new file mode 100644 index 0000000..8d33ad8 --- /dev/null +++ b/src/commands/user_interactions/headpat.rs @@ -0,0 +1,20 @@ +use poise; +use serenity::all::User; + +use super::interaction::send_with_embed; +use crate::types::{Error, Context}; + +#[poise::command( + slash_command, + description_localized("en-US", "Headpat all your friends!") +)] +pub async fn headpat(ctx: Context<'_>, + #[description = "Who is the lucky one?"] + user: User +) -> Result<(), Error> { + let title = "HEADPATS!"; + let desc = format!("{} headpats {}", ctx.author(), user); + send_with_embed(ctx, "headpat", &title, &desc).await?; + ctx.reply("Done!").await?; + Ok(()) +} \ No newline at end of file diff --git a/src/commands/user_interactions/hug.rs b/src/commands/user_interactions/hug.rs new file mode 100644 index 0000000..31dbe8c --- /dev/null +++ b/src/commands/user_interactions/hug.rs @@ -0,0 +1,20 @@ +use poise; +use serenity::all::User; + +use super::interaction::send_with_embed; +use crate::types::{Error, Context}; + +#[poise::command( + slash_command, + description_localized("en-US", "Hug all your friends!") +)] +pub async fn hug(ctx: Context<'_>, + #[description = "Who is the lucky one?"] + user: User +) -> Result<(), Error> { + let title = "HUGS!"; + let desc = format!("{} hugs {}", ctx.author(), user); + send_with_embed(ctx, "hug", &title, &desc).await?; + ctx.reply("Done!").await?; + Ok(()) +} \ No newline at end of file diff --git a/src/commands/user_interactions/interaction.rs b/src/commands/user_interactions/interaction.rs new file mode 100644 index 0000000..439ef72 --- /dev/null +++ b/src/commands/user_interactions/interaction.rs @@ -0,0 +1,38 @@ +use anyhow::anyhow; +use serenity::all::{Colour, CreateEmbed, CreateMessage}; +use tenorv2::tenor_builder::Tenor; + +use crate::{types::Context, util::{gifs::get_random_tenor_gif, utilities}}; + +pub(super) async fn send_with_embed(ctx: Context<'_>, query: &str, title: &str, desc: &str) -> anyhow::Result<()> { + let tenor_response = Tenor::new()? + .random(true) + .search(query).await?; + + const LIMIT: u8 = 20; + let url = get_random_tenor_gif(tenor_response, LIMIT).await?; + + let embed = CreateEmbed::new() + .color(Colour::new(rand::random::() % 0xFFFFFF)) + .title(title) + .description(desc) + .image(url.as_str()); + + if ctx.guild_id().is_none() { + return Err(anyhow!("Guild id not available in context")); + } + + utilities::get_system_channel( + ctx.guild_id().unwrap(), ctx.http() + ).await? + .send_message( + ctx.http(), + CreateMessage::new().add_embed(embed) + ).await?; + + Ok(()) +} + +pub(super) async fn send(ctx: Context<'_>, msg: &str) -> anyhow::Result<()> { + Ok(()) +} \ No newline at end of file diff --git a/src/commands/user_interactions/mod.rs b/src/commands/user_interactions/mod.rs new file mode 100644 index 0000000..0e8654b --- /dev/null +++ b/src/commands/user_interactions/mod.rs @@ -0,0 +1,6 @@ +pub use headpat::*; +pub use hug::*; + +pub mod interaction; +pub mod headpat; +pub mod hug; \ No newline at end of file diff --git a/src/message_handler.rs b/src/message_handler.rs index 1183998..767448a 100644 --- a/src/message_handler.rs +++ b/src/message_handler.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use crate::util::debug::send_error; use crate::util::utilities; -use crate::commands::moove::{moove, moove_check}; +use crate::commands::moover::moove::{moove, moove_check}; pub async fn handle(ctx: Context, msg: Message) { if msg.author.bot { diff --git a/src/other/notice.rs b/src/other/notice.rs index e7fde2e..2294637 100644 --- a/src/other/notice.rs +++ b/src/other/notice.rs @@ -30,7 +30,7 @@ async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, ht .color(Colour::new(rand::random::() % 0xFFFFFF)) .title("Today's event is:"); - let system_channel = utilities::get_system_channel(guild_id, http.clone()).await?; + let system_channel = utilities::get_system_channel(guild_id, &http).await?; if special_message.contains("http") { event_embed = event_embed.description(name); @@ -65,7 +65,7 @@ async fn celebrate_birthday(guild_id: GuildId, user_id: UserId, nick: &str, http } }; - let system_channel = utilities::get_system_channel(guild_id, http.clone()).await?; + let system_channel = utilities::get_system_channel(guild_id, &http).await?; let mut embed = CreateEmbed::new() .color(Colour::new(rand::random::() % 0xFFFFFF)) diff --git a/src/types.rs b/src/types.rs index 2571aab..b5ebced 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,4 +2,4 @@ pub type Error = Box; // replace () with Data if you ever need to store some additional data -// pub type Context<'a> = poise::Context<'a, (), Error>; +pub type Context<'a> = poise::Context<'a, (), Error>; diff --git a/src/util/gifs.rs b/src/util/gifs.rs new file mode 100644 index 0000000..f128ea9 --- /dev/null +++ b/src/util/gifs.rs @@ -0,0 +1,9 @@ +use tenorv2::{tenor, tenor_types::{MediaFilter, TenorError}, JsonValue}; + +pub async fn get_random_tenor_gif(tenor_response: JsonValue, limit: u8) -> Result { + let index = rand::random::() % limit as usize; + match tenor::get_gif_url(MediaFilter::gif, tenor_response) { + Ok(urls) => Ok(urls[index].clone()), + Err(e) => Err(e) + } +} \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index d3d2689..a259bb4 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,2 +1,3 @@ pub mod debug; -pub mod utilities; \ No newline at end of file +pub mod utilities; +pub mod gifs; \ No newline at end of file diff --git a/src/util/utilities.rs b/src/util/utilities.rs index 7669eb7..8b5f470 100644 --- a/src/util/utilities.rs +++ b/src/util/utilities.rs @@ -4,7 +4,7 @@ use serenity::{all::{ChannelId, CreateMessage, GuildId, Message}, http::Http}; use anyhow::Context; -pub async fn get_system_channel(guild_id: GuildId, http: Arc) -> anyhow::Result { +pub async fn get_system_channel(guild_id: GuildId, http: &Http) -> anyhow::Result { return http.get_guild(guild_id).await?.system_channel_id .context(format!("System channel of guild: {} not found", guild_id.get())); } From a311ca7a2ee4d29091e7473838d43a8d83862316 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 6 Oct 2024 16:54:08 +0200 Subject: [PATCH 02/19] feat: add commands to main, guild/global command registration --- Cargo.toml | 1 + src/main.rs | 32 +++++++++++++++++++++----------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7b8e356..359cd1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,4 @@ tenorv2 = { path = "./tenor-v2/tenorv2" } [features] DEBUG = [] RELEASE = [] +GUILD_COMMAND = [] \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index de3c551..59da021 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,13 +5,14 @@ use std::time::Duration; use std::error; use std::env; -use poise::samples::register_in_guild; +use poise::samples::register_globally; +use poise::samples::register_in_guild; use serenity::async_trait; use serenity::prelude::GatewayIntents; use serenity::client::Context; use serenity::model::gateway::Ready; -use serenity::all::{EventHandler, GuildId, Message}; +use serenity::all::{EventHandler, Message}; use serenity::Client; use dotenv::dotenv; @@ -82,7 +83,10 @@ async fn main() -> anyhow::Result<()> { // create poise framework for registering commands let options: poise::FrameworkOptions<(), Box> = poise::FrameworkOptions { - commands: vec![], + commands: vec![ + commands::say(), + commands::hug() + ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), edit_tracker: Some(Arc::new(poise::EditTracker::for_timespan( @@ -99,15 +103,21 @@ async fn main() -> anyhow::Result<()> { ..Default::default() }; - let debug_guild_id = env::var("DEBUG_GUILD_ID") - .context("DEBUG_GUILD_ID not found in env")? - .parse::().unwrap(); - + let framework = poise::Framework::builder() - .setup(move |ctx, _ready, framework| { - Box::pin(async move { - register_in_guild(ctx, &framework.options().commands, GuildId::new(debug_guild_id)).await?; - Ok(()) + .setup(move |ctx, _ready, framework| { + Box::pin(async move { + #[cfg(feature="GUILD_COMMAND")] { + let debug_guild_id = env::var("DEBUG_GUILD_ID") + .context("DEBUG_GUILD_ID not found in env")? + .parse::().unwrap(); + + register_in_guild(ctx, &framework.options().commands, debug_guild_id).await?; + } + #[cfg(not(feature="GUILD_COMMAND"))] { + register_globally(ctx, &framework.options().commands).await?; + } + Ok(()) }) }) .options(options) From 79809029484eb62b7648a0e73b0e44a8fddcc254 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Mon, 9 Dec 2024 15:39:54 +0100 Subject: [PATCH 03/19] chore: documentation, dependency updates, etc. --- .env.example | 10 ++++++ Cargo.lock | 16 ++++----- Cargo.toml | 6 ++-- README.md | 35 +++++++++++++++++++ makefile | 2 +- src/commands/moover/moove.rs | 10 +++--- src/commands/notice/mod.rs | 3 ++ src/commands/other/mod.rs | 0 src/commands/user_interactions/interaction.rs | 2 ++ src/other/notice.rs | 4 +++ 10 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 .env.example create mode 100644 README.md create mode 100644 src/commands/other/mod.rs diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..1363c8f --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +TOKEN=token used for release version +DEBUGTOKEN=token I use for debugging on standalone bot +DBPASS=password for database (currently not used) +DEBUG=ON + +DEBUG_CHANNEL_ID=channel where debug info will be sent +DEBUG_GUILD_ID=guild where local slash commands will be registered + +DATABASE_URL=sqlite://path_to_database +TENORV2_TOKEN=token to tenor API v2 \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index c63ac13..6926099 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arrayvec" @@ -1611,9 +1611,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2001,9 +2001,9 @@ dependencies = [ [[package]] name = "serenity" -version = "0.12.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "880a04106592d0a8f5bdacb1d935889bfbccb4a14f7074984d9cd857235d34ac" +checksum = "3d72ec4323681bf9a3cabe40fd080abc2435859b502a1b5aa9bf693f125bfa76" dependencies = [ "arrayvec", "async-trait", @@ -2530,9 +2530,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 359cd1d..1a16780 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,10 +11,10 @@ anyhow = "1.0.89" tokio-cron-scheduler = "0.13.0" dotenv = "0.15.0" poise = "0.6.1" -serenity = { version = "0.12.2", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] } +serenity = { version = "0.12.4", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] } # serenity_utils = "0.7.0" -tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] } -regex = "1.11.0" +tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] } +regex = "1.11.1" chrono = "0.4.38" sqlx = {version="0.8.2", features=["runtime-tokio", "sqlite"]} form_urlencoded = "1.2.1" diff --git a/README.md b/README.md new file mode 100644 index 0000000..7ff7f51 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Discord bot made in rust + +## Current feature list: + - move message from one channel to another + - send hug and headpat embed and tag user in it + - announces events and birthdays that are in database + +## Technologies used + - Discord API - serenity, poise + - Database - sqlite + - gifs - my partial implementation of tenor API + +## Compilation +Make sure you have cargo installed! +Edit .env.example and rename to .env + +Compile debug version +``` +make dev +``` + +Compile release version +``` +make release +``` + +Compile debug version and run it +``` +make run +``` + +Run release version +``` +make run_rel +``` diff --git a/makefile b/makefile index e16831f..7815468 100644 --- a/makefile +++ b/makefile @@ -8,5 +8,5 @@ run: cargo build --features DEBUG ./target/debug/moover_rust -run_release: +run_rel: ./target/release/moover_rust \ No newline at end of file diff --git a/src/commands/moover/moove.rs b/src/commands/moover/moove.rs index 85539d8..046e433 100644 --- a/src/commands/moover/moove.rs +++ b/src/commands/moover/moove.rs @@ -9,10 +9,9 @@ use tokio::time::sleep; use regex::Regex; use serenity::model::id::ChannelId; -// Checks if the message should be mooved -// If the message should be mooved, try to move it and return Ok if mooved succesfully -// else returns Err() +/// Checks if the message should be mooved +/// If the message should be mooved, try to move it and return Ok if mooved succesfully pub async fn moove_check(msg: &Message) -> Option { let word_count = msg.content.trim().split_whitespace().count(); let re = Regex::new(r"<#[0-9]*>$").unwrap(); @@ -29,8 +28,11 @@ pub async fn moove_check(msg: &Message) -> Option { return Some(channel_id); } +/// Move message to new channel (will delete the old message) pub async fn moove(http: Arc, msg: Message, m_channel_id: u64) -> anyhow::Result<()> { - // this should be in moove_check, but I need to find a good way to return in with channel_id + msg.react(http.clone(), '🐮').await?; + + // this should be in moove_check, but I need to find a good way to return it with channel_id let msg_to_moove = msg.clone().referenced_message.context("Referenced message not found")?; //steals all attachments, but sets all of them as Image urls, so rip actual docs etc diff --git a/src/commands/notice/mod.rs b/src/commands/notice/mod.rs index ef275cb..d63767d 100644 --- a/src/commands/notice/mod.rs +++ b/src/commands/notice/mod.rs @@ -1,2 +1,5 @@ +pub use birthday::*; +pub use events::*; + pub mod birthday; pub mod events; \ No newline at end of file diff --git a/src/commands/other/mod.rs b/src/commands/other/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/commands/user_interactions/interaction.rs b/src/commands/user_interactions/interaction.rs index 439ef72..6db121a 100644 --- a/src/commands/user_interactions/interaction.rs +++ b/src/commands/user_interactions/interaction.rs @@ -4,6 +4,8 @@ use tenorv2::tenor_builder::Tenor; use crate::{types::Context, util::{gifs::get_random_tenor_gif, utilities}}; +/// Sends embed with random tenor gif from searched query +/// title and desc are used in the embed pub(super) async fn send_with_embed(ctx: Context<'_>, query: &str, title: &str, desc: &str) -> anyhow::Result<()> { let tenor_response = Tenor::new()? .random(true) diff --git a/src/other/notice.rs b/src/other/notice.rs index 2294637..69b39ed 100644 --- a/src/other/notice.rs +++ b/src/other/notice.rs @@ -24,6 +24,7 @@ pub async fn notice_wrapper(ctx: Context) { } } +/// Send embed with event name and optional special message to guild's general channel async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, http: Arc) -> anyhow::Result<()> { let mut event_embed = CreateEmbed::new() @@ -46,6 +47,7 @@ async fn announce_event(guild_id: GuildId, name: &str, special_message: &str, ht Ok(()) } +/// Send birthday embed to guild's general channel async fn celebrate_birthday(guild_id: GuildId, user_id: UserId, nick: &str, http: Arc) -> anyhow::Result<()> { const LIMIT: u8 = 20; @@ -98,6 +100,8 @@ struct EventRow { special_message: String, } +/// Fetches guild/global events and birthdays for current day +/// Sends notification to relevant channels async fn notice(http: Arc) -> anyhow::Result<()> { use anyhow::Context; From 13d7f48c3dd3d29392f8559d5bcd760cca990d2f Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 8 Dec 2024 15:40:33 +0100 Subject: [PATCH 04/19] chore: preparation for player --- Cargo.lock | 2622 ++++++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 2 + makefile | 4 +- 3 files changed, 2567 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6926099..d901a7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "ahash" version = "0.8.11" @@ -44,6 +79,28 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alsa" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" +dependencies = [ + "alsa-sys", + "bitflags 2.6.0", + "cfg-if", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -59,6 +116,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + [[package]] name = "anyhow" version = "1.0.94" @@ -82,7 +188,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -100,12 +206,58 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "audiopus" +version = "0.3.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab55eb0e56d7c6de3d59f544e5db122d7725ec33be6a276ee8241f3be6473955" +dependencies = [ + "audiopus_sys", +] + +[[package]] +name = "audiopus_sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62314a1546a2064e033665d658e88c620a62904be945f8147e6b16c3db9f8651" +dependencies = [ + "cmake", + "log", + "pkg-config", +] + [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "aws-lc-rs" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" +dependencies = [ + "aws-lc-sys", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" +dependencies = [ + "bindgen 0.69.5", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "backtrace" version = "0.3.73" @@ -121,6 +273,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -139,6 +297,47 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.87", + "which", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.87", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -175,6 +374,12 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +[[package]] +name = "bytemuck" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" + [[package]] name = "byteorder" version = "1.5.0" @@ -223,6 +428,25 @@ name = "cc" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] [[package]] name = "cfg-if" @@ -230,6 +454,30 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + [[package]] name = "chrono" version = "0.4.38" @@ -245,6 +493,53 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +dependencies = [ + "cc", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -260,6 +555,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation" version = "0.9.4" @@ -271,10 +572,63 @@ dependencies = [ ] [[package]] -name = "core-foundation-sys" -version = "0.8.6" +name = "core-foundation" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "coreaudio-rs" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" +dependencies = [ + "bitflags 1.3.2", + "core-foundation-sys", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" +dependencies = [ + "bindgen 0.70.1", +] + +[[package]] +name = "cpal" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" +dependencies = [ + "alsa", + "core-foundation-sys", + "coreaudio-rs", + "dasp_sample", + "jni", + "js-sys", + "libc", + "mach2", + "ndk", + "ndk-context", + "oboe", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.54.0", +] [[package]] name = "cpufeatures" @@ -349,17 +703,66 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "cipher", + "generic-array", + "poly1305", + "salsa20", + "subtle", + "zeroize", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core 0.10.2", + "darling_macro 0.10.2", +] + [[package]] name = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.10", + "darling_macro 0.20.10", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.9.3", + "syn 1.0.109", ] [[package]] @@ -372,8 +775,19 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", - "syn 2.0.72", + "strsim 0.11.1", + "syn 2.0.87", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core 0.10.2", + "quote", + "syn 1.0.109", ] [[package]] @@ -382,9 +796,9 @@ version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core", + "darling_core 0.20.10", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -401,6 +815,12 @@ dependencies = [ "serde", ] +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + [[package]] name = "data-encoding" version = "2.6.0" @@ -439,6 +859,75 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" +dependencies = [ + "darling 0.10.2", + "derive_builder_core 0.9.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" +dependencies = [ + "darling 0.10.2", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.10", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core 0.20.2", + "syn 2.0.87", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.87", +] + [[package]] name = "digest" version = "0.10.7" @@ -451,6 +940,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "discortp" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c793408a15d361754613fa68123ffa60424c2617fafdf82127b4bedf37d3f5d" +dependencies = [ + "pnet_macros", + "pnet_macros_support", +] + [[package]] name = "dotenv" version = "0.15.0" @@ -463,6 +962,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.13.0" @@ -481,6 +986,28 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -534,6 +1061,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.0.30" @@ -552,7 +1085,8 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin", + "nanorand", + "spin 0.9.8", ] [[package]] @@ -585,6 +1119,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "from_map" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f31122ab0445ff8cee420b805f24e07683073815de1dd276ee7d588d301700" +dependencies = [ + "hashmap_derive", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.30" @@ -593,6 +1142,7 @@ checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -651,7 +1201,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -666,6 +1216,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.30" @@ -693,6 +1249,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows 0.48.0", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -701,6 +1270,16 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", ] [[package]] @@ -710,8 +1289,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", ] [[package]] @@ -726,6 +1317,24 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "futures", + "futures-timer", + "no-std-compat 0.4.1", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "rand", + "smallvec", + "spinning_top", +] + [[package]] name = "h2" version = "0.3.26" @@ -783,6 +1392,50 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "hashmap_derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb30bf173e72cc31b5265dac095423ca14e7789ff7c3b0e6096a37a996f12883" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64 0.21.7", + "bytes", + "headers-core", + "http 1.1.0", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http 1.1.0", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "heck" version = "0.5.0" @@ -810,6 +1463,21 @@ dependencies = [ "hmac", ] +[[package]] +name = "hls_m3u8" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b906521a5b0e6d2ec07ea0bb855d92a1db30b48812744a645a3b2a1405cb8159" +dependencies = [ + "derive_builder 0.9.0", + "derive_more", + "hex", + "shorthand", + "stable-vec", + "strum", + "thiserror", +] + [[package]] name = "hmac" version = "0.12.1" @@ -896,6 +1564,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.30" @@ -933,6 +1607,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -940,6 +1615,27 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-proxy2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9043b7b23fb0bc4a1c7014c27b50a4fc42cc76206f71d34fc0dfe5b28ddc3faf" +dependencies = [ + "bytes", + "futures-util", + "headers", + "http 1.1.0", + "hyper 1.4.1", + "hyper-rustls 0.26.0", + "hyper-util", + "pin-project-lite", + "rustls-native-certs 0.7.3", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", + "webpki", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -954,6 +1650,25 @@ dependencies = [ "tokio-rustls 0.24.1", ] +[[package]] +name = "hyper-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", + "log", + "rustls 0.22.4", + "rustls-native-certs 0.7.3", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", +] + [[package]] name = "hyper-rustls" version = "0.27.2" @@ -964,7 +1679,9 @@ dependencies = [ "http 1.1.0", "hyper 1.4.1", "hyper-util", + "log", "rustls 0.23.12", + "rustls-native-certs 0.7.3", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -1018,7 +1735,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -1056,18 +1773,82 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -1089,21 +1870,251 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin", + "spin 0.9.8", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "librespot" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e4b1f97b2767e35327b8443dcc1d2360a83c1c09a8686bf824ff61ab50f04c" +dependencies = [ + "data-encoding", + "env_logger", + "futures-util", + "getopts", + "librespot-audio", + "librespot-connect", + "librespot-core", + "librespot-discovery", + "librespot-metadata", + "librespot-oauth", + "librespot-playback", + "librespot-protocol", + "log", + "sha1", + "sysinfo", + "thiserror", + "tokio", + "url", +] + +[[package]] +name = "librespot-audio" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e07566fe7553042936c61bbdd9bedb524114a904aa7f9738e266c641468bab8" +dependencies = [ + "aes", + "bytes", + "ctr", + "futures-util", + "http-body-util", + "hyper 1.4.1", + "hyper-util", + "librespot-core", + "log", + "parking_lot", + "tempfile", + "thiserror", + "tokio", +] + +[[package]] +name = "librespot-connect" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ce3a5634669ce051a425cff5437a474831111df045fd5a2bb37fabe316fa60" +dependencies = [ + "form_urlencoded", + "futures-util", + "librespot-core", + "librespot-playback", + "librespot-protocol", + "log", + "protobuf", + "rand", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "librespot-core" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4c76303efcf949a59f9380220ca420c4d72fa32dbb3641a0079f429cc5e44e7" +dependencies = [ + "aes", + "base64 0.22.1", + "byteorder", + "bytes", + "data-encoding", + "form_urlencoded", + "futures-core", + "futures-util", + "governor", + "hmac", + "http 1.1.0", + "http-body-util", + "httparse", + "hyper 1.4.1", + "hyper-proxy2", + "hyper-rustls 0.27.2", + "hyper-util", + "librespot-oauth", + "librespot-protocol", + "log", + "nonzero_ext", + "num-bigint", + "num-derive", + "num-integer", + "num-traits", + "once_cell", + "parking_lot", + "pbkdf2", + "pin-project-lite", + "priority-queue", + "protobuf", + "quick-xml", + "rand", + "rsa", + "serde", + "serde_json", + "sha1", + "shannon", + "sysinfo", + "thiserror", + "time", + "tokio", + "tokio-stream", + "tokio-tungstenite 0.24.0", + "tokio-util", + "url", + "uuid", + "vergen-gitcl", +] + +[[package]] +name = "librespot-discovery" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a952d28c775562b9b6039102c0e3a834cb31157fccb2f2a68a26dc4397fea8" +dependencies = [ + "aes", + "base64 0.22.1", + "bytes", + "ctr", + "form_urlencoded", + "futures-core", + "futures-util", + "hmac", + "http-body-util", + "hyper 1.4.1", + "hyper-util", + "librespot-core", + "log", + "rand", + "serde_json", + "serde_repr", + "sha1", + "thiserror", + "tokio", +] + +[[package]] +name = "librespot-metadata" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cf6d5c46a401b1dd3e062ebdce959aa694bbae1039841756545d2e9c4f8be5f" +dependencies = [ + "async-trait", + "bytes", + "librespot-core", + "librespot-protocol", + "log", + "protobuf", + "serde", + "serde_json", + "thiserror", + "uuid", +] + +[[package]] +name = "librespot-oauth" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00dcad779aa6c3b442e493e2a40ca83a5c5fcf38a65c05b026c3587bd4f8d14f" +dependencies = [ + "log", + "oauth2", + "thiserror", + "url", +] + +[[package]] +name = "librespot-playback" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ed1f776a04c8c9275407f8d4df034f2615ea729ec6c6d0fa69f423fc571df64" +dependencies = [ + "cpal", + "futures-util", + "librespot-audio", + "librespot-core", + "librespot-metadata", + "log", + "parking_lot", + "rand", + "rand_distr", + "rodio", + "shell-words", + "symphonia", + "thiserror", + "tokio", + "zerocopy 0.7.35", +] + +[[package]] +name = "librespot-protocol" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80802f52b5a1b3a2157454e6aca483a627fbf7b942e0a5fea037ebf3ed8b0546" +dependencies = [ + "protobuf", + "protobuf-codegen", +] + [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -1137,6 +2148,39 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "md-5" version = "0.10.6" @@ -1219,16 +2263,27 @@ dependencies = [ "chrono", "dotenv", "form_urlencoded", + "librespot", "poise", "rand", "regex", "serenity", + "songbird", "sqlx", "tenorv2", "tokio", "tokio-cron-scheduler", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + [[package]] name = "native-tls" version = "0.2.12" @@ -1241,11 +2296,64 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] +[[package]] +name = "ndk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +dependencies = [ + "bitflags 2.6.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "no-std-compat" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df270209a7f04d62459240d890ecb792714d5db12c92937823574a09930276b4" + +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -1256,6 +2364,42 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "rand", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -1273,6 +2417,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -1287,7 +2440,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -1320,6 +2473,66 @@ dependencies = [ "libm", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "oauth2" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" +dependencies = [ + "base64 0.13.1", + "chrono", + "getrandom", + "http 0.2.12", + "rand", + "reqwest 0.11.27", + "serde", + "serde_json", + "serde_path_to_error", + "sha2", + "thiserror", + "url", +] + [[package]] name = "object" version = "0.36.2" @@ -1329,12 +2542,41 @@ dependencies = [ "memchr", ] +[[package]] +name = "oboe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" +dependencies = [ + "jni", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" +dependencies = [ + "cc", +] + [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.66" @@ -1358,7 +2600,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -1379,6 +2621,21 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking" version = "2.2.0" @@ -1401,10 +2658,13 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ + "backtrace", "cfg-if", "libc", + "petgraph", "redox_syscall 0.5.3", "smallvec", + "thread-id", "windows-targets 0.52.6", ] @@ -1414,6 +2674,25 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "patricia_tree" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f2f4539bffe53fc4b4da301df49d114b845b077bd5727b7fe2bd9d8df2ae68" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -1429,6 +2708,16 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -1446,7 +2735,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -1488,6 +2777,36 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "pnet_base" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_macros" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.87", +] + +[[package]] +name = "pnet_macros_support" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56" +dependencies = [ + "pnet_base", +] + [[package]] name = "poise" version = "0.6.1" @@ -1511,12 +2830,41 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fa2c123c961e78315cd3deac7663177f12be4460f5440dbf62a7ed37b1effea" dependencies = [ - "darling", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + [[package]] name = "powerfmt" version = "0.2.0" @@ -1532,6 +2880,45 @@ dependencies = [ "zerocopy 0.6.6", ] +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.87", +] + +[[package]] +name = "primal-check" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" +dependencies = [ + "num-integer", +] + +[[package]] +name = "priority-queue" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714c75db297bc88a63783ffc6ab9f830698a6705aa0201416931759ef4c8183d" +dependencies = [ + "autocfg", + "equivalent", + "indexmap", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.86" @@ -1541,6 +2928,57 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "protobuf" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror", +] + +[[package]] +name = "protobuf-codegen" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e26b833f144769a30e04b1db0146b2aaa53fd2fd83acf10a6b5f996606c18144" +dependencies = [ + "anyhow", + "once_cell", + "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror", +] + +[[package]] +name = "protobuf-parse" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322330e133eab455718444b4e033ebfac7c6528972c784fcde28d2cc783c6257" +dependencies = [ + "anyhow", + "indexmap", + "log", + "protobuf", + "protobuf-support", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252" +dependencies = [ + "thiserror", +] + [[package]] name = "pulldown-cmark" version = "0.9.6" @@ -1552,6 +2990,16 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" version = "1.0.36" @@ -1591,6 +3039,25 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "realfft" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390252372b7f2aac8360fc5e72eba10136b166d6faeed97e6d0c8324eb99b2b1" +dependencies = [ + "rustfft", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1617,8 +3084,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -1629,9 +3105,15 @@ checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" @@ -1725,6 +3207,21 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + [[package]] name = "ring" version = "0.17.8" @@ -1735,11 +3232,31 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin", - "untrusted", + "spin 0.9.8", + "untrusted 0.9.0", "windows-sys 0.52.0", ] +[[package]] +name = "ringbuf" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726bb493fe9cac765e8f96a144c3a8396bdf766dedad22e504b70b908dcbceb4" +dependencies = [ + "crossbeam-utils", + "portable-atomic", +] + +[[package]] +name = "rodio" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" +dependencies = [ + "cpal", + "thiserror", +] + [[package]] name = "rsa" version = "0.9.6" @@ -1760,12 +3277,54 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rubato" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5d18b486e7d29a408ef3f825bc1327d8f87af091c987ca2f5b734625940e234" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "realfft", +] + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustfft" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "primal-check", + "strength_reduce", + "transpose", + "version_check", +] + [[package]] name = "rustix" version = "0.38.34" @@ -1779,6 +3338,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct", + "webpki", +] + [[package]] name = "rustls" version = "0.21.12" @@ -1786,7 +3357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring", + "ring 0.17.8", "rustls-webpki 0.101.7", "sct", ] @@ -1798,7 +3369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "ring", + "ring 0.17.8", "rustls-pki-types", "rustls-webpki 0.102.6", "subtle", @@ -1811,6 +3382,8 @@ version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ + "aws-lc-rs", + "log", "once_cell", "rustls-pki-types", "rustls-webpki 0.102.6", @@ -1818,6 +3391,43 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.2", + "rustls-pki-types", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.0.1", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -1839,9 +3449,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -1849,8 +3459,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -1859,9 +3469,29 @@ version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ - "ring", + "aws-lc-rs", + "ring 0.17.8", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "rusty_pool" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ed36cdb20de66d89a17ea04b8883fc7a386f2cf877aaedca5005583ce4876ff" +dependencies = [ + "crossbeam-channel", + "futures", + "futures-channel", + "futures-executor", + "num_cpus", ] [[package]] @@ -1870,6 +3500,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1888,6 +3527,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -1900,8 +3545,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -1921,7 +3566,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -1929,9 +3587,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -1955,6 +3613,27 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-aux" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d2e8bfba469d06512e11e3311d4d051a4a387a5b42d010404fecf3200321c95" +dependencies = [ + "chrono", + "serde", + "serde_json", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_cow" version = "0.1.2" @@ -1972,7 +3651,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -1987,6 +3666,27 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2025,13 +3725,26 @@ dependencies = [ "serde_json", "time", "tokio", - "tokio-tungstenite", + "tokio-tungstenite 0.21.0", "tracing", "typemap_rev", "typesize", "url", ] +[[package]] +name = "serenity-voice-model" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "593682f6155d07c8b331b3d1060f5aab7e6796caca9f2f66bd9e6855c880e06b" +dependencies = [ + "bitflags 2.6.0", + "num-traits", + "serde", + "serde_json", + "serde_repr", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2054,6 +3767,57 @@ dependencies = [ "digest", ] +[[package]] +name = "shannon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ea5b41c9427b56caa7b808cb548a04fb50bb5b9e98590b53f28064ff4174561" +dependencies = [ + "byteorder", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "shorthand" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "474f77f985d8212610f170332eaf173e768404c0c1d4deb041f32c297cf18931" +dependencies = [ + "from_map", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "2.2.0" @@ -2107,6 +3871,62 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "songbird" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30c6bde67a7ba20c8d9abefa35dfbb4f7abb570b344af73c201626033fb64703" +dependencies = [ + "aead", + "aes-gcm", + "async-trait", + "audiopus", + "byteorder", + "bytes", + "chacha20poly1305", + "crypto_secretbox", + "dashmap", + "derivative", + "discortp", + "flume", + "futures", + "nohash-hasher", + "once_cell", + "parking_lot", + "pin-project", + "rand", + "reqwest 0.11.27", + "ringbuf", + "rubato", + "rusty_pool", + "serde", + "serde-aux", + "serde_json", + "serenity", + "serenity-voice-model", + "socket2", + "stream_lib", + "streamcatcher", + "symphonia", + "symphonia-core", + "tokio", + "tokio-tungstenite 0.21.0", + "tokio-util", + "tracing", + "tracing-futures", + "twilight-gateway", + "typemap_rev", + "typenum", + "url", + "uuid", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" @@ -2116,6 +3936,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.7.3" @@ -2198,7 +4027,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -2209,7 +4038,7 @@ checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" dependencies = [ "dotenvy", "either", - "heck", + "heck 0.5.0", "hex", "once_cell", "proc-macro2", @@ -2221,7 +4050,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.72", + "syn 2.0.87", "tempfile", "tokio", "url", @@ -2330,6 +4159,49 @@ dependencies = [ "url", ] +[[package]] +name = "stable-vec" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1dff32a2ce087283bec878419027cebd888760d8760b2941ad0843531dc9ec8" +dependencies = [ + "no-std-compat 0.2.0", +] + +[[package]] +name = "stream_lib" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa3f10eb5a7054e17abf61d310e4e29108187a847591c63c4c79b6a74898a5a7" +dependencies = [ + "bytes", + "futures-core", + "futures-util", + "hls_m3u8", + "patricia_tree", + "reqwest 0.11.27", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "streamcatcher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71664755c349abb0758fda6218fb2d2391ca2a73f9302c03b145491db4fcea29" +dependencies = [ + "crossbeam-utils", + "futures-util", + "loom", +] + +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + [[package]] name = "stringprep" version = "0.1.5" @@ -2341,18 +4213,129 @@ dependencies = [ "unicode-properties", ] +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "530efb820d53b712f4e347916c5e7ed20deb76a4f0457943b3182fb889b06d2c" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6e163a520367c465f59e0a61a23cfae3b10b6546d78b6f672a382be79f7110" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "symphonia" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" +dependencies = [ + "lazy_static", + "symphonia-bundle-mp3", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-ogg", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-core" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", +] + +[[package]] +name = "symphonia-format-ogg" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-metadata" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-utils-xiph" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "syn" version = "1.0.109" @@ -2366,9 +4349,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -2390,6 +4373,19 @@ dependencies = [ "futures-core", ] +[[package]] +name = "sysinfo" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "windows 0.57.0", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -2397,7 +4393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.5.0", ] @@ -2408,7 +4404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -2479,7 +4475,27 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", +] + +[[package]] +name = "thread-id" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe8f25bbdd100db7e1d34acf7fd2dc59c4bf8f7483f505eaa7d4f12f76cc0ea" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] @@ -2490,7 +4506,9 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -2538,7 +4556,9 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -2567,7 +4587,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -2580,6 +4600,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.9", + "tokio", + "webpki", +] + [[package]] name = "tokio-rustls" version = "0.24.1" @@ -2623,6 +4654,22 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +dependencies = [ + "futures-util", + "log", + "rustls 0.20.9", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.23.4", + "tungstenite 0.18.0", + "webpki", +] + [[package]] name = "tokio-tungstenite" version = "0.21.0" @@ -2635,10 +4682,26 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", - "tungstenite", + "tungstenite 0.21.0", "webpki-roots 0.26.3", ] +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.12", + "rustls-native-certs 0.8.1", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tungstenite 0.24.0", +] + [[package]] name = "tokio-util" version = "0.7.11" @@ -2652,6 +4715,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -2699,7 +4779,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -2709,6 +4789,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "transpose" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" +dependencies = [ + "num-integer", + "strength_reduce", ] [[package]] @@ -2723,6 +4853,27 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" +dependencies = [ + "base64 0.13.1", + "byteorder", + "bytes", + "http 0.2.12", + "httparse", + "log", + "rand", + "rustls 0.20.9", + "sha1", + "thiserror", + "url", + "utf-8", + "webpki", +] + [[package]] name = "tungstenite" version = "0.21.0" @@ -2744,6 +4895,69 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.1.0", + "httparse", + "log", + "rand", + "rustls 0.23.12", + "rustls-pki-types", + "sha1", + "thiserror", + "utf-8", +] + +[[package]] +name = "twilight-gateway" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30be5c7e2b13b4a59e0f93344c070c23404279a318a324eece1f4384ead47d86" +dependencies = [ + "bitflags 1.3.2", + "futures-util", + "rand", + "rustls 0.20.9", + "rustls-native-certs 0.6.3", + "serde", + "serde_json", + "tokio", + "tokio-tungstenite 0.18.0", + "tracing", + "twilight-gateway-queue", + "twilight-model", +] + +[[package]] +name = "twilight-gateway-queue" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3073747da8e1d09bc5383eed750451c9534021c8206a20092405b9855b3cb35a" +dependencies = [ + "tokio", + "tracing", +] + +[[package]] +name = "twilight-model" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276bd50f4817b3b421395afac89f5d7b61fdfd0f00a28b2a7db983e4878b4a1a" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde-value", + "serde_repr", + "time", +] + [[package]] name = "typemap_rev" version = "0.3.0" @@ -2782,7 +4996,7 @@ checksum = "905e88c2a4cc27686bd57e495121d451f027e441388a67f773be729ad4be1ea8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -2821,12 +5035,40 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unicode_categories" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -2851,6 +5093,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.10.0" @@ -2858,14 +5106,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", + "rand", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vergen" +version = "9.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f25fc8f8f05df455c7941e87f093ad22522a9ff33d7a027774815acf6f0639" +dependencies = [ + "anyhow", + "derive_builder 0.20.2", + "rustversion", + "time", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0227006d09f98ab00ea69e9a5e055e676a813cfbed4232986176c86a6080b997" +dependencies = [ + "anyhow", + "derive_builder 0.20.2", + "rustversion", + "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0c767e6751c09fc85cde58722cf2f1007e80e4c8d5a4321fc90d83dc54ca147" +dependencies = [ + "anyhow", + "derive_builder 0.20.2", + "rustversion", +] + [[package]] name = "version_check" version = "0.9.5" @@ -2924,7 +5217,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -2958,7 +5251,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2992,6 +5285,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -3007,6 +5310,18 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "whoami" version = "1.5.1" @@ -3017,13 +5332,64 @@ dependencies = [ "wasite", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", ] [[package]] @@ -3035,17 +5401,70 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-strings", "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -3061,10 +5480,19 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3083,6 +5511,30 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -3114,6 +5566,12 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3126,6 +5584,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3138,6 +5602,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3156,6 +5626,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3168,6 +5644,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3180,6 +5662,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3192,6 +5680,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3204,6 +5698,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" @@ -3230,6 +5733,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive 0.7.35", ] @@ -3241,7 +5745,7 @@ checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] @@ -3252,7 +5756,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.87", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1a16780..6f16d12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,8 @@ chrono = "0.4.38" sqlx = {version="0.8.2", features=["runtime-tokio", "sqlite"]} form_urlencoded = "1.2.1" tenorv2 = { path = "./tenor-v2/tenorv2" } +librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] } +songbird = "0.4.6" [features] DEBUG = [] diff --git a/makefile b/makefile index 7815468..6b47a53 100644 --- a/makefile +++ b/makefile @@ -1,11 +1,11 @@ dev: - cargo build --features DEBUG + cargo build --features DEBUG,GUILD_COMMAND release: cargo build --release --features RELEASE run: - cargo build --features DEBUG + cargo build --features DEBUG,GUILD_COMMAND ./target/debug/moover_rust run_rel: From 92b7bd64bf4637f7ead212ab0d4071b175ba6d5e Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Mon, 9 Dec 2024 15:40:46 +0100 Subject: [PATCH 05/19] feat: connect command implementation --- src/commands/mod.rs | 3 + src/commands/voice/mod.rs | 1 + src/commands/voice/spotify/mod.rs | 1 + src/commands/voice/spotify/player.rs | 159 +++++++++++++++++++++++++++ src/main.rs | 25 +++-- src/util/utilities.rs | 27 ++++- 6 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 src/commands/voice/mod.rs create mode 100644 src/commands/voice/spotify/mod.rs create mode 100644 src/commands/voice/spotify/player.rs diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 440afec..d680d50 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,7 +1,10 @@ pub use moover::*; pub use notice::*; pub use user_interactions::*; +pub use voice::*; pub mod moover; pub mod notice; pub mod user_interactions; +pub mod other; +pub mod voice; diff --git a/src/commands/voice/mod.rs b/src/commands/voice/mod.rs new file mode 100644 index 0000000..9c66493 --- /dev/null +++ b/src/commands/voice/mod.rs @@ -0,0 +1 @@ +pub mod spotify; \ No newline at end of file diff --git a/src/commands/voice/spotify/mod.rs b/src/commands/voice/spotify/mod.rs new file mode 100644 index 0000000..d44230b --- /dev/null +++ b/src/commands/voice/spotify/mod.rs @@ -0,0 +1 @@ +pub mod player; \ No newline at end of file diff --git a/src/commands/voice/spotify/player.rs b/src/commands/voice/spotify/player.rs new file mode 100644 index 0000000..37e9a16 --- /dev/null +++ b/src/commands/voice/spotify/player.rs @@ -0,0 +1,159 @@ +use poise; +use serenity::{all::ChannelId, async_trait}; +use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; +use songbird::TrackEvent; + +use crate::util::debug::send_error; +use crate::{types::{Context, Error}, util::utilities::get_channel_by_name}; + +use serenity::all::User; + +#[poise::command( + slash_command, + description_localized("en-US", "Play song") +)] +pub async fn play(ctx: Context<'_>, + #[description = "Song: "] + _url: String +) -> Result<(), Error> { + + ctx.reply("Done!").await?; + Ok(()) +} + + + +#[poise::command( + slash_command, + description_localized("en-US", "Headpat all your friends!") +)] +pub async fn headpat(ctx: Context<'_>, + #[description = "Who is the lucky one?"] + user: User +) -> Result<(), Error> { + let _title = "HEADPATS!"; + let _desc = format!("{} headpats {}", ctx.author(), user); + // send_with_embed(ctx, "headpat", &title, &desc).await?; + ctx.reply("Done!").await?; + Ok(()) +} + + +#[poise::command( + slash_command, + description_localized("en-US", "Connect to channel") +)] +pub async fn connect(ctx: Context<'_>, + #[autocomplete = "autocomplete_channel"] + #[description = "Voice channel name: "] + name: Option +) -> Result<(), Error> { + + if ctx.guild().is_none() { + ctx.reply("Can't use this outside of guild").await?; + return Ok(()) + } + + let channel: ChannelId; + if name.is_none() || name.clone().unwrap() == "" { + // Ugly one liner since I don't know how to do this another way yet + // TODO fix please + let Some(voice_channel) = ctx.guild().unwrap().voice_states.get(&ctx.author().id).and_then(|voice_state| voice_state.channel_id) else { + ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; + return Ok(()) + }; + + channel = voice_channel; + } + else { + channel = match get_channel_by_name(ctx.guild().unwrap(), name.unwrap()) { + Some(channel) => channel, + None => { + ctx.reply("Channel with this name does not exist").await?; + return Ok(()); + } + }; + } + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + if let Ok(handler_lock) = manager.join(ctx.guild_id().unwrap(), channel).await { + let mut handler = handler_lock.lock().await; + handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); + } + + ctx.reply("Done!").await?; + Ok(()) +} + + +struct TrackErrorNotifier; + +#[async_trait] +impl VoiceEventHandler for TrackErrorNotifier { + async fn act(&self, ctx: &EventContext<'_>) -> Option { + if let EventContext::Track(track_list) = ctx { + for (state, handle) in *track_list { + println!( + "Track {:?} encountered an error: {:?}", + handle.uuid(), + state.playing + ); + } + } + + None + } +} + +async fn autocomplete_channel( + ctx: Context<'_>, + _partial: &str, +) -> Vec { + + use crate::util::utilities::get_vc_names; + match ctx.guild() { + Some(guild) => get_vc_names(guild), + None => [].to_vec() + } +} + +#[poise::command( + slash_command, + description_localized("en-US", "Disconnect from voice channel") +)] +async fn disconnect( + ctx: Context<'_> +) -> Result<(), Error> { + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply("Can't use this outside of guild").await?; + return Ok(()); + }; + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let has_handler = manager.get(guild_id).is_some(); + + if ! has_handler { + ctx.reply("I am not connected to a channel!").await?; + return Ok(()) + } + + match manager.remove(guild_id).await { + Ok(()) => { + ctx.reply("Disconnected").await?; + return Ok(()) + } + Err(e) => { + let _ = send_error(ctx.serenity_context().http.clone(), e.to_string()).await; + return Ok(()) + } + } +} diff --git a/src/main.rs b/src/main.rs index 59da021..abfaf56 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,9 +5,6 @@ use std::time::Duration; use std::error; use std::env; -use poise::samples::register_globally; - -use poise::samples::register_in_guild; use serenity::async_trait; use serenity::prelude::GatewayIntents; use serenity::client::Context; @@ -17,6 +14,7 @@ use serenity::Client; use dotenv::dotenv; +use songbird::SerenityInit; use tokio_cron_scheduler::{JobScheduler, Job}; mod message_handler; @@ -85,7 +83,9 @@ async fn main() -> anyhow::Result<()> { let options: poise::FrameworkOptions<(), Box> = poise::FrameworkOptions { commands: vec![ commands::say(), - commands::hug() + commands::hug(), + // commands::spotify::player::play(), + commands::spotify::player::connect(), ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), @@ -107,14 +107,20 @@ async fn main() -> anyhow::Result<()> { let framework = poise::Framework::builder() .setup(move |ctx, _ready, framework| { Box::pin(async move { + + #[cfg(feature="GUILD_COMMAND")] { + use poise::samples::register_in_guild; + use serenity::all::GuildId; + let debug_guild_id = env::var("DEBUG_GUILD_ID") .context("DEBUG_GUILD_ID not found in env")? .parse::().unwrap(); - - register_in_guild(ctx, &framework.options().commands, debug_guild_id).await?; + + register_in_guild(ctx, &framework.options().commands, GuildId::new(debug_guild_id)).await?; } #[cfg(not(feature="GUILD_COMMAND"))] { + use poise::samples::register_globally; register_globally(ctx, &framework.options().commands).await?; } Ok(()) @@ -130,11 +136,16 @@ async fn main() -> anyhow::Result<()> { let token = env::var(token_str).context("TOKEN not found in env")?; - let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT; + let intents = GatewayIntents::GUILD_MESSAGES + | GatewayIntents::MESSAGE_CONTENT + | GatewayIntents::GUILD_VOICE_STATES + | GatewayIntents::GUILD_MESSAGE_REACTIONS + | GatewayIntents::GUILD_MESSAGE_TYPING; let mut client = Client::builder(&token, intents) .event_handler(Handler) .framework(framework) + .register_songbird() .await .context("Failed to build client")?; diff --git a/src/util/utilities.rs b/src/util/utilities.rs index 8b5f470..3bac776 100644 --- a/src/util/utilities.rs +++ b/src/util/utilities.rs @@ -1,7 +1,8 @@ use std::sync::Arc; -use serenity::{all::{ChannelId, CreateMessage, GuildId, Message}, http::Http}; +use serenity::{all::{ChannelId, ChannelType, CreateMessage, GuildChannel, GuildId, GuildRef, Message}, http::Http}; +use crate::types; use anyhow::Context; pub async fn get_system_channel(guild_id: GuildId, http: &Http) -> anyhow::Result { @@ -13,4 +14,28 @@ pub async fn replace_msg(http: Arc, msg: Message, content: String) -> Resu msg.delete(http.clone()).await?; return ChannelId::new(msg.channel_id.get()).send_message(http.clone(), CreateMessage::new().content(content)).await; +} + +pub fn get_vc_names(guild: GuildRef) -> Vec { + + let mut result: Vec = [].to_vec(); + for (_, channel) in &guild.channels { + if channel.kind == ChannelType::Voice { + result.push(channel.name.clone()); + } + } + + result +} + +pub fn get_channel_by_name(guild: GuildRef, name: String) -> Option { + let mut result = None; + for (_, channel) in &guild.channels { + if channel.name == name { + result = Some(channel.id); + break; + } + } + + result } \ No newline at end of file From 800a0bcd3baa9e3eb6fb7bf9c91d62f18db5dd93 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 8 Dec 2024 18:08:53 +0100 Subject: [PATCH 06/19] future send error showcase --- src/commands/voice/spotify/player.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/commands/voice/spotify/player.rs b/src/commands/voice/spotify/player.rs index 37e9a16..9b3b9d5 100644 --- a/src/commands/voice/spotify/player.rs +++ b/src/commands/voice/spotify/player.rs @@ -56,6 +56,33 @@ pub async fn connect(ctx: Context<'_>, let channel: ChannelId; if name.is_none() || name.clone().unwrap() == "" { + // ERROR: <> + // !### This will work if you comment out one of the replies ###! + // let Some(guild) = ctx.guild() else { + // ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; + // return Ok(()) + // }; + + // let Some(voice_channel) = guild.voice_states.get(&ctx.author().id).and_then(|voice_state| voice_state.channel_id) else { + // ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; + // return Ok(()) + // }; + + // channel = voice_channel; + // !### ###! + + // This one liner works only if you comment out the reply + // channel = match ctx.guild().unwrap().voice_states.get(&ctx.author().id).and_then(|voice_state| voice_state.channel_id) { + // Some(channel) => channel, + // None => { + // // ERROR: <> + // // Will work if you comment this out + // ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; + // return Ok(()) + // } + // } + + // This one works // Ugly one liner since I don't know how to do this another way yet // TODO fix please let Some(voice_channel) = ctx.guild().unwrap().voice_states.get(&ctx.author().id).and_then(|voice_state| voice_state.channel_id) else { From 18927e7493b02fc9814187365b113f42be06619b Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Tue, 17 Dec 2024 15:28:52 +0100 Subject: [PATCH 07/19] feat: implemented local song player --- Cargo.toml | 2 +- makefile | 5 +- src/commands/voice/mod.rs | 2 +- src/commands/voice/player.rs | 255 +++++++++++++++++++++ src/commands/voice/soundcloud/souncloud.rs | 0 src/commands/voice/spotify/spotify.rs | 0 src/main.rs | 13 +- src/util/mod.rs | 3 +- src/util/poise_context_extension.rs | 22 ++ src/util/utilities.rs | 33 ++- 10 files changed, 317 insertions(+), 18 deletions(-) create mode 100644 src/commands/voice/player.rs create mode 100644 src/commands/voice/soundcloud/souncloud.rs create mode 100644 src/commands/voice/spotify/spotify.rs create mode 100644 src/util/poise_context_extension.rs diff --git a/Cargo.toml b/Cargo.toml index 6f16d12..b53e91f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ sqlx = {version="0.8.2", features=["runtime-tokio", "sqlite"]} form_urlencoded = "1.2.1" tenorv2 = { path = "./tenor-v2/tenorv2" } librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] } -songbird = "0.4.6" +songbird = { version = "0.4.6", features = ["driver"] } [features] DEBUG = [] diff --git a/makefile b/makefile index 6b47a53..ad262f5 100644 --- a/makefile +++ b/makefile @@ -4,9 +4,8 @@ dev: release: cargo build --release --features RELEASE -run: - cargo build --features DEBUG,GUILD_COMMAND +run: dev ./target/debug/moover_rust -run_rel: +run_rel: release ./target/release/moover_rust \ No newline at end of file diff --git a/src/commands/voice/mod.rs b/src/commands/voice/mod.rs index 9c66493..d44230b 100644 --- a/src/commands/voice/mod.rs +++ b/src/commands/voice/mod.rs @@ -1 +1 @@ -pub mod spotify; \ No newline at end of file +pub mod player; \ No newline at end of file diff --git a/src/commands/voice/player.rs b/src/commands/voice/player.rs new file mode 100644 index 0000000..ddffb7d --- /dev/null +++ b/src/commands/voice/player.rs @@ -0,0 +1,255 @@ +use std::vec; + +use serenity::{all::ChannelId, async_trait}; +use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; +use songbird::input::{File, Input}; +use songbird::TrackEvent; + +use crate::util::debug::send_error; +use crate::util::poise_context_extension::ContextExt; +use crate::util::utilities::get_local_songs; +use crate::{types::{Context, Error}, util::utilities::get_channel_by_name}; + +#[poise::command( + slash_command, + description_localized("en-US", "Play song") +)] +pub async fn play(ctx: Context<'_>, + #[description = "Song: "] + _url: String +) -> Result<(), Error> { + + ctx.reply("Done!").await?; + Ok(()) +} + +/// Returns either voice channel to which the user is currently connected to or the one passed via name +async fn get_voice_channel(ctx: &Context<'_>, name: Option) -> Result { + if name.is_none() || name.as_ref().is_some_and(|n| n.is_empty()) { + match ctx.guild().and_then(|guild| + guild.voice_states.get(&ctx.author().id).and_then(|voice_state| + voice_state.channel_id + ) + ) { + Some(c) => Ok(c), + None => Err("You must be in a voice channel or specify explicit voice channel by name".to_string()) + } + } + else { + match ctx.guild().and_then(|guild| + get_channel_by_name(guild, name.unwrap()) + ) { + Some(c) => Ok(c), + None => Err("Channel with this name does not exist".to_string()) + } + } +} + +#[poise::command( + slash_command, + description_localized("en-US", "Connect to channel") +)] +pub async fn connect(ctx: Context<'_>, + #[autocomplete = "autocomplete_channel"] + #[description = "Voice channel name: "] + name: Option +) -> Result<(), Error> { + + if ctx.guild().is_none() { + ctx.reply_ephemeral("Can't use this outside of guild").await?; + return Ok(()); + } + + let voice_channel = match get_voice_channel(&ctx, name).await { + Ok(c) => c, + Err(e) => { + ctx.reply_ephemeral(e.as_str()).await?; + return Ok(()) + } + }; + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + if let Ok(handler_lock) = manager.join(guild_id, voice_channel).await { + let mut handler = handler_lock.lock().await; + handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); + } + + ctx.reply_ephemeral("Done!").await?; + Ok(()) +} + +struct TrackErrorNotifier; + +#[async_trait] +impl VoiceEventHandler for TrackErrorNotifier { + async fn act(&self, ctx: &EventContext<'_>) -> Option { + if let EventContext::Track(track_list) = ctx { + for (state, handle) in *track_list { + println!( + "Track {:?} encountered an error: {:?}", + handle.uuid(), + state.playing + ); + } + } + + None + } +} + +async fn autocomplete_channel( + ctx: Context<'_>, + _partial: &str, +) -> Vec { + + use crate::util::utilities::get_vc_names; + match ctx.guild() { + Some(guild) => get_vc_names(guild), + None => [].to_vec() + } +} + +#[poise::command( + slash_command, + description_localized("en-US", "Disconnect from voice channel") +)] +pub async fn disconnect( + ctx: Context<'_> +) -> Result<(), Error> { + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply("Can't use this outside of guild").await?; + return Ok(()); + }; + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let has_handler = manager.get(guild_id).is_some(); + + if ! has_handler { + ctx.reply("I am not connected to a channel!").await?; + return Ok(()) + } + + match manager.remove(guild_id).await { + Ok(()) => { + ctx.reply("Disconnected").await?; + return Ok(()) + } + Err(e) => { + let _ = send_error(ctx.serenity_context().http.clone(), e.to_string()).await; + return Ok(()) + } + } +} + +async fn autocomplete_song( + _ctx: Context<'_>, + partial: &str, +) -> Vec { + + match get_local_songs(partial) { + Ok(names) => names, + Err(_) => vec![] + } +} + +#[poise::command( + slash_command, + description_localized("en-US", "Connect to channel") +)] +pub async fn play_local(ctx: Context<'_>, + #[autocomplete = "autocomplete_channel"] + #[description = "Voice channel name: "] + _channel: Option, + #[autocomplete = "autocomplete_song"] + #[description = "Filename of local song: "] + file_name: String +) -> Result<(), Error> { + + if ctx.guild().is_none() { + ctx.reply_ephemeral("Can't use this outside of guild").await?; + return Ok(()); + } + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + + + if let Some(handler_lock) = manager.get(guild_id) { + let mut handler = handler_lock.lock().await; + + let input_file = File::new(format!("/home/emil/Music/{file_name}")); + let input = Input::Lazy(Box::new(input_file)); + let _ = handler.play_input(input); + } + else { + + ctx.reply_ephemeral("Not in a voice channel").await?; + return Ok(()) + } + + ctx.reply_ephemeral("Done!").await?; + Ok(()) +} + +// #[poise::command( +// slash_command, +// description_localized("en-US", "Connect to channel") +// )] +// pub async fn play_local(ctx: Context<'_>, +// #[autocomplete = "autocomplete_song"] +// #[description = "Voice channel name: "] +// file_name: String +// ) -> Result<(), Error> { + +// if ctx.guild().is_none() { +// ctx.reply_ephemeral("Can't use this outside of guild").await?; +// return Ok(()); +// } + +// let manager = songbird::get(ctx.serenity_context()) +// .await +// .expect("Songbird Voice client placed in at initialisation.") +// .clone(); + +// let Some(guild_id) = ctx.guild_id() else { +// ctx.reply_ephemeral("Guild id not found").await?; +// return Ok(()) +// }; + +// if let Some(handler_lock) = manager.get(guild_id) { +// let mut handler = handler_lock.lock().await; + +// let input_file = File::new(format!("/home/emil/Music/{file_name}")); +// let input = Input::Lazy(Box::new(input_file)); +// let _ = handler.play_input(input); +// } +// else { +// ctx.reply_ephemeral("Not in a voice channel").await?; +// return Ok(()) +// } + +// ctx.reply_ephemeral("Done!").await?; +// Ok(()) +// } diff --git a/src/commands/voice/soundcloud/souncloud.rs b/src/commands/voice/soundcloud/souncloud.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/commands/voice/spotify/spotify.rs b/src/commands/voice/spotify/spotify.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs index abfaf56..e4d139f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,7 +56,7 @@ impl EventHandler for Handler { #[cfg(feature="RELEASE")] { use util::debug::hello; - hello(ctx.http.clone()).await; + let _ = hello(ctx.http.clone()).await; } let sched = JobScheduler::new().await.unwrap(); @@ -84,8 +84,9 @@ async fn main() -> anyhow::Result<()> { commands: vec![ commands::say(), commands::hug(), - // commands::spotify::player::play(), - commands::spotify::player::connect(), + commands::player::play_local(), + commands::player::connect(), + commands::player::disconnect(), ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), @@ -107,7 +108,6 @@ async fn main() -> anyhow::Result<()> { let framework = poise::Framework::builder() .setup(move |ctx, _ready, framework| { Box::pin(async move { - #[cfg(feature="GUILD_COMMAND")] { use poise::samples::register_in_guild; @@ -119,10 +119,12 @@ async fn main() -> anyhow::Result<()> { register_in_guild(ctx, &framework.options().commands, GuildId::new(debug_guild_id)).await?; } + #[cfg(not(feature="GUILD_COMMAND"))] { use poise::samples::register_globally; register_globally(ctx, &framework.options().commands).await?; } + Ok(()) }) }) @@ -136,7 +138,8 @@ async fn main() -> anyhow::Result<()> { let token = env::var(token_str).context("TOKEN not found in env")?; - let intents = GatewayIntents::GUILD_MESSAGES + let intents = GatewayIntents::GUILDS + | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_VOICE_STATES | GatewayIntents::GUILD_MESSAGE_REACTIONS diff --git a/src/util/mod.rs b/src/util/mod.rs index a259bb4..f268cfa 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ pub mod debug; pub mod utilities; -pub mod gifs; \ No newline at end of file +pub mod gifs; +pub mod poise_context_extension; \ No newline at end of file diff --git a/src/util/poise_context_extension.rs b/src/util/poise_context_extension.rs new file mode 100644 index 0000000..39a9475 --- /dev/null +++ b/src/util/poise_context_extension.rs @@ -0,0 +1,22 @@ +use poise::CreateReply; +use serenity::async_trait; + +use crate::types::Context; + + +/// Trait to extend `Context` with additional methods. +#[async_trait] +pub trait ContextExt { + async fn reply_ephemeral(&self, content: &str) -> anyhow::Result<()>; +} + +#[async_trait] +impl ContextExt for Context<'_> { + async fn reply_ephemeral(&self, content: &str) -> anyhow::Result<()> { + self.send(CreateReply::default() + .ephemeral(true) + .content(content) + ).await?; + Ok(()) + } +} diff --git a/src/util/utilities.rs b/src/util/utilities.rs index 3bac776..c36912b 100644 --- a/src/util/utilities.rs +++ b/src/util/utilities.rs @@ -1,11 +1,9 @@ -use std::sync::Arc; +use std::{fs, io, path::Path, sync::Arc, vec}; -use serenity::{all::{ChannelId, ChannelType, CreateMessage, GuildChannel, GuildId, GuildRef, Message}, http::Http}; - -use crate::types; -use anyhow::Context; +use serenity::{all::{ChannelId, ChannelType, CreateMessage, GuildId, GuildRef, Message}, http::Http}; pub async fn get_system_channel(guild_id: GuildId, http: &Http) -> anyhow::Result { + use anyhow::Context; return http.get_guild(guild_id).await?.system_channel_id .context(format!("System channel of guild: {} not found", guild_id.get())); } @@ -31,11 +29,32 @@ pub fn get_vc_names(guild: GuildRef) -> Vec { pub fn get_channel_by_name(guild: GuildRef, name: String) -> Option { let mut result = None; for (_, channel) in &guild.channels { - if channel.name == name { + if channel.name.contains(&name) { result = Some(channel.id); break; } } result -} \ No newline at end of file +} + +pub fn get_local_songs(partial: &str) -> io::Result> { + let mut result: Vec = vec![]; + let path = Path::new("/home/emil/Music"); + for entry in fs::read_dir(path)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + continue; + } + + let name = entry.file_name(); + if name.to_str().is_some_and(|name| !name.to_lowercase().contains(&partial.to_lowercase())) { + continue; + } + + result.push(name.to_str().unwrap().into()); + } + + Ok(result) +} From 8a3edf32da5ef5bc5c03c3559f2c5201385396fd Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Tue, 17 Dec 2024 15:54:51 +0100 Subject: [PATCH 08/19] feat: removed the need to manualy connect if not in vc --- src/commands/voice/spotify/player.rs | 167 +++++++++++++++------------ src/main.rs | 1 - 2 files changed, 96 insertions(+), 72 deletions(-) diff --git a/src/commands/voice/spotify/player.rs b/src/commands/voice/spotify/player.rs index 9b3b9d5..5c00980 100644 --- a/src/commands/voice/spotify/player.rs +++ b/src/commands/voice/spotify/player.rs @@ -1,13 +1,18 @@ -use poise; +use std::vec; + +use poise::{self, CreateReply}; +use serenity::all::{CacheHttp, Guild, PartialGuild, UserId}; use serenity::{all::ChannelId, async_trait}; use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; +use songbird::input::{File, Input}; +use songbird::tracks::Track; use songbird::TrackEvent; use crate::util::debug::send_error; +use crate::util::poise_context_extension::ContextExt; +use crate::util::utilities::get_local_songs; use crate::{types::{Context, Error}, util::utilities::get_channel_by_name}; -use serenity::all::User; - #[poise::command( slash_command, description_localized("en-US", "Play song") @@ -21,24 +26,28 @@ pub async fn play(ctx: Context<'_>, Ok(()) } - - -#[poise::command( - slash_command, - description_localized("en-US", "Headpat all your friends!") -)] -pub async fn headpat(ctx: Context<'_>, - #[description = "Who is the lucky one?"] - user: User -) -> Result<(), Error> { - let _title = "HEADPATS!"; - let _desc = format!("{} headpats {}", ctx.author(), user); - // send_with_embed(ctx, "headpat", &title, &desc).await?; - ctx.reply("Done!").await?; - Ok(()) +/// Returns either voice channel to which the user is currently connected to or the one passed via name +async fn get_voice_channel(ctx: &Context<'_>, name: Option) -> Result { + if name.is_none() || name.as_ref().is_some_and(|n| n.is_empty()) { + match ctx.guild().and_then(|guild| + guild.voice_states.get(&ctx.author().id).and_then(|voice_state| + voice_state.channel_id + ) + ) { + Some(c) => Ok(c), + None => Err("You must be in a voice channel or specify explicit voice channel by name".to_string()) + } + } + else { + match ctx.guild().and_then(|guild| + get_channel_by_name(guild, name.unwrap()) + ) { + Some(c) => Ok(c), + None => Err("Channel with this name does not exist".to_string()) + } + } } - #[poise::command( slash_command, description_localized("en-US", "Connect to channel") @@ -50,73 +59,37 @@ pub async fn connect(ctx: Context<'_>, ) -> Result<(), Error> { if ctx.guild().is_none() { - ctx.reply("Can't use this outside of guild").await?; - return Ok(()) + ctx.reply_ephemeral("Can't use this outside of guild").await?; + return Ok(()); } - let channel: ChannelId; - if name.is_none() || name.clone().unwrap() == "" { - // ERROR: <> - // !### This will work if you comment out one of the replies ###! - // let Some(guild) = ctx.guild() else { - // ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; - // return Ok(()) - // }; - - // let Some(voice_channel) = guild.voice_states.get(&ctx.author().id).and_then(|voice_state| voice_state.channel_id) else { - // ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; - // return Ok(()) - // }; - - // channel = voice_channel; - // !### ###! - - // This one liner works only if you comment out the reply - // channel = match ctx.guild().unwrap().voice_states.get(&ctx.author().id).and_then(|voice_state| voice_state.channel_id) { - // Some(channel) => channel, - // None => { - // // ERROR: <> - // // Will work if you comment this out - // ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; - // return Ok(()) - // } - // } - - // This one works - // Ugly one liner since I don't know how to do this another way yet - // TODO fix please - let Some(voice_channel) = ctx.guild().unwrap().voice_states.get(&ctx.author().id).and_then(|voice_state| voice_state.channel_id) else { - ctx.reply("You must be in a voice channel or specify explicit voice channel by name").await?; + let voice_channel = match get_voice_channel(&ctx, name).await { + Ok(c) => c, + Err(e) => { + ctx.reply_ephemeral(e.as_str()).await?; return Ok(()) - }; - - channel = voice_channel; - } - else { - channel = match get_channel_by_name(ctx.guild().unwrap(), name.unwrap()) { - Some(channel) => channel, - None => { - ctx.reply("Channel with this name does not exist").await?; - return Ok(()); - } - }; - } + } + }; let manager = songbird::get(ctx.serenity_context()) .await .expect("Songbird Voice client placed in at initialisation.") .clone(); - if let Ok(handler_lock) = manager.join(ctx.guild_id().unwrap(), channel).await { + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + if let Ok(handler_lock) = manager.join(guild_id, voice_channel).await { let mut handler = handler_lock.lock().await; handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); } - ctx.reply("Done!").await?; + ctx.reply_ephemeral("Done!").await?; Ok(()) } - struct TrackErrorNotifier; #[async_trait] @@ -152,7 +125,7 @@ async fn autocomplete_channel( slash_command, description_localized("en-US", "Disconnect from voice channel") )] -async fn disconnect( +pub async fn disconnect( ctx: Context<'_> ) -> Result<(), Error> { @@ -184,3 +157,55 @@ async fn disconnect( } } } + +async fn autocomplete_song( + _ctx: Context<'_>, + partial: &str, +) -> Vec { + + match get_local_songs(partial) { + Ok(names) => names, + Err(_) => vec![] + } +} + +#[poise::command( + slash_command, + description_localized("en-US", "Connect to channel") +)] +pub async fn play_local(ctx: Context<'_>, + #[autocomplete = "autocomplete_song"] + #[description = "Voice channel name: "] + file_name: String +) -> Result<(), Error> { + + if ctx.guild().is_none() { + ctx.reply_ephemeral("Can't use this outside of guild").await?; + return Ok(()); + } + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + if let Some(handler_lock) = manager.get(guild_id) { + let mut handler = handler_lock.lock().await; + + let input_file = File::new(format!("/home/emil/Music/{file_name}")); + let input = Input::Lazy(Box::new(input_file)); + let _ = handler.play_input(input); + } + else { + ctx.reply_ephemeral("Not in a voice channel").await?; + return Ok(()) + } + + ctx.reply_ephemeral("Done!").await?; + Ok(()) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e4d139f..3eedf7d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -85,7 +85,6 @@ async fn main() -> anyhow::Result<()> { commands::say(), commands::hug(), commands::player::play_local(), - commands::player::connect(), commands::player::disconnect(), ], prefix_options: poise::PrefixFrameworkOptions { From 513f9a5ee67c8757db30f3f9ab267216069e731c Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Tue, 31 Dec 2024 12:20:44 +0100 Subject: [PATCH 09/19] chore: updated cargo.toml --- Cargo.lock | 1439 +--------------------------------------------------- Cargo.toml | 2 +- 2 files changed, 16 insertions(+), 1425 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d901a7a..dd16aa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -79,28 +79,6 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" -[[package]] -name = "alsa" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" -dependencies = [ - "alsa-sys", - "bitflags 2.6.0", - "cfg-if", - "libc", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -116,55 +94,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" -dependencies = [ - "anstyle", - "windows-sys 0.59.0", -] - [[package]] name = "anyhow" version = "1.0.94" @@ -232,32 +161,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "aws-lc-rs" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" -dependencies = [ - "aws-lc-sys", - "paste", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" -dependencies = [ - "bindgen 0.69.5", - "cc", - "cmake", - "dunce", - "fs_extra", - "libc", - "paste", -] - [[package]] name = "backtrace" version = "0.3.73" @@ -297,47 +200,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.87", - "which", -] - -[[package]] -name = "bindgen" -version = "0.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.87", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -428,25 +290,6 @@ name = "cc" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" -dependencies = [ - "jobserver", - "libc", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] [[package]] name = "cfg-if" @@ -504,17 +347,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "cmake" version = "0.1.52" @@ -524,22 +356,6 @@ dependencies = [ "cc", ] -[[package]] -name = "colorchoice" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -571,65 +387,12 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "coreaudio-rs" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" -dependencies = [ - "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" -dependencies = [ - "bindgen 0.70.1", -] - -[[package]] -name = "cpal" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" -dependencies = [ - "alsa", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni", - "js-sys", - "libc", - "mach2", - "ndk", - "ndk-context", - "oboe", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.54.0", -] - [[package]] name = "cpufeatures" version = "0.2.12" @@ -815,12 +578,6 @@ dependencies = [ "serde", ] -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - [[package]] name = "data-encoding" version = "2.6.0" @@ -866,21 +623,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" dependencies = [ "darling 0.10.2", - "derive_builder_core 0.9.0", + "derive_builder_core", "proc-macro2", "quote", "syn 1.0.109", ] -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - [[package]] name = "derive_builder_core" version = "0.9.0" @@ -893,28 +641,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling 0.20.10", - "proc-macro2", - "quote", - "syn 2.0.87", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core 0.20.2", - "syn 2.0.87", -] - [[package]] name = "derive_more" version = "0.99.18" @@ -962,12 +688,6 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "either" version = "1.13.0" @@ -986,28 +706,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_filter" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" -dependencies = [ - "log", -] - -[[package]] -name = "env_logger" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1061,12 +759,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "flate2" version = "1.0.30" @@ -1128,12 +820,6 @@ dependencies = [ "hashmap_derive", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures" version = "0.3.30" @@ -1216,12 +902,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - [[package]] name = "futures-util" version = "0.3.30" @@ -1259,7 +939,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows 0.48.0", + "windows", ] [[package]] @@ -1273,15 +953,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -1317,24 +988,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "governor" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" -dependencies = [ - "cfg-if", - "futures", - "futures-timer", - "no-std-compat 0.4.1", - "nonzero_ext", - "parking_lot", - "portable-atomic", - "rand", - "smallvec", - "spinning_top", -] - [[package]] name = "h2" version = "0.3.26" @@ -1403,30 +1056,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "headers" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http 1.1.0", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" -dependencies = [ - "http 1.1.0", -] - [[package]] name = "heck" version = "0.3.3" @@ -1469,7 +1098,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b906521a5b0e6d2ec07ea0bb855d92a1db30b48812744a645a3b2a1405cb8159" dependencies = [ - "derive_builder 0.9.0", + "derive_builder", "derive_more", "hex", "shorthand", @@ -1564,12 +1193,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.30" @@ -1607,7 +1230,6 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "httparse", - "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -1615,27 +1237,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-proxy2" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9043b7b23fb0bc4a1c7014c27b50a4fc42cc76206f71d34fc0dfe5b28ddc3faf" -dependencies = [ - "bytes", - "futures-util", - "headers", - "http 1.1.0", - "hyper 1.4.1", - "hyper-rustls 0.26.0", - "hyper-util", - "pin-project-lite", - "rustls-native-certs 0.7.3", - "tokio", - "tokio-rustls 0.25.0", - "tower-service", - "webpki", -] - [[package]] name = "hyper-rustls" version = "0.24.2" @@ -1650,25 +1251,6 @@ dependencies = [ "tokio-rustls 0.24.1", ] -[[package]] -name = "hyper-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.4.1", - "hyper-util", - "log", - "rustls 0.22.4", - "rustls-native-certs 0.7.3", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.25.0", - "tower-service", -] - [[package]] name = "hyper-rustls" version = "0.27.2" @@ -1679,9 +1261,7 @@ dependencies = [ "http 1.1.0", "hyper 1.4.1", "hyper-util", - "log", "rustls 0.23.12", - "rustls-native-certs 0.7.3", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -1735,7 +1315,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core", ] [[package]] @@ -1788,67 +1368,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.69" @@ -1873,248 +1398,18 @@ dependencies = [ "spin 0.9.8", ] -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - [[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "librespot" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96e4b1f97b2767e35327b8443dcc1d2360a83c1c09a8686bf824ff61ab50f04c" -dependencies = [ - "data-encoding", - "env_logger", - "futures-util", - "getopts", - "librespot-audio", - "librespot-connect", - "librespot-core", - "librespot-discovery", - "librespot-metadata", - "librespot-oauth", - "librespot-playback", - "librespot-protocol", - "log", - "sha1", - "sysinfo", - "thiserror", - "tokio", - "url", -] - -[[package]] -name = "librespot-audio" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e07566fe7553042936c61bbdd9bedb524114a904aa7f9738e266c641468bab8" -dependencies = [ - "aes", - "bytes", - "ctr", - "futures-util", - "http-body-util", - "hyper 1.4.1", - "hyper-util", - "librespot-core", - "log", - "parking_lot", - "tempfile", - "thiserror", - "tokio", -] - -[[package]] -name = "librespot-connect" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce3a5634669ce051a425cff5437a474831111df045fd5a2bb37fabe316fa60" -dependencies = [ - "form_urlencoded", - "futures-util", - "librespot-core", - "librespot-playback", - "librespot-protocol", - "log", - "protobuf", - "rand", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-stream", -] - -[[package]] -name = "librespot-core" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4c76303efcf949a59f9380220ca420c4d72fa32dbb3641a0079f429cc5e44e7" -dependencies = [ - "aes", - "base64 0.22.1", - "byteorder", - "bytes", - "data-encoding", - "form_urlencoded", - "futures-core", - "futures-util", - "governor", - "hmac", - "http 1.1.0", - "http-body-util", - "httparse", - "hyper 1.4.1", - "hyper-proxy2", - "hyper-rustls 0.27.2", - "hyper-util", - "librespot-oauth", - "librespot-protocol", - "log", - "nonzero_ext", - "num-bigint", - "num-derive", - "num-integer", - "num-traits", - "once_cell", - "parking_lot", - "pbkdf2", - "pin-project-lite", - "priority-queue", - "protobuf", - "quick-xml", - "rand", - "rsa", - "serde", - "serde_json", - "sha1", - "shannon", - "sysinfo", - "thiserror", - "time", - "tokio", - "tokio-stream", - "tokio-tungstenite 0.24.0", - "tokio-util", - "url", - "uuid", - "vergen-gitcl", -] - -[[package]] -name = "librespot-discovery" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a952d28c775562b9b6039102c0e3a834cb31157fccb2f2a68a26dc4397fea8" -dependencies = [ - "aes", - "base64 0.22.1", - "bytes", - "ctr", - "form_urlencoded", - "futures-core", - "futures-util", - "hmac", - "http-body-util", - "hyper 1.4.1", - "hyper-util", - "librespot-core", - "log", - "rand", - "serde_json", - "serde_repr", - "sha1", - "thiserror", - "tokio", -] - -[[package]] -name = "librespot-metadata" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf6d5c46a401b1dd3e062ebdce959aa694bbae1039841756545d2e9c4f8be5f" -dependencies = [ - "async-trait", - "bytes", - "librespot-core", - "librespot-protocol", - "log", - "protobuf", - "serde", - "serde_json", - "thiserror", - "uuid", -] - -[[package]] -name = "librespot-oauth" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00dcad779aa6c3b442e493e2a40ca83a5c5fcf38a65c05b026c3587bd4f8d14f" -dependencies = [ - "log", - "oauth2", - "thiserror", - "url", -] - -[[package]] -name = "librespot-playback" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ed1f776a04c8c9275407f8d4df034f2615ea729ec6c6d0fa69f423fc571df64" -dependencies = [ - "cpal", - "futures-util", - "librespot-audio", - "librespot-core", - "librespot-metadata", - "log", - "parking_lot", - "rand", - "rand_distr", - "rodio", - "shell-words", - "symphonia", - "thiserror", - "tokio", - "zerocopy 0.7.35", -] - -[[package]] -name = "librespot-protocol" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80802f52b5a1b3a2157454e6aca483a627fbf7b942e0a5fea037ebf3ed8b0546" -dependencies = [ - "protobuf", - "protobuf-codegen", -] - [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -2163,15 +1458,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "matchers" version = "0.1.0" @@ -2263,7 +1549,6 @@ dependencies = [ "chrono", "dotenv", "form_urlencoded", - "librespot", "poise", "rand", "regex", @@ -2296,52 +1581,17 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.6.0", - "jni-sys", - "log", - "ndk-sys", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.5.0+25.2.9519653" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" -dependencies = [ - "jni-sys", -] - [[package]] name = "no-std-compat" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df270209a7f04d62459240d890ecb792714d5db12c92937823574a09930276b4" -[[package]] -name = "no-std-compat" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" - [[package]] name = "no-std-net" version = "0.6.0" @@ -2364,21 +1614,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nonzero_ext" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2389,17 +1624,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", - "rand", -] - [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -2483,56 +1707,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.87", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "oauth2" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" -dependencies = [ - "base64 0.13.1", - "chrono", - "getrandom", - "http 0.2.12", - "rand", - "reqwest 0.11.27", - "serde", - "serde_json", - "serde_path_to_error", - "sha2", - "thiserror", - "url", -] - [[package]] name = "object" version = "0.36.2" @@ -2542,29 +1716,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "oboe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" -dependencies = [ - "jni", - "ndk", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" -dependencies = [ - "cc", -] - [[package]] name = "once_cell" version = "1.19.0" @@ -2658,13 +1809,10 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "backtrace", "cfg-if", "libc", - "petgraph", "redox_syscall 0.5.3", "smallvec", - "thread-id", "windows-targets 0.52.6", ] @@ -2683,16 +1831,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest", - "hmac", -] - [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -2708,16 +1846,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset", - "indexmap", -] - [[package]] name = "pin-project" version = "1.1.5" @@ -2880,16 +2008,6 @@ dependencies = [ "zerocopy 0.6.6", ] -[[package]] -name = "prettyplease" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" -dependencies = [ - "proc-macro2", - "syn 2.0.87", -] - [[package]] name = "primal-check" version = "0.3.4" @@ -2899,26 +2017,6 @@ dependencies = [ "num-integer", ] -[[package]] -name = "priority-queue" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714c75db297bc88a63783ffc6ab9f830698a6705aa0201416931759ef4c8183d" -dependencies = [ - "autocfg", - "equivalent", - "indexmap", -] - -[[package]] -name = "proc-macro-crate" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" -dependencies = [ - "toml_edit", -] - [[package]] name = "proc-macro2" version = "1.0.86" @@ -2928,57 +2026,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "protobuf" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72" -dependencies = [ - "once_cell", - "protobuf-support", - "thiserror", -] - -[[package]] -name = "protobuf-codegen" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e26b833f144769a30e04b1db0146b2aaa53fd2fd83acf10a6b5f996606c18144" -dependencies = [ - "anyhow", - "once_cell", - "protobuf", - "protobuf-parse", - "regex", - "tempfile", - "thiserror", -] - -[[package]] -name = "protobuf-parse" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322330e133eab455718444b4e033ebfac7c6528972c784fcde28d2cc783c6257" -dependencies = [ - "anyhow", - "indexmap", - "log", - "protobuf", - "protobuf-support", - "tempfile", - "thiserror", - "which", -] - -[[package]] -name = "protobuf-support" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252" -dependencies = [ - "thiserror", -] - [[package]] name = "pulldown-cmark" version = "0.9.6" @@ -2990,16 +2037,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "quote" version = "1.0.36" @@ -3039,16 +2076,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_distr" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" -dependencies = [ - "num-traits", - "rand", -] - [[package]] name = "realfft" version = "3.4.0" @@ -3247,16 +2274,6 @@ dependencies = [ "portable-atomic", ] -[[package]] -name = "rodio" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" -dependencies = [ - "cpal", - "thiserror", -] - [[package]] name = "rsa" version = "0.9.6" @@ -3295,12 +2312,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc_version" version = "0.4.1" @@ -3382,8 +2393,6 @@ version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ - "aws-lc-rs", - "log", "once_cell", "rustls-pki-types", "rustls-webpki 0.102.6", @@ -3400,32 +2409,7 @@ dependencies = [ "openssl-probe", "rustls-pemfile 1.0.4", "schannel", - "security-framework 2.11.1", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe", - "rustls-pemfile 2.1.2", - "rustls-pki-types", - "schannel", - "security-framework 2.11.1", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework 3.0.1", + "security-framework", ] [[package]] @@ -3469,7 +2453,6 @@ version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ - "aws-lc-rs", "ring 0.17.8", "rustls-pki-types", "untrusted 0.9.0", @@ -3566,20 +2549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -3666,16 +2636,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa", - "serde", -] - [[package]] name = "serde_repr" version = "0.1.19" @@ -3767,15 +2727,6 @@ dependencies = [ "digest", ] -[[package]] -name = "shannon" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ea5b41c9427b56caa7b808cb548a04fb50bb5b9e98590b53f28064ff4174561" -dependencies = [ - "byteorder", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -3785,18 +2736,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shell-words" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "shorthand" version = "0.1.1" @@ -3936,15 +2875,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "spinning_top" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" -dependencies = [ - "lock_api", -] - [[package]] name = "spki" version = "0.7.3" @@ -4165,7 +3095,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1dff32a2ce087283bec878419027cebd888760d8760b2941ad0843531dc9ec8" dependencies = [ - "no-std-compat 0.2.0", + "no-std-compat", ] [[package]] @@ -4259,36 +3189,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" dependencies = [ "lazy_static", - "symphonia-bundle-mp3", - "symphonia-codec-vorbis", - "symphonia-core", - "symphonia-format-ogg", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-bundle-mp3" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" -dependencies = [ - "lazy_static", - "log", "symphonia-core", "symphonia-metadata", ] -[[package]] -name = "symphonia-codec-vorbis" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" -dependencies = [ - "log", - "symphonia-core", - "symphonia-utils-xiph", -] - [[package]] name = "symphonia-core" version = "0.5.4" @@ -4302,18 +3206,6 @@ dependencies = [ "log", ] -[[package]] -name = "symphonia-format-ogg" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" -dependencies = [ - "log", - "symphonia-core", - "symphonia-metadata", - "symphonia-utils-xiph", -] - [[package]] name = "symphonia-metadata" version = "0.5.4" @@ -4326,16 +3218,6 @@ dependencies = [ "symphonia-core", ] -[[package]] -name = "symphonia-utils-xiph" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" -dependencies = [ - "symphonia-core", - "symphonia-metadata", -] - [[package]] name = "syn" version = "1.0.109" @@ -4373,19 +3255,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "sysinfo" -version = "0.31.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" -dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "windows 0.57.0", -] - [[package]] name = "system-configuration" version = "0.5.1" @@ -4393,7 +3262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", + "core-foundation", "system-configuration-sys 0.5.0", ] @@ -4404,7 +3273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", + "core-foundation", "system-configuration-sys 0.6.0", ] @@ -4478,16 +3347,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "thread-id" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe8f25bbdd100db7e1d34acf7fd2dc59c4bf8f7483f505eaa7d4f12f76cc0ea" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "thread_local" version = "1.1.8" @@ -4506,9 +3365,7 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", - "libc", "num-conv", - "num_threads", "powerfmt", "serde", "time-core", @@ -4556,7 +3413,6 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -4663,7 +3519,7 @@ dependencies = [ "futures-util", "log", "rustls 0.20.9", - "rustls-native-certs 0.6.3", + "rustls-native-certs", "tokio", "tokio-rustls 0.23.4", "tungstenite 0.18.0", @@ -4686,22 +3542,6 @@ dependencies = [ "webpki-roots 0.26.3", ] -[[package]] -name = "tokio-tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" -dependencies = [ - "futures-util", - "log", - "rustls 0.23.12", - "rustls-native-certs 0.8.1", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.0", - "tungstenite 0.24.0", -] - [[package]] name = "tokio-util" version = "0.7.11" @@ -4715,23 +3555,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - [[package]] name = "tower" version = "0.4.13" @@ -4895,26 +3718,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand", - "rustls 0.23.12", - "rustls-pki-types", - "sha1", - "thiserror", - "utf-8", -] - [[package]] name = "twilight-gateway" version = "0.15.4" @@ -4925,7 +3728,7 @@ dependencies = [ "futures-util", "rand", "rustls 0.20.9", - "rustls-native-certs 0.6.3", + "rustls-native-certs", "serde", "serde_json", "tokio", @@ -5041,12 +3844,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "unicode_categories" version = "0.1.1" @@ -5093,12 +3890,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - [[package]] name = "uuid" version = "1.10.0" @@ -5106,7 +3897,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", - "rand", ] [[package]] @@ -5121,44 +3911,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vergen" -version = "9.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f25fc8f8f05df455c7941e87f093ad22522a9ff33d7a027774815acf6f0639" -dependencies = [ - "anyhow", - "derive_builder 0.20.2", - "rustversion", - "time", - "vergen-lib", -] - -[[package]] -name = "vergen-gitcl" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0227006d09f98ab00ea69e9a5e055e676a813cfbed4232986176c86a6080b997" -dependencies = [ - "anyhow", - "derive_builder 0.20.2", - "rustversion", - "time", - "vergen", - "vergen-lib", -] - -[[package]] -name = "vergen-lib" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0c767e6751c09fc85cde58722cf2f1007e80e4c8d5a4321fc90d83dc54ca147" -dependencies = [ - "anyhow", - "derive_builder 0.20.2", - "rustversion", -] - [[package]] name = "version_check" version = "0.9.5" @@ -5310,18 +4062,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "whoami" version = "1.5.1" @@ -5372,26 +4112,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" -dependencies = [ - "windows-core 0.54.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" -dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.52.0" @@ -5401,70 +4121,17 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-core" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" -dependencies = [ - "windows-result 0.1.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result 0.1.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-implement" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - -[[package]] -name = "windows-interface" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result 0.2.0", + "windows-result", "windows-strings", "windows-targets 0.52.6", ] -[[package]] -name = "windows-result" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-result" version = "0.2.0" @@ -5480,19 +4147,10 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result 0.2.0", + "windows-result", "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5520,21 +4178,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -5566,12 +4209,6 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -5584,12 +4221,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -5602,12 +4233,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -5626,12 +4251,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -5644,12 +4263,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -5662,12 +4275,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -5680,12 +4287,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -5698,15 +4299,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" -dependencies = [ - "memchr", -] - [[package]] name = "winreg" version = "0.50.0" @@ -5733,7 +4325,6 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "byteorder", "zerocopy-derive 0.7.35", ] diff --git a/Cargo.toml b/Cargo.toml index b53e91f..63a2b9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ chrono = "0.4.38" sqlx = {version="0.8.2", features=["runtime-tokio", "sqlite"]} form_urlencoded = "1.2.1" tenorv2 = { path = "./tenor-v2/tenorv2" } -librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] } +# librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] } songbird = { version = "0.4.6", features = ["driver"] } [features] From 49f09082e9b129bdbdc284b79175e46a29947c80 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Mon, 6 Jan 2025 12:51:57 +0100 Subject: [PATCH 10/19] feat: playing from URL works now --- .TODO | 2 + Cargo.lock | 199 +++++++++++++++++++-- Cargo.toml | 7 +- src/commands/voice/mod.rs | 6 +- src/commands/voice/player.rs | 180 +++---------------- src/commands/voice/radio/mod.rs | 3 + src/commands/voice/radio/radio_player.rs | 66 +++++++ src/commands/voice/spotify/player.rs | 211 ----------------------- src/commands/voice/util.rs | 76 ++++++++ src/main.rs | 1 + 10 files changed, 369 insertions(+), 382 deletions(-) create mode 100644 .TODO create mode 100644 src/commands/voice/radio/mod.rs create mode 100644 src/commands/voice/radio/radio_player.rs delete mode 100644 src/commands/voice/spotify/player.rs create mode 100644 src/commands/voice/util.rs diff --git a/.TODO b/.TODO new file mode 100644 index 0000000..f6e1060 --- /dev/null +++ b/.TODO @@ -0,0 +1,2 @@ +handle disconnect by someone, other than command +disconnect after some time when not playing \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index dd16aa1..52a49e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -753,6 +753,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + [[package]] name = "fastrand" version = "2.1.0" @@ -1268,6 +1274,19 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.30", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -1286,9 +1305,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1299,7 +1318,6 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -1552,9 +1570,11 @@ dependencies = [ "poise", "rand", "regex", + "reqwest 0.11.27", "serenity", "songbird", "sqlx", + "symphonia", "tenorv2", "tokio", "tokio-cron-scheduler", @@ -2163,11 +2183,13 @@ dependencies = [ "http-body 0.4.6", "hyper 0.14.30", "hyper-rustls 0.24.2", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", "mime", "mime_guess", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -2179,6 +2201,7 @@ dependencies = [ "sync_wrapper 0.1.2", "system-configuration 0.5.1", "tokio", + "tokio-native-tls", "tokio-rustls 0.24.1", "tokio-util", "tower-service", @@ -2193,9 +2216,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64 0.22.1", "bytes", @@ -2208,7 +2231,7 @@ dependencies = [ "http-body-util", "hyper 1.4.1", "hyper-rustls 0.27.2", - "hyper-tls", + "hyper-tls 0.6.0", "hyper-util", "ipnet", "js-sys", @@ -2226,6 +2249,7 @@ dependencies = [ "system-configuration 0.6.1", "tokio", "tokio-native-tls", + "tower", "tower-service", "url", "wasm-bindgen", @@ -3189,8 +3213,95 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" dependencies = [ "lazy_static", + "symphonia-bundle-flac", + "symphonia-bundle-mp3", + "symphonia-codec-aac", + "symphonia-codec-adpcm", + "symphonia-codec-alac", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-isomp4", + "symphonia-format-mkv", + "symphonia-format-ogg", + "symphonia-format-riff", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-flac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" +dependencies = [ + "log", "symphonia-core", "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-codec-aac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-adpcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-alac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-pcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", ] [[package]] @@ -3206,6 +3317,56 @@ dependencies = [ "log", ] +[[package]] +name = "symphonia-format-isomp4" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" +dependencies = [ + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-mkv" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-ogg" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-riff" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" +dependencies = [ + "extended", + "log", + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "symphonia-metadata" version = "0.5.4" @@ -3218,6 +3379,16 @@ dependencies = [ "symphonia-core", ] +[[package]] +name = "symphonia-utils-xiph" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "syn" version = "1.0.109" @@ -3323,7 +3494,7 @@ dependencies = [ "form_urlencoded", "json", "regex", - "reqwest 0.12.8", + "reqwest 0.12.12", "thiserror", ] @@ -3557,14 +3728,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 1.0.1", "tokio", "tower-layer", "tower-service", @@ -3572,15 +3743,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" diff --git a/Cargo.toml b/Cargo.toml index 63a2b9c..999bd3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,12 @@ sqlx = {version="0.8.2", features=["runtime-tokio", "sqlite"]} form_urlencoded = "1.2.1" tenorv2 = { path = "./tenor-v2/tenorv2" } # librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] } -songbird = { version = "0.4.6", features = ["driver"] } +songbird = { version = "0.4.6", features = ["driver", "builtin-queue"] } +reqwest = "0.11.27" # songbird depends on ^0.11 + +[dependencies.symphonia] +version = "0.5.2" +features = ["aac", "mp3", "isomp4", "alac"] [features] DEBUG = [] diff --git a/src/commands/voice/mod.rs b/src/commands/voice/mod.rs index d44230b..0df6866 100644 --- a/src/commands/voice/mod.rs +++ b/src/commands/voice/mod.rs @@ -1 +1,5 @@ -pub mod player; \ No newline at end of file +pub mod util; +pub mod player; +pub mod radio; +// pub mod spotify; +// pub mod yt; \ No newline at end of file diff --git a/src/commands/voice/player.rs b/src/commands/voice/player.rs index ddffb7d..5444b86 100644 --- a/src/commands/voice/player.rs +++ b/src/commands/voice/player.rs @@ -1,122 +1,26 @@ use std::vec; -use serenity::{all::ChannelId, async_trait}; -use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; use songbird::input::{File, Input}; -use songbird::TrackEvent; use crate::util::debug::send_error; use crate::util::poise_context_extension::ContextExt; use crate::util::utilities::get_local_songs; -use crate::{types::{Context, Error}, util::utilities::get_channel_by_name}; +use crate::types::{Context, Error}; -#[poise::command( - slash_command, - description_localized("en-US", "Play song") -)] -pub async fn play(ctx: Context<'_>, - #[description = "Song: "] - _url: String -) -> Result<(), Error> { +use super::util::{connect, autocomplete_channel}; - ctx.reply("Done!").await?; - Ok(()) -} +// #[poise::command( +// slash_command, +// description_localized("en-US", "Play song") +// )] +// pub async fn play(ctx: Context<'_>, +// #[description = "Song: "] +// _url: String +// ) -> Result<(), Error> { -/// Returns either voice channel to which the user is currently connected to or the one passed via name -async fn get_voice_channel(ctx: &Context<'_>, name: Option) -> Result { - if name.is_none() || name.as_ref().is_some_and(|n| n.is_empty()) { - match ctx.guild().and_then(|guild| - guild.voice_states.get(&ctx.author().id).and_then(|voice_state| - voice_state.channel_id - ) - ) { - Some(c) => Ok(c), - None => Err("You must be in a voice channel or specify explicit voice channel by name".to_string()) - } - } - else { - match ctx.guild().and_then(|guild| - get_channel_by_name(guild, name.unwrap()) - ) { - Some(c) => Ok(c), - None => Err("Channel with this name does not exist".to_string()) - } - } -} - -#[poise::command( - slash_command, - description_localized("en-US", "Connect to channel") -)] -pub async fn connect(ctx: Context<'_>, - #[autocomplete = "autocomplete_channel"] - #[description = "Voice channel name: "] - name: Option -) -> Result<(), Error> { - - if ctx.guild().is_none() { - ctx.reply_ephemeral("Can't use this outside of guild").await?; - return Ok(()); - } - - let voice_channel = match get_voice_channel(&ctx, name).await { - Ok(c) => c, - Err(e) => { - ctx.reply_ephemeral(e.as_str()).await?; - return Ok(()) - } - }; - - let manager = songbird::get(ctx.serenity_context()) - .await - .expect("Songbird Voice client placed in at initialisation.") - .clone(); - - let Some(guild_id) = ctx.guild_id() else { - ctx.reply_ephemeral("Guild id not found").await?; - return Ok(()) - }; - - if let Ok(handler_lock) = manager.join(guild_id, voice_channel).await { - let mut handler = handler_lock.lock().await; - handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); - } - - ctx.reply_ephemeral("Done!").await?; - Ok(()) -} - -struct TrackErrorNotifier; - -#[async_trait] -impl VoiceEventHandler for TrackErrorNotifier { - async fn act(&self, ctx: &EventContext<'_>) -> Option { - if let EventContext::Track(track_list) = ctx { - for (state, handle) in *track_list { - println!( - "Track {:?} encountered an error: {:?}", - handle.uuid(), - state.playing - ); - } - } - - None - } -} - -async fn autocomplete_channel( - ctx: Context<'_>, - _partial: &str, -) -> Vec { - - use crate::util::utilities::get_vc_names; - match ctx.guild() { - Some(guild) => get_vc_names(guild), - None => [].to_vec() - } -} +// ctx.reply("Done!").await?; +// Ok(()) +// } #[poise::command( slash_command, @@ -168,12 +72,12 @@ async fn autocomplete_song( #[poise::command( slash_command, - description_localized("en-US", "Connect to channel") + description_localized("en-US", "Play song from server storage") )] pub async fn play_local(ctx: Context<'_>, #[autocomplete = "autocomplete_channel"] #[description = "Voice channel name: "] - _channel: Option, + channel: Option, #[autocomplete = "autocomplete_song"] #[description = "Filename of local song: "] file_name: String @@ -194,17 +98,24 @@ pub async fn play_local(ctx: Context<'_>, return Ok(()) }; - + if manager.get(guild_id).is_none() { + match connect(&ctx, guild_id, channel).await { + Ok(_) => (), + Err(e) => { + ctx.reply_ephemeral(&e.to_string()).await?; + return Ok(()) + } + } + } if let Some(handler_lock) = manager.get(guild_id) { let mut handler = handler_lock.lock().await; let input_file = File::new(format!("/home/emil/Music/{file_name}")); let input = Input::Lazy(Box::new(input_file)); - let _ = handler.play_input(input); + let _ = handler.play_only_input(input); } else { - ctx.reply_ephemeral("Not in a voice channel").await?; return Ok(()) } @@ -212,44 +123,3 @@ pub async fn play_local(ctx: Context<'_>, ctx.reply_ephemeral("Done!").await?; Ok(()) } - -// #[poise::command( -// slash_command, -// description_localized("en-US", "Connect to channel") -// )] -// pub async fn play_local(ctx: Context<'_>, -// #[autocomplete = "autocomplete_song"] -// #[description = "Voice channel name: "] -// file_name: String -// ) -> Result<(), Error> { - -// if ctx.guild().is_none() { -// ctx.reply_ephemeral("Can't use this outside of guild").await?; -// return Ok(()); -// } - -// let manager = songbird::get(ctx.serenity_context()) -// .await -// .expect("Songbird Voice client placed in at initialisation.") -// .clone(); - -// let Some(guild_id) = ctx.guild_id() else { -// ctx.reply_ephemeral("Guild id not found").await?; -// return Ok(()) -// }; - -// if let Some(handler_lock) = manager.get(guild_id) { -// let mut handler = handler_lock.lock().await; - -// let input_file = File::new(format!("/home/emil/Music/{file_name}")); -// let input = Input::Lazy(Box::new(input_file)); -// let _ = handler.play_input(input); -// } -// else { -// ctx.reply_ephemeral("Not in a voice channel").await?; -// return Ok(()) -// } - -// ctx.reply_ephemeral("Done!").await?; -// Ok(()) -// } diff --git a/src/commands/voice/radio/mod.rs b/src/commands/voice/radio/mod.rs new file mode 100644 index 0000000..27ead6c --- /dev/null +++ b/src/commands/voice/radio/mod.rs @@ -0,0 +1,3 @@ +pub use radio_player::*; + +pub mod radio_player; diff --git a/src/commands/voice/radio/radio_player.rs b/src/commands/voice/radio/radio_player.rs new file mode 100644 index 0000000..b9ed39d --- /dev/null +++ b/src/commands/voice/radio/radio_player.rs @@ -0,0 +1,66 @@ +use std::vec; + +use reqwest::Client; + +use songbird::input::Input; +use songbird::input::HttpRequest; + +use crate::commands::util::connect; +use crate::util::poise_context_extension::ContextExt; +use crate::types::{Context, Error}; +use crate::commands::voice::util::autocomplete_channel; + +// TODO: autocomplete radio stream URLs +#[poise::command( + slash_command, + description_localized("en-US", "Plays music from URL source") +)] +pub async fn radio(ctx: Context<'_>, + #[autocomplete = "autocomplete_channel"] + #[description = "Voice channel name: "] + channel: Option, + #[description = "Source URL: "] + url: String, +) -> Result<(), Error> { + + if ctx.guild().is_none() { + ctx.reply_ephemeral("Can't use this outside of guild").await?; + return Ok(()); + } + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + if manager.get(guild_id).is_none() { + match connect(&ctx, guild_id, channel).await { + Ok(_) => (), + Err(e) => { + ctx.reply_ephemeral(&e.to_string()).await?; + return Ok(()) + } + } + } + + if let Some(handler_lock) = manager.get(guild_id) { + let mut handler = handler_lock.lock().await; + + let client = Client::new(); + let request = HttpRequest::new(client, url); + let input = Input::from(request); + handler.play_only_input(input); + } + else { + ctx.reply_ephemeral("Not in a voice channel").await?; + return Ok(()) + } + + ctx.reply_ephemeral("Done!").await?; + Ok(()) +} diff --git a/src/commands/voice/spotify/player.rs b/src/commands/voice/spotify/player.rs deleted file mode 100644 index 5c00980..0000000 --- a/src/commands/voice/spotify/player.rs +++ /dev/null @@ -1,211 +0,0 @@ -use std::vec; - -use poise::{self, CreateReply}; -use serenity::all::{CacheHttp, Guild, PartialGuild, UserId}; -use serenity::{all::ChannelId, async_trait}; -use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; -use songbird::input::{File, Input}; -use songbird::tracks::Track; -use songbird::TrackEvent; - -use crate::util::debug::send_error; -use crate::util::poise_context_extension::ContextExt; -use crate::util::utilities::get_local_songs; -use crate::{types::{Context, Error}, util::utilities::get_channel_by_name}; - -#[poise::command( - slash_command, - description_localized("en-US", "Play song") -)] -pub async fn play(ctx: Context<'_>, - #[description = "Song: "] - _url: String -) -> Result<(), Error> { - - ctx.reply("Done!").await?; - Ok(()) -} - -/// Returns either voice channel to which the user is currently connected to or the one passed via name -async fn get_voice_channel(ctx: &Context<'_>, name: Option) -> Result { - if name.is_none() || name.as_ref().is_some_and(|n| n.is_empty()) { - match ctx.guild().and_then(|guild| - guild.voice_states.get(&ctx.author().id).and_then(|voice_state| - voice_state.channel_id - ) - ) { - Some(c) => Ok(c), - None => Err("You must be in a voice channel or specify explicit voice channel by name".to_string()) - } - } - else { - match ctx.guild().and_then(|guild| - get_channel_by_name(guild, name.unwrap()) - ) { - Some(c) => Ok(c), - None => Err("Channel with this name does not exist".to_string()) - } - } -} - -#[poise::command( - slash_command, - description_localized("en-US", "Connect to channel") -)] -pub async fn connect(ctx: Context<'_>, - #[autocomplete = "autocomplete_channel"] - #[description = "Voice channel name: "] - name: Option -) -> Result<(), Error> { - - if ctx.guild().is_none() { - ctx.reply_ephemeral("Can't use this outside of guild").await?; - return Ok(()); - } - - let voice_channel = match get_voice_channel(&ctx, name).await { - Ok(c) => c, - Err(e) => { - ctx.reply_ephemeral(e.as_str()).await?; - return Ok(()) - } - }; - - let manager = songbird::get(ctx.serenity_context()) - .await - .expect("Songbird Voice client placed in at initialisation.") - .clone(); - - let Some(guild_id) = ctx.guild_id() else { - ctx.reply_ephemeral("Guild id not found").await?; - return Ok(()) - }; - - if let Ok(handler_lock) = manager.join(guild_id, voice_channel).await { - let mut handler = handler_lock.lock().await; - handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); - } - - ctx.reply_ephemeral("Done!").await?; - Ok(()) -} - -struct TrackErrorNotifier; - -#[async_trait] -impl VoiceEventHandler for TrackErrorNotifier { - async fn act(&self, ctx: &EventContext<'_>) -> Option { - if let EventContext::Track(track_list) = ctx { - for (state, handle) in *track_list { - println!( - "Track {:?} encountered an error: {:?}", - handle.uuid(), - state.playing - ); - } - } - - None - } -} - -async fn autocomplete_channel( - ctx: Context<'_>, - _partial: &str, -) -> Vec { - - use crate::util::utilities::get_vc_names; - match ctx.guild() { - Some(guild) => get_vc_names(guild), - None => [].to_vec() - } -} - -#[poise::command( - slash_command, - description_localized("en-US", "Disconnect from voice channel") -)] -pub async fn disconnect( - ctx: Context<'_> -) -> Result<(), Error> { - - let Some(guild_id) = ctx.guild_id() else { - ctx.reply("Can't use this outside of guild").await?; - return Ok(()); - }; - - let manager = songbird::get(ctx.serenity_context()) - .await - .expect("Songbird Voice client placed in at initialisation.") - .clone(); - - let has_handler = manager.get(guild_id).is_some(); - - if ! has_handler { - ctx.reply("I am not connected to a channel!").await?; - return Ok(()) - } - - match manager.remove(guild_id).await { - Ok(()) => { - ctx.reply("Disconnected").await?; - return Ok(()) - } - Err(e) => { - let _ = send_error(ctx.serenity_context().http.clone(), e.to_string()).await; - return Ok(()) - } - } -} - -async fn autocomplete_song( - _ctx: Context<'_>, - partial: &str, -) -> Vec { - - match get_local_songs(partial) { - Ok(names) => names, - Err(_) => vec![] - } -} - -#[poise::command( - slash_command, - description_localized("en-US", "Connect to channel") -)] -pub async fn play_local(ctx: Context<'_>, - #[autocomplete = "autocomplete_song"] - #[description = "Voice channel name: "] - file_name: String -) -> Result<(), Error> { - - if ctx.guild().is_none() { - ctx.reply_ephemeral("Can't use this outside of guild").await?; - return Ok(()); - } - - let manager = songbird::get(ctx.serenity_context()) - .await - .expect("Songbird Voice client placed in at initialisation.") - .clone(); - - let Some(guild_id) = ctx.guild_id() else { - ctx.reply_ephemeral("Guild id not found").await?; - return Ok(()) - }; - - if let Some(handler_lock) = manager.get(guild_id) { - let mut handler = handler_lock.lock().await; - - let input_file = File::new(format!("/home/emil/Music/{file_name}")); - let input = Input::Lazy(Box::new(input_file)); - let _ = handler.play_input(input); - } - else { - ctx.reply_ephemeral("Not in a voice channel").await?; - return Ok(()) - } - - ctx.reply_ephemeral("Done!").await?; - Ok(()) -} \ No newline at end of file diff --git a/src/commands/voice/util.rs b/src/commands/voice/util.rs new file mode 100644 index 0000000..4208b51 --- /dev/null +++ b/src/commands/voice/util.rs @@ -0,0 +1,76 @@ +use serenity::all::{ChannelId, GuildId}; +use serenity::async_trait; + +use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; +use songbird::TrackEvent; + +use crate::{types::{Context, Error}, util::utilities::get_channel_by_name}; + +/// Returns either voice channel to which the user is currently connected to or the one passed via name +async fn get_voice_channel(ctx: &Context<'_>, name: Option) -> Result { + if name.is_none() || name.as_ref().is_some_and(|n| n.is_empty()) { + match ctx.guild().and_then(|guild| + guild.voice_states.get(&ctx.author().id).and_then(|voice_state| + voice_state.channel_id + ) + ) { + Some(c) => Ok(c), + None => Err("You must be in a voice channel or specify explicit voice channel by name".to_string()) + } + } + else { + match ctx.guild().and_then(|guild| + get_channel_by_name(guild, name.unwrap()) + ) { + Some(c) => Ok(c), + None => Err("Channel with this name does not exist".to_string()) + } + } +} + +struct TrackErrorNotifier; + +#[async_trait] +impl VoiceEventHandler for TrackErrorNotifier { + async fn act(&self, ctx: &EventContext<'_>) -> Option { + if let EventContext::Track(track_list) = ctx { + for (state, handle) in *track_list { + println!( + "Track {:?} encountered an error: {:?}", + handle.uuid(), + state.playing + ); + } + } + + None + } +} + +pub async fn connect(ctx: &Context<'_>, guild_id: GuildId, channel: Option) -> Result<(), Error> { + let voice_channel = get_voice_channel(&ctx, channel).await?; + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + if let Ok(handler_lock) = manager.join(guild_id, voice_channel).await { + let mut handler = handler_lock.lock().await; + handler.add_global_event(TrackEvent::Error.into(), TrackErrorNotifier); + } + + Ok(()) +} + +pub async fn autocomplete_channel( + ctx: Context<'_>, + _partial: &str, +) -> Vec { + + use crate::util::utilities::get_vc_names; + match ctx.guild() { + Some(guild) => get_vc_names(guild), + None => [].to_vec() + } +} diff --git a/src/main.rs b/src/main.rs index 3eedf7d..6db17f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -86,6 +86,7 @@ async fn main() -> anyhow::Result<()> { commands::hug(), commands::player::play_local(), commands::player::disconnect(), + commands::radio::radio() ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), From 3c8cf4e663420c4bbf790a62a18b7408817a1788 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Mon, 6 Jan 2025 14:14:52 +0100 Subject: [PATCH 11/19] chore: changed version --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 6db17f5..c85ed95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,7 +52,7 @@ impl EventHandler for Handler { } async fn ready(&self, ctx: Context, ready: Ready) { - println!("{} v0.3 is connected!", ready.user.name); + println!("{} v3.2.0 is connected!", ready.user.name); #[cfg(feature="RELEASE")] { use util::debug::hello; From 3eaee7c8ba3424aef8c83f4aee1b33062ce4f3f4 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Thu, 9 Jan 2025 18:57:42 +0100 Subject: [PATCH 12/19] feat: implemented general player using yt-dlp --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/commands/moover/say.rs | 4 +- src/commands/voice/general/general_player.rs | 63 +++++++++++++++++++ src/commands/voice/general/mod.rs | 3 + src/commands/voice/mod.rs | 4 +- .../voice/{player.rs => player_common.rs} | 19 ++---- src/commands/voice/spotify/mod.rs | 4 +- .../spotify_player.rs} | 0 src/main.rs | 21 ++++--- src/types.rs | 25 +++++++- 11 files changed, 116 insertions(+), 31 deletions(-) create mode 100644 src/commands/voice/general/general_player.rs create mode 100644 src/commands/voice/general/mod.rs rename src/commands/voice/{player.rs => player_common.rs} (88%) rename src/commands/voice/{soundcloud/souncloud.rs => spotify/spotify_player.rs} (100%) diff --git a/Cargo.lock b/Cargo.lock index 52a49e8..7831905 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1561,7 +1561,7 @@ dependencies = [ [[package]] name = "moover_rust" -version = "0.3.0" +version = "3.3.0" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 999bd3f..b6ca761 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "moover_rust" -version = "0.3.0" +version = "3.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/commands/moover/say.rs b/src/commands/moover/say.rs index c097539..e4df757 100644 --- a/src/commands/moover/say.rs +++ b/src/commands/moover/say.rs @@ -1,8 +1,6 @@ use poise; -// use super::super::types::Data; -type Error = Box; -type Context<'a> = poise::Context<'a, (), Error>; +use crate::types::{Context, Error}; #[poise::command( slash_command, diff --git a/src/commands/voice/general/general_player.rs b/src/commands/voice/general/general_player.rs new file mode 100644 index 0000000..c3cd0d6 --- /dev/null +++ b/src/commands/voice/general/general_player.rs @@ -0,0 +1,63 @@ +use std::vec; + +use songbird::input::YoutubeDl; + +use crate::commands::util::connect; +use crate::util::poise_context_extension::ContextExt; +use crate::types::{Context, Error}; +use crate::commands::voice::util::autocomplete_channel; + +// TODO: search, queue +#[poise::command( + slash_command, + description_localized("en-US", "Plays music from supported URL") +)] +pub async fn play(ctx: Context<'_>, + #[autocomplete = "autocomplete_channel"] + #[description = "Voice channel name: "] + channel: Option, + #[description = "Source URL: "] + url: String, +) -> Result<(), Error> { + + if ctx.guild().is_none() { + ctx.reply_ephemeral("Can't use this outside of guild").await?; + return Ok(()); + } + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + let http_client = &ctx.data().http_client; + + if manager.get(guild_id).is_none() { + match connect(&ctx, guild_id, channel).await { + Ok(_) => (), + Err(e) => { + ctx.reply_ephemeral(&e.to_string()).await?; + return Ok(()) + } + } + } + + if let Some(handler_lock) = manager.get(guild_id) { + let mut handler = handler_lock.lock().await; + + let src = YoutubeDl::new(http_client.clone(), url); + handler.enqueue_input(src.into()).await; + } + else { + ctx.reply_ephemeral("Not in a voice channel").await?; + return Ok(()) + } + + ctx.reply_ephemeral("Done!").await?; + Ok(()) +} diff --git a/src/commands/voice/general/mod.rs b/src/commands/voice/general/mod.rs new file mode 100644 index 0000000..8b6dfd4 --- /dev/null +++ b/src/commands/voice/general/mod.rs @@ -0,0 +1,3 @@ +pub use general_player::*; + +pub mod general_player; \ No newline at end of file diff --git a/src/commands/voice/mod.rs b/src/commands/voice/mod.rs index 0df6866..284b48d 100644 --- a/src/commands/voice/mod.rs +++ b/src/commands/voice/mod.rs @@ -1,5 +1,5 @@ pub mod util; -pub mod player; +pub mod player_common; pub mod radio; // pub mod spotify; -// pub mod yt; \ No newline at end of file +pub mod general; \ No newline at end of file diff --git a/src/commands/voice/player.rs b/src/commands/voice/player_common.rs similarity index 88% rename from src/commands/voice/player.rs rename to src/commands/voice/player_common.rs index 5444b86..38ac50a 100644 --- a/src/commands/voice/player.rs +++ b/src/commands/voice/player_common.rs @@ -9,18 +9,9 @@ use crate::types::{Context, Error}; use super::util::{connect, autocomplete_channel}; -// #[poise::command( -// slash_command, -// description_localized("en-US", "Play song") -// )] -// pub async fn play(ctx: Context<'_>, -// #[description = "Song: "] -// _url: String -// ) -> Result<(), Error> { - -// ctx.reply("Done!").await?; -// Ok(()) -// } +/** + * Common commands that are the same for every implementation + */ #[poise::command( slash_command, @@ -31,7 +22,7 @@ pub async fn disconnect( ) -> Result<(), Error> { let Some(guild_id) = ctx.guild_id() else { - ctx.reply("Can't use this outside of guild").await?; + ctx.reply_ephemeral("Can't use this outside of guild").await?; return Ok(()); }; @@ -49,7 +40,7 @@ pub async fn disconnect( match manager.remove(guild_id).await { Ok(()) => { - ctx.reply("Disconnected").await?; + ctx.reply_ephemeral("Disconnected").await?; return Ok(()) } Err(e) => { diff --git a/src/commands/voice/spotify/mod.rs b/src/commands/voice/spotify/mod.rs index d44230b..f73c81c 100644 --- a/src/commands/voice/spotify/mod.rs +++ b/src/commands/voice/spotify/mod.rs @@ -1 +1,3 @@ -pub mod player; \ No newline at end of file +pub use spotify_player::*; + +pub mod spotify_player; diff --git a/src/commands/voice/soundcloud/souncloud.rs b/src/commands/voice/spotify/spotify_player.rs similarity index 100% rename from src/commands/voice/soundcloud/souncloud.rs rename to src/commands/voice/spotify/spotify_player.rs diff --git a/src/main.rs b/src/main.rs index c85ed95..44bd0d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,8 @@ use serenity::model::gateway::Ready; use serenity::all::{EventHandler, Message}; use serenity::Client; +use reqwest::Client as HttpClient; + use dotenv::dotenv; use songbird::SerenityInit; @@ -27,11 +29,11 @@ mod other; use other::notice; mod types; -use types::Error; +use types::{Data, Error}; struct Handler; -async fn on_error(error: poise::FrameworkError<'_, (), Error>) { +async fn on_error(error: poise::FrameworkError<'_, Data, Error>) { match error { poise::FrameworkError::Setup { error, .. } => panic!("Failed to start bot: {:?}", error), poise::FrameworkError::Command { error, ctx, .. } => { @@ -52,7 +54,7 @@ impl EventHandler for Handler { } async fn ready(&self, ctx: Context, ready: Ready) { - println!("{} v3.2.0 is connected!", ready.user.name); + println!("{} v3.3.0 is connected!", ready.user.name); #[cfg(feature="RELEASE")] { use util::debug::hello; @@ -80,13 +82,14 @@ async fn main() -> anyhow::Result<()> { dotenv().ok(); // create poise framework for registering commands - let options: poise::FrameworkOptions<(), Box> = poise::FrameworkOptions { + let options: poise::FrameworkOptions> = poise::FrameworkOptions { commands: vec![ commands::say(), commands::hug(), - commands::player::play_local(), - commands::player::disconnect(), - commands::radio::radio() + // commands::player::play_local(), + commands::player_common::disconnect(), + commands::radio::radio(), + commands::general::play() ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), @@ -125,7 +128,9 @@ async fn main() -> anyhow::Result<()> { register_globally(ctx, &framework.options().commands).await?; } - Ok(()) + Ok(Data { + http_client: HttpClient::new() + }) }) }) .options(options) diff --git a/src/types.rs b/src/types.rs index b5ebced..1103f1c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,28 @@ // pub struct Data {} +use std::{ffi::OsString, path::PathBuf}; + +use serenity::prelude::TypeMapKey; + +use reqwest::Client as HttpClient; + +// TODO: this should be probably expanded also to be used by multiple servers and commands +// radio and spotify commands always create new HttpClient +pub struct HttpKey; + +impl TypeMapKey for HttpKey { + type Value = HttpClient; +} + +pub struct Data { + pub http_client: HttpClient, +} + pub type Error = Box; // replace () with Data if you ever need to store some additional data -pub type Context<'a> = poise::Context<'a, (), Error>; +pub type Context<'a> = poise::Context<'a, Data, Error>; + +pub struct Track { + pub path: PathBuf, + pub name: OsString, +} From 1a2221d379dd506827baa48c091149eddf72e5d3 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Mon, 13 Jan 2025 18:14:41 +0100 Subject: [PATCH 13/19] feat: implemented youtube player --- src/commands/voice/mod.rs | 3 +- src/commands/voice/yt/mod.rs | 3 + src/commands/voice/yt/yt_player.rs | 88 ++++++++++++++++++++++++++++++ src/main.rs | 5 +- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 src/commands/voice/yt/mod.rs create mode 100644 src/commands/voice/yt/yt_player.rs diff --git a/src/commands/voice/mod.rs b/src/commands/voice/mod.rs index 284b48d..f3d7e73 100644 --- a/src/commands/voice/mod.rs +++ b/src/commands/voice/mod.rs @@ -2,4 +2,5 @@ pub mod util; pub mod player_common; pub mod radio; // pub mod spotify; -pub mod general; \ No newline at end of file +pub mod general; +pub mod yt; \ No newline at end of file diff --git a/src/commands/voice/yt/mod.rs b/src/commands/voice/yt/mod.rs new file mode 100644 index 0000000..989288e --- /dev/null +++ b/src/commands/voice/yt/mod.rs @@ -0,0 +1,3 @@ +pub use yt_player::*; + +pub mod yt_player; \ No newline at end of file diff --git a/src/commands/voice/yt/yt_player.rs b/src/commands/voice/yt/yt_player.rs new file mode 100644 index 0000000..ff5098b --- /dev/null +++ b/src/commands/voice/yt/yt_player.rs @@ -0,0 +1,88 @@ +use std::vec; +use std::env; + +use songbird::input::YoutubeDl; + +use crate::commands::util::connect; +use crate::util::poise_context_extension::ContextExt; +use crate::types::{Context, Error}; +use crate::commands::voice::util::autocomplete_channel; + +// TODO: search, queue +#[poise::command( + slash_command, + description_localized("en-US", "Plays music from YouTube URL") +)] +pub async fn play_yt(ctx: Context<'_>, + #[autocomplete = "autocomplete_channel"] + #[description = "Voice channel name: "] + channel: Option, + #[description = "Source URL: "] + url: String, +) -> Result<(), Error> { + + if ctx.guild().is_none() { + ctx.reply_ephemeral("Can't use this outside of guild").await?; + return Ok(()); + } + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + let http_client = ctx.data().http_client.clone(); + + if manager.get(guild_id).is_none() { + match connect(&ctx, guild_id, channel).await { + Ok(_) => (), + Err(e) => { + ctx.reply_ephemeral(&e.to_string()).await?; + return Ok(()) + } + } + } + + if let Some(handler_lock) = manager.get(guild_id) { + let mut handler = handler_lock.lock().await; + + let cookies_path = match env::var("COOKIES") { + Ok(path) => path, + Err(e) => { + let _ = ctx.reply_ephemeral("There was an error (did not find cookies)").await; + dbg!(e); + return Ok(()); + } + }; + + let po_token = match env::var("PO_TOKEN") { + Ok(token) => token, + Err(e) => { + let _ = ctx.reply_ephemeral("There was an error (did not find token)").await; + dbg!(e); + return Ok(()); + } + }; + + let arguments: Vec = vec![ + "--extractor-args".into(), + format!("youtube:player-client=web,default;po_token=web+{po_token}"), + "--cookies".into(), + cookies_path + ]; + let src = YoutubeDl::new(http_client, url).user_args(arguments); + handler.enqueue_input(src.into()).await; + } + else { + ctx.reply_ephemeral("Not in a voice channel").await?; + return Ok(()) + } + + ctx.reply_ephemeral("Done!").await?; + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 44bd0d3..66380e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,7 +54,7 @@ impl EventHandler for Handler { } async fn ready(&self, ctx: Context, ready: Ready) { - println!("{} v3.3.0 is connected!", ready.user.name); + println!("{} v3.3.1 is connected!", ready.user.name); #[cfg(feature="RELEASE")] { use util::debug::hello; @@ -89,7 +89,8 @@ async fn main() -> anyhow::Result<()> { // commands::player::play_local(), commands::player_common::disconnect(), commands::radio::radio(), - commands::general::play() + commands::general::play(), + commands::yt::play_yt() ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), From e32e632c7ca23e31eb2f6afe7bb5cad048e78859 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 19 Jan 2025 15:18:40 +0100 Subject: [PATCH 14/19] chore: change package version --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7831905..d88a0c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1561,7 +1561,7 @@ dependencies = [ [[package]] name = "moover_rust" -version = "3.3.0" +version = "3.3.1" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index b6ca761..c9e3f30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "moover_rust" -version = "3.3.0" +version = "3.3.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -30,4 +30,4 @@ features = ["aac", "mp3", "isomp4", "alac"] [features] DEBUG = [] RELEASE = [] -GUILD_COMMAND = [] \ No newline at end of file +GUILD_COMMAND = [] From 9d920421b7bd6f9ceeb70b9abccddb9295e72267 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Fri, 24 Jan 2025 21:52:13 +0100 Subject: [PATCH 15/19] chore: restructurize the whole source --- .gitignore | 4 +- Cargo.lock | 879 +++++++++++++++--- Cargo.toml | 9 +- src/{commands/mod.rs => commands.rs} | 6 +- src/commands/{moover/mod.rs => moover.rs} | 4 +- src/commands/moover/gif.rs | 20 + src/commands/{notice/mod.rs => notice.rs} | 2 +- src/commands/other/mod.rs | 0 .../mod.rs => user_interactions.rs} | 2 +- src/commands/user_interactions/interaction.rs | 2 +- src/commands/voice.rs | 11 + src/commands/voice/general/mod.rs | 3 - .../voice/{general => }/general_player.rs | 16 +- src/commands/voice/mod.rs | 6 - src/commands/voice/player_common.rs | 8 +- src/commands/voice/{radio/mod.rs => radio.rs} | 3 + src/commands/voice/radio/radio_player.rs | 115 ++- src/commands/voice/radio/radio_utils.rs | 83 ++ .../voice/{spotify/mod.rs => spotify.rs} | 0 .../voice/{util.rs => voice_utils.rs} | 9 +- src/commands/voice/{yt/mod.rs => yt.rs} | 2 +- src/main.rs | 13 +- src/message_handler.rs | 4 +- src/other/notice.rs | 4 +- src/types.rs | 9 +- src/{util/mod.rs => utils.rs} | 0 src/{util => utils}/debug.rs | 0 src/{util => utils}/embeds.rs | 0 src/{util => utils}/gifs.rs | 0 .../poise_context_extension.rs | 0 src/{util => utils}/utilities.rs | 0 31 files changed, 1031 insertions(+), 183 deletions(-) rename src/{commands/mod.rs => commands.rs} (64%) rename src/commands/{moover/mod.rs => moover.rs} (64%) create mode 100644 src/commands/moover/gif.rs rename src/commands/{notice/mod.rs => notice.rs} (78%) delete mode 100644 src/commands/other/mod.rs rename src/commands/{user_interactions/mod.rs => user_interactions.rs} (85%) create mode 100644 src/commands/voice.rs delete mode 100644 src/commands/voice/general/mod.rs rename src/commands/voice/{general => }/general_player.rs (79%) delete mode 100644 src/commands/voice/mod.rs rename src/commands/voice/{radio/mod.rs => radio.rs} (55%) create mode 100644 src/commands/voice/radio/radio_utils.rs rename src/commands/voice/{spotify/mod.rs => spotify.rs} (100%) rename src/commands/voice/{util.rs => voice_utils.rs} (86%) rename src/commands/voice/{yt/mod.rs => yt.rs} (54%) rename src/{util/mod.rs => utils.rs} (100%) rename src/{util => utils}/debug.rs (100%) rename src/{util => utils}/embeds.rs (100%) rename src/{util => utils}/gifs.rs (100%) rename src/{util => utils}/poise_context_extension.rs (100%) rename src/{util => utils}/utilities.rs (100%) diff --git a/.gitignore b/.gitignore index 2c549b2..f50483c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ # IDE config .vscode -mooverdb.db* \ No newline at end of file +mooverdb.db* + +*.txt \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index d88a0c7..b28a66d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,18 +52,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy 0.7.35", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -96,9 +84,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arrayvec" @@ -109,6 +97,184 @@ dependencies = [ "serde", ] +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.3.1", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", + "tokio", +] + +[[package]] +name = "async-io" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel 2.3.1", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.3.1", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-std" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +dependencies = [ + "async-attributes", + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-std-resolver" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa5ee46ec0c518414838d2fdc7dd18f6ba7d934b6e728005c958621da450682d" +dependencies = [ + "async-std", + "async-trait", + "futures-io", + "futures-util", + "hickory-resolver", + "pin-utils", + "socket2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.81" @@ -224,6 +390,19 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel 2.3.1", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -323,9 +502,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -571,7 +750,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -676,6 +855,17 @@ dependencies = [ "pnet_macros_support", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "dotenv" version = "0.15.0" @@ -706,6 +896,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -742,6 +944,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "event-listener" version = "5.3.1" @@ -753,6 +961,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + [[package]] name = "extended" version = "0.1.0" @@ -793,6 +1011,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "foreign-types" version = "0.3.2" @@ -885,6 +1109,19 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -994,6 +1231,18 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "h2" version = "0.3.26" @@ -1037,18 +1286,25 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ - "ahash", "allocator-api2", + "equivalent", + "foldhash", ] [[package]] name = "hashlink" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown", + "hashbrown 0.15.2", ] [[package]] @@ -1083,12 +1339,61 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hickory-proto" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447afdcdb8afb9d0a852af6dc65d9b285ce720ed7a59e42a8bf2e931c67bc1b5" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 1.0.3", + "ipnet", + "once_cell", + "rand", + "thiserror 1.0.64", + "tinyvec", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2e2aba9c389ce5267d31cf1e4dace82390ae276b0b364ea55630b1fa1b44b4" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror 1.0.64", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -1110,7 +1415,7 @@ dependencies = [ "shorthand", "stable-vec", "strum", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -1131,6 +1436,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" version = "0.2.12" @@ -1345,6 +1661,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1361,6 +1795,27 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indexmap" version = "2.3.0" @@ -1368,7 +1823,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1380,6 +1835,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1407,6 +1874,15 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1418,9 +1894,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libm" @@ -1439,12 +1915,24 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -1460,6 +1948,9 @@ name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "value-bag", +] [[package]] name = "loom" @@ -1476,6 +1967,21 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchers" version = "0.1.0" @@ -1532,12 +2038,6 @@ dependencies = [ "triomphe", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.4" @@ -1553,7 +2053,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -1568,6 +2068,7 @@ dependencies = [ "dotenv", "form_urlencoded", "poise", + "radiobrowser", "rand", "regex", "reqwest 0.11.27", @@ -1624,16 +2125,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1723,7 +2214,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -1836,12 +2327,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "patricia_tree" version = "0.8.0" @@ -1898,6 +2383,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -1984,6 +2480,21 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "polling" +version = "3.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "poly1305" version = "0.8.0" @@ -2025,7 +2536,7 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f" dependencies = [ - "zerocopy 0.6.6", + "zerocopy", ] [[package]] @@ -2057,6 +2568,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.36" @@ -2066,6 +2583,21 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radiobrowser" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763ad5f847e3d2e3221dac4e87370297a970e3f9eb8f2760b915001b9c79023b" +dependencies = [ + "async-std", + "async-std-resolver", + "chrono", + "log", + "rand", + "reqwest 0.11.27", + "serde", +] + [[package]] name = "rand" version = "0.8.5" @@ -2258,6 +2790,16 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "ring" version = "0.16.20" @@ -2909,21 +3451,11 @@ dependencies = [ "der", ] -[[package]] -name = "sqlformat" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" -dependencies = [ - "nom", - "unicode_categories", -] - [[package]] name = "sqlx" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" +checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2934,37 +3466,31 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" +checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" dependencies = [ - "atoi", - "byteorder", "bytes", "crc", "crossbeam-queue", "either", - "event-listener", - "futures-channel", + "event-listener 5.3.1", "futures-core", "futures-intrusive", "futures-io", "futures-util", - "hashbrown", + "hashbrown 0.15.2", "hashlink", - "hex", "indexmap", "log", "memchr", "once_cell", - "paste", "percent-encoding", "serde", "serde_json", "sha2", "smallvec", - "sqlformat", - "thiserror", + "thiserror 2.0.11", "tokio", "tokio-stream", "tracing", @@ -2973,9 +3499,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" +checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" dependencies = [ "proc-macro2", "quote", @@ -2986,9 +3512,9 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" +checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" dependencies = [ "dotenvy", "either", @@ -3012,9 +3538,9 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" +checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" dependencies = [ "atoi", "base64 0.22.1", @@ -3047,16 +3573,16 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 2.0.11", "tracing", "whoami", ] [[package]] name = "sqlx-postgres" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" +checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" dependencies = [ "atoi", "base64 0.22.1", @@ -3067,7 +3593,6 @@ dependencies = [ "etcetera", "futures-channel", "futures-core", - "futures-io", "futures-util", "hex", "hkdf", @@ -3085,16 +3610,16 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 2.0.11", "tracing", "whoami", ] [[package]] name = "sqlx-sqlite" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" +checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" dependencies = [ "atoi", "flume", @@ -3122,6 +3647,12 @@ dependencies = [ "no-std-compat", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "stream_lib" version = "0.4.2" @@ -3426,6 +3957,17 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3495,7 +4037,7 @@ dependencies = [ "json", "regex", "reqwest 0.12.12", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -3504,7 +4046,16 @@ version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.64", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", ] [[package]] @@ -3518,6 +4069,17 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "thread_local" version = "1.1.8" @@ -3559,6 +4121,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -3576,9 +4148,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -3608,9 +4180,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -3862,7 +4434,7 @@ dependencies = [ "rand", "rustls 0.20.9", "sha1", - "thiserror", + "thiserror 1.0.64", "url", "utf-8", "webpki", @@ -3884,7 +4456,7 @@ dependencies = [ "rustls 0.22.4", "rustls-pki-types", "sha1", - "thiserror", + "thiserror 1.0.64", "url", "utf-8", ] @@ -3952,7 +4524,7 @@ checksum = "5dece5c06268af6a9ff4541788601e560a4284ffebfb357f713d676f13b964db" dependencies = [ "chrono", "dashmap", - "hashbrown", + "hashbrown 0.14.5", "mini-moka", "parking_lot", "secrecy", @@ -4015,12 +4587,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - [[package]] name = "universal-hash" version = "0.5.1" @@ -4050,7 +4616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna", + "idna 0.5.0", "percent-encoding", "serde", ] @@ -4061,6 +4627,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" version = "1.10.0" @@ -4076,6 +4654,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" + [[package]] name = "vcpkg" version = "0.2.15" @@ -4243,6 +4827,12 @@ dependencies = [ "wasite", ] +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "winapi" version = "0.3.9" @@ -4480,6 +5070,42 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.6.6" @@ -4487,16 +5113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" dependencies = [ "byteorder", - "zerocopy-derive 0.6.6", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive 0.7.35", + "zerocopy-derive", ] [[package]] @@ -4511,14 +5128,24 @@ dependencies = [ ] [[package]] -name = "zerocopy-derive" -version = "0.7.35" +name = "zerofrom" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", "syn 2.0.87", + "synstructure", ] [[package]] @@ -4526,3 +5153,25 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] diff --git a/Cargo.toml b/Cargo.toml index c9e3f30..79850ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,21 +7,22 @@ edition = "2021" [dependencies] rand = "0.8.5" -anyhow = "1.0.89" +anyhow = "1.0.95" tokio-cron-scheduler = "0.13.0" dotenv = "0.15.0" poise = "0.6.1" serenity = { version = "0.12.4", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] } # serenity_utils = "0.7.0" -tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] } regex = "1.11.1" -chrono = "0.4.38" -sqlx = {version="0.8.2", features=["runtime-tokio", "sqlite"]} +chrono = "0.4.39" +sqlx = {version="0.8.3", features=["runtime-tokio", "sqlite"]} form_urlencoded = "1.2.1" tenorv2 = { path = "./tenor-v2/tenorv2" } # librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] } songbird = { version = "0.4.6", features = ["driver", "builtin-queue"] } reqwest = "0.11.27" # songbird depends on ^0.11 +radiobrowser = "0.6.1" [dependencies.symphonia] version = "0.5.2" diff --git a/src/commands/mod.rs b/src/commands.rs similarity index 64% rename from src/commands/mod.rs rename to src/commands.rs index df0d152..6a1c0f7 100644 --- a/src/commands/mod.rs +++ b/src/commands.rs @@ -1,11 +1,13 @@ pub use moover::*; pub use notice::*; pub use user_interactions::*; -pub use other::*; +// pub use other::*; pub use voice::*; +// pub use command_utils::*; pub mod moover; pub mod notice; pub mod user_interactions; -pub mod other; +// pub mod other; pub mod voice; +// mod command_utils; diff --git a/src/commands/moover/mod.rs b/src/commands/moover.rs similarity index 64% rename from src/commands/moover/mod.rs rename to src/commands/moover.rs index 51a3f5b..f2c99f7 100644 --- a/src/commands/moover/mod.rs +++ b/src/commands/moover.rs @@ -1,7 +1,7 @@ pub use moove::*; +pub use gif::*; pub use say::*; -// pub use gif::*; pub mod moove; +pub mod gif; pub mod say; -// pub mod gif; diff --git a/src/commands/moover/gif.rs b/src/commands/moover/gif.rs new file mode 100644 index 0000000..4861a37 --- /dev/null +++ b/src/commands/moover/gif.rs @@ -0,0 +1,20 @@ +use poise; +use serenity::all::{Embed, User}; + +use crate::types::{Error, Context}; + +#[poise::command( + slash_command, + description_localized("en-US", "Send a gif from Tenor") +)] +pub async fn gif(ctx: Context<'_>, + #[description = "What should I search?"] + what: String, + #[description = "Should the gif be R-rated?"] + contentfilter: String +) -> Result<(), Error> { + // let embed; + // send_with_embed(ctx, "hug", &title, &desc).await?; + ctx.reply("Done!").await?; + Ok(()) +} \ No newline at end of file diff --git a/src/commands/notice/mod.rs b/src/commands/notice.rs similarity index 78% rename from src/commands/notice/mod.rs rename to src/commands/notice.rs index d63767d..33bed17 100644 --- a/src/commands/notice/mod.rs +++ b/src/commands/notice.rs @@ -2,4 +2,4 @@ pub use birthday::*; pub use events::*; pub mod birthday; -pub mod events; \ No newline at end of file +pub mod events; diff --git a/src/commands/other/mod.rs b/src/commands/other/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/commands/user_interactions/mod.rs b/src/commands/user_interactions.rs similarity index 85% rename from src/commands/user_interactions/mod.rs rename to src/commands/user_interactions.rs index 0e8654b..f9a7882 100644 --- a/src/commands/user_interactions/mod.rs +++ b/src/commands/user_interactions.rs @@ -3,4 +3,4 @@ pub use hug::*; pub mod interaction; pub mod headpat; -pub mod hug; \ No newline at end of file +pub mod hug; diff --git a/src/commands/user_interactions/interaction.rs b/src/commands/user_interactions/interaction.rs index 6db121a..f495f3e 100644 --- a/src/commands/user_interactions/interaction.rs +++ b/src/commands/user_interactions/interaction.rs @@ -2,7 +2,7 @@ use anyhow::anyhow; use serenity::all::{Colour, CreateEmbed, CreateMessage}; use tenorv2::tenor_builder::Tenor; -use crate::{types::Context, util::{gifs::get_random_tenor_gif, utilities}}; +use crate::{types::Context, utils::{gifs::get_random_tenor_gif, utilities}}; /// Sends embed with random tenor gif from searched query /// title and desc are used in the embed diff --git a/src/commands/voice.rs b/src/commands/voice.rs new file mode 100644 index 0000000..98fd8f5 --- /dev/null +++ b/src/commands/voice.rs @@ -0,0 +1,11 @@ +use voice_utils::*; + +mod voice_utils; +pub mod player_common; +pub mod radio; +pub mod general_player; + +// ! not working +// pub mod yt; +// TODO implement +// pub mod spotify; diff --git a/src/commands/voice/general/mod.rs b/src/commands/voice/general/mod.rs deleted file mode 100644 index 8b6dfd4..0000000 --- a/src/commands/voice/general/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub use general_player::*; - -pub mod general_player; \ No newline at end of file diff --git a/src/commands/voice/general/general_player.rs b/src/commands/voice/general_player.rs similarity index 79% rename from src/commands/voice/general/general_player.rs rename to src/commands/voice/general_player.rs index c3cd0d6..860d22f 100644 --- a/src/commands/voice/general/general_player.rs +++ b/src/commands/voice/general_player.rs @@ -2,10 +2,11 @@ use std::vec; use songbird::input::YoutubeDl; -use crate::commands::util::connect; -use crate::util::poise_context_extension::ContextExt; +use crate::utils::poise_context_extension::ContextExt; use crate::types::{Context, Error}; -use crate::commands::voice::util::autocomplete_channel; +use crate::commands::voice::voice_utils::autocomplete_channel; + +use super::connect; // TODO: search, queue #[poise::command( @@ -38,12 +39,9 @@ pub async fn play(ctx: Context<'_>, let http_client = &ctx.data().http_client; if manager.get(guild_id).is_none() { - match connect(&ctx, guild_id, channel).await { - Ok(_) => (), - Err(e) => { - ctx.reply_ephemeral(&e.to_string()).await?; - return Ok(()) - } + if let Err(e) = connect(&ctx, guild_id, channel).await { + ctx.reply_ephemeral(&e.to_string()).await?; + return Ok(()) } } diff --git a/src/commands/voice/mod.rs b/src/commands/voice/mod.rs deleted file mode 100644 index f3d7e73..0000000 --- a/src/commands/voice/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod util; -pub mod player_common; -pub mod radio; -// pub mod spotify; -pub mod general; -pub mod yt; \ No newline at end of file diff --git a/src/commands/voice/player_common.rs b/src/commands/voice/player_common.rs index 38ac50a..f87031c 100644 --- a/src/commands/voice/player_common.rs +++ b/src/commands/voice/player_common.rs @@ -2,12 +2,12 @@ use std::vec; use songbird::input::{File, Input}; -use crate::util::debug::send_error; -use crate::util::poise_context_extension::ContextExt; -use crate::util::utilities::get_local_songs; +use crate::utils::debug::send_error; +use crate::utils::poise_context_extension::ContextExt; +use crate::utils::utilities::get_local_songs; use crate::types::{Context, Error}; -use super::util::{connect, autocomplete_channel}; +use super::voice_utils::{connect, autocomplete_channel}; /** * Common commands that are the same for every implementation diff --git a/src/commands/voice/radio/mod.rs b/src/commands/voice/radio.rs similarity index 55% rename from src/commands/voice/radio/mod.rs rename to src/commands/voice/radio.rs index 27ead6c..0ea2063 100644 --- a/src/commands/voice/radio/mod.rs +++ b/src/commands/voice/radio.rs @@ -1,3 +1,6 @@ pub use radio_player::*; +use radio_utils::*; pub mod radio_player; + +mod radio_utils; diff --git a/src/commands/voice/radio/radio_player.rs b/src/commands/voice/radio/radio_player.rs index b9ed39d..599c610 100644 --- a/src/commands/voice/radio/radio_player.rs +++ b/src/commands/voice/radio/radio_player.rs @@ -1,26 +1,41 @@ use std::vec; +use radiobrowser::RadioBrowserAPI; use reqwest::Client; use songbird::input::Input; use songbird::input::HttpRequest; -use crate::commands::util::connect; -use crate::util::poise_context_extension::ContextExt; +use super::super::connect; +use crate::utils::poise_context_extension::ContextExt; use crate::types::{Context, Error}; -use crate::commands::voice::util::autocomplete_channel; +use crate::commands::voice::voice_utils::autocomplete_channel; + +use super::radio_utils::paginate_search; + +use super::super::voice_utils::MAX_ENTRIES; + +#[poise::command( + slash_command, + description_localized("en-US", "Plays music from URL source"), + subcommands("search", "play") +)] +pub async fn radio(_ctx: Context<'_>) -> Result<(), Error> { + Ok(()) +} // TODO: autocomplete radio stream URLs #[poise::command( slash_command, description_localized("en-US", "Plays music from URL source") )] -pub async fn radio(ctx: Context<'_>, +pub async fn play(ctx: Context<'_>, #[autocomplete = "autocomplete_channel"] #[description = "Voice channel name: "] channel: Option, - #[description = "Source URL: "] - url: String, + #[autocomplete = "autocomplete_radio"] + #[description = "Radio station: "] + name: String, ) -> Result<(), Error> { if ctx.guild().is_none() { @@ -39,12 +54,9 @@ pub async fn radio(ctx: Context<'_>, }; if manager.get(guild_id).is_none() { - match connect(&ctx, guild_id, channel).await { - Ok(_) => (), - Err(e) => { - ctx.reply_ephemeral(&e.to_string()).await?; - return Ok(()) - } + if let Err(e) = connect(&ctx, guild_id, channel).await { + ctx.reply_ephemeral(&e.to_string()).await?; + return Ok(()) } } @@ -52,7 +64,7 @@ pub async fn radio(ctx: Context<'_>, let mut handler = handler_lock.lock().await; let client = Client::new(); - let request = HttpRequest::new(client, url); + let request = HttpRequest::new(client, name); let input = Input::from(request); handler.play_only_input(input); } @@ -64,3 +76,80 @@ pub async fn radio(ctx: Context<'_>, ctx.reply_ephemeral("Done!").await?; Ok(()) } + +async fn autocomplete_radio( + ctx: Context<'_>, + partial: &str +) -> Vec { + + let api = { + match &ctx.data().radio_browser { + Some(v) => v.clone(), + None => { + let Ok(radio_browser) = RadioBrowserAPI::new().await else { + return vec!["There was an error with radio API!".to_owned()] + }; + radio_browser + } + } + }; + + let stations: Vec = match api.get_stations() + .limit(MAX_ENTRIES) + .name(partial) + .hidebroken(true) + .send().await { + Ok(stations) => { + stations.iter().map(|station| + format!("Name: {} Language: {} Bitrate: {}", station.name, station.countrycode, station.bitrate) + ).collect() + }, + Err(_) => return vec!["".to_owned()] + }; + + dbg!(&stations); + + return stations + // return vec![]; +} + +// TODO +// autocomplete +// search with buttons and list in embed with direct links to stream +// embed showing currently playing song + +// TODO: autocomplete radio stream URLs +#[poise::command( + slash_command, + description_localized("en-US", "Search for a radio") +)] +pub async fn search(ctx: Context<'_>, + #[description = "Radio station: "] + name: String, + #[description = "Country: "] + country: Option, + #[description = "Tag: "] + tag: Option +) -> Result<(), Error> { + + let api = match &ctx.data().radio_browser { + Some(v) => v.clone(), + None => { + let Ok(radio_browser) = RadioBrowserAPI::new().await else { + let _ = ctx.reply_ephemeral("There was an error with radio API!").await; + return Ok(()) + }; + radio_browser + } + }; + + let station_search_builder = api.get_stations() + .name(name) + .tag(tag.unwrap_or("".to_owned())) + .country(country.unwrap_or("".to_owned())) + .hidebroken(true); + + paginate_search(ctx, station_search_builder); + + Ok(()) +} diff --git a/src/commands/voice/radio/radio_utils.rs b/src/commands/voice/radio/radio_utils.rs new file mode 100644 index 0000000..de1832c --- /dev/null +++ b/src/commands/voice/radio/radio_utils.rs @@ -0,0 +1,83 @@ +use poise::{ChoiceParameter, CreateReply}; +use radiobrowser::StationSearchBuilder; +use serenity::{all::{CreateActionRow, CreateButton, CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage}, futures::SinkExt}; + +use crate::types::Context; + +#[derive(ChoiceParameter)] +pub enum WelcomeChoice { + #[name = "5"] + A, + #[name = "10"] + B, + #[name = "15"] + C +} + +pub async fn paginate_search( + ctx: Context<'_>, + search_builder: StationSearchBuilder, +) -> Result<(), serenity::Error> { + // Define some unique identifiers for the navigation buttons + let ctx_id = ctx.id(); + let prev_button_id = format!("{}prev", ctx_id); + let next_button_id = format!("{}next", ctx_id); + + let Ok(stations) = search_builder.send().await else { + let _ = ctx.reply("Something went wrong, try searching again").await; + return Ok(()) + }; + + // Send the embed with the first page as content + let reply = { + let components = CreateActionRow::Buttons(vec![ + CreateButton::new(&prev_button_id).emoji('◀'), + CreateButton::new(&next_button_id).emoji('▶'), + ]); + + CreateReply::default() + .embed(CreateEmbed::new()) + .components(vec![components]) + }; + + ctx.send(reply).await?; + + // Loop through incoming interactions with the navigation buttons + let mut current_page = 0; + while let Some(press) = serenity::collector::ComponentInteractionCollector::new(ctx) + // We defined our button IDs to start with `ctx_id`. If they don't, some other command's + // button was pressed + .filter(move |press| press.data.custom_id.starts_with(&ctx_id.to_string())) + // Timeout when no navigation button has been pressed for 24 hours + .timeout(std::time::Duration::from_secs(3600 * 24)) + .await + { + // Depending on which button was pressed, go to next or previous page + if press.data.custom_id == next_button_id { + current_page += 1; + // TODO find a way to check end + // if current_page >= pages.len() { + // current_page = 0; + // } + } else if press.data.custom_id == prev_button_id { + // TODO find a way to get pages len + // current_page = current_page.checked_sub(1).unwrap_or(pages.len() - 1); + } else { + // This is an unrelated button interaction + continue; + } + + // Update the message with the new page contents + press + .create_response( + ctx.serenity_context(), + CreateInteractionResponse::UpdateMessage( + CreateInteractionResponseMessage::new() + .embed(CreateEmbed::new()), + ), + ) + .await?; + } + + Ok(()) +} diff --git a/src/commands/voice/spotify/mod.rs b/src/commands/voice/spotify.rs similarity index 100% rename from src/commands/voice/spotify/mod.rs rename to src/commands/voice/spotify.rs diff --git a/src/commands/voice/util.rs b/src/commands/voice/voice_utils.rs similarity index 86% rename from src/commands/voice/util.rs rename to src/commands/voice/voice_utils.rs index 4208b51..d9e4a8c 100644 --- a/src/commands/voice/util.rs +++ b/src/commands/voice/voice_utils.rs @@ -1,10 +1,13 @@ -use serenity::all::{ChannelId, GuildId}; +use poise::{CreateReply}; +use serenity::all::{ChannelId, CreateActionRow, CreateButton, CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage, Embed, GuildId}; use serenity::async_trait; use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; use songbird::TrackEvent; -use crate::{types::{Context, Error}, util::utilities::get_channel_by_name}; +use crate::{types::{Context, Error}, utils::utilities::get_channel_by_name}; + +pub const MAX_ENTRIES: &str = "15"; /// Returns either voice channel to which the user is currently connected to or the one passed via name async fn get_voice_channel(ctx: &Context<'_>, name: Option) -> Result { @@ -68,7 +71,7 @@ pub async fn autocomplete_channel( _partial: &str, ) -> Vec { - use crate::util::utilities::get_vc_names; + use crate::utils::utilities::get_vc_names; match ctx.guild() { Some(guild) => get_vc_names(guild), None => [].to_vec() diff --git a/src/commands/voice/yt/mod.rs b/src/commands/voice/yt.rs similarity index 54% rename from src/commands/voice/yt/mod.rs rename to src/commands/voice/yt.rs index 989288e..af9e888 100644 --- a/src/commands/voice/yt/mod.rs +++ b/src/commands/voice/yt.rs @@ -1,3 +1,3 @@ pub use yt_player::*; -pub mod yt_player; \ No newline at end of file +pub mod yt_player; diff --git a/src/main.rs b/src/main.rs index 66380e6..a36e45a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ mod message_handler; use message_handler::handle; mod commands; -mod util; +mod utils; mod other; use other::notice; @@ -57,7 +57,7 @@ impl EventHandler for Handler { println!("{} v3.3.1 is connected!", ready.user.name); #[cfg(feature="RELEASE")] { - use util::debug::hello; + use utils::debug::hello; let _ = hello(ctx.http.clone()).await; } @@ -87,10 +87,9 @@ async fn main() -> anyhow::Result<()> { commands::say(), commands::hug(), // commands::player::play_local(), - commands::player_common::disconnect(), commands::radio::radio(), - commands::general::play(), - commands::yt::play_yt() + commands::general_player::play(), + commands::player_common::disconnect(), ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), @@ -129,8 +128,10 @@ async fn main() -> anyhow::Result<()> { register_globally(ctx, &framework.options().commands).await?; } + Ok(Data { - http_client: HttpClient::new() + http_client: HttpClient::new(), + radio_browser: RadioBrowserAPI::new().await.ok() }) }) }) diff --git a/src/message_handler.rs b/src/message_handler.rs index 4aa263e..8033036 100644 --- a/src/message_handler.rs +++ b/src/message_handler.rs @@ -5,8 +5,8 @@ use serenity::model::channel::Message; use std::collections::HashMap; use std::sync::Arc; -use crate::util::debug::send_error; -use crate::util::utilities; +use crate::utils::debug::send_error; +use crate::utils::utilities; use crate::commands::moover::moove::{moove, moove_check}; diff --git a/src/other/notice.rs b/src/other/notice.rs index 69b39ed..9d75231 100644 --- a/src/other/notice.rs +++ b/src/other/notice.rs @@ -6,8 +6,8 @@ use serenity::{all::{GuildId, UserId}, builder::{CreateEmbed, CreateMessage}, cl use sqlx::{Connection, FromRow, SqliteConnection}; -use crate::util::debug::send_error; -use crate::util::utilities; +use crate::utils::debug::send_error; +use crate::utils::utilities; use std::{env, sync::Arc}; diff --git a/src/types.rs b/src/types.rs index 1103f1c..068d8e4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,20 +2,15 @@ use std::{ffi::OsString, path::PathBuf}; -use serenity::prelude::TypeMapKey; - +use radiobrowser::RadioBrowserAPI; use reqwest::Client as HttpClient; // TODO: this should be probably expanded also to be used by multiple servers and commands // radio and spotify commands always create new HttpClient -pub struct HttpKey; - -impl TypeMapKey for HttpKey { - type Value = HttpClient; -} pub struct Data { pub http_client: HttpClient, + pub radio_browser: Option, } pub type Error = Box; diff --git a/src/util/mod.rs b/src/utils.rs similarity index 100% rename from src/util/mod.rs rename to src/utils.rs diff --git a/src/util/debug.rs b/src/utils/debug.rs similarity index 100% rename from src/util/debug.rs rename to src/utils/debug.rs diff --git a/src/util/embeds.rs b/src/utils/embeds.rs similarity index 100% rename from src/util/embeds.rs rename to src/utils/embeds.rs diff --git a/src/util/gifs.rs b/src/utils/gifs.rs similarity index 100% rename from src/util/gifs.rs rename to src/utils/gifs.rs diff --git a/src/util/poise_context_extension.rs b/src/utils/poise_context_extension.rs similarity index 100% rename from src/util/poise_context_extension.rs rename to src/utils/poise_context_extension.rs diff --git a/src/util/utilities.rs b/src/utils/utilities.rs similarity index 100% rename from src/util/utilities.rs rename to src/utils/utilities.rs From bbf65e645819b7cfc82affd609aac8e59950c2a2 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 26 Jan 2025 15:58:07 +0100 Subject: [PATCH 16/19] chore: add radiobrowser fork as submodule --- .gitmodules | 3 +++ Cargo.lock | 3 +-- Cargo.toml | 3 ++- radiobrowser | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) create mode 160000 radiobrowser diff --git a/.gitmodules b/.gitmodules index 3ad93ca..ae57159 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "tenor-v2"] path = tenor-v2 url = ssh://git@forgejo.djkato.net:222/HLadislav/tenor-v2.git +[submodule "radiobrowser"] + path = radiobrowser + url = ./radiobrowser diff --git a/Cargo.lock b/Cargo.lock index b28a66d..148d130 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2586,8 +2586,6 @@ dependencies = [ [[package]] name = "radiobrowser" version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763ad5f847e3d2e3221dac4e87370297a970e3f9eb8f2760b915001b9c79023b" dependencies = [ "async-std", "async-std-resolver", @@ -2596,6 +2594,7 @@ dependencies = [ "rand", "reqwest 0.11.27", "serde", + "serde_json", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 79850ab..c557b4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,8 @@ tenorv2 = { path = "./tenor-v2/tenorv2" } # librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] } songbird = { version = "0.4.6", features = ["driver", "builtin-queue"] } reqwest = "0.11.27" # songbird depends on ^0.11 -radiobrowser = "0.6.1" +# radiobrowser = "0.6.1" +radiobrowser = { path = "./radiobrowser" } [dependencies.symphonia] version = "0.5.2" diff --git a/radiobrowser b/radiobrowser new file mode 160000 index 0000000..0786c89 --- /dev/null +++ b/radiobrowser @@ -0,0 +1 @@ +Subproject commit 0786c897260c7f180917af101ae5ea686cb60c2e From 67f1b4176bba33cd8c35757860273b5a9d06ec67 Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 26 Jan 2025 21:39:54 +0100 Subject: [PATCH 17/19] chore: update tenor-v2 --- tenor-v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tenor-v2 b/tenor-v2 index fd8c8bd..66cf5cc 160000 --- a/tenor-v2 +++ b/tenor-v2 @@ -1 +1 @@ -Subproject commit fd8c8bde1be41116fe398776c45625a19ec10281 +Subproject commit 66cf5cc388af947846caf5b7118257df01d60725 From 0ff20483c9f4424dff181a68baa2f0379ee2b9fc Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 26 Jan 2025 21:45:24 +0100 Subject: [PATCH 18/19] feat: fully implemented radio player --- src/commands/voice.rs | 1 + src/commands/voice/general_player.rs | 3 +- src/commands/voice/player_common.rs | 49 ++++++- src/commands/voice/radio/radio_player.rs | 108 ++++++++++----- src/commands/voice/radio/radio_utils.rs | 165 ++++++++++++++++------- src/commands/voice/voice_types.rs | 91 +++++++++++++ src/commands/voice/voice_utils.rs | 3 +- src/main.rs | 8 +- src/types.rs | 30 +++-- src/utils.rs | 3 +- src/utils/poise_context_extension.rs | 22 --- src/utils/utilities.rs | 15 ++- 12 files changed, 375 insertions(+), 123 deletions(-) create mode 100644 src/commands/voice/voice_types.rs delete mode 100644 src/utils/poise_context_extension.rs diff --git a/src/commands/voice.rs b/src/commands/voice.rs index 98fd8f5..a86fe29 100644 --- a/src/commands/voice.rs +++ b/src/commands/voice.rs @@ -4,6 +4,7 @@ mod voice_utils; pub mod player_common; pub mod radio; pub mod general_player; +pub mod voice_types; // ! not working // pub mod yt; diff --git a/src/commands/voice/general_player.rs b/src/commands/voice/general_player.rs index 860d22f..3ad9b7b 100644 --- a/src/commands/voice/general_player.rs +++ b/src/commands/voice/general_player.rs @@ -2,8 +2,7 @@ use std::vec; use songbird::input::YoutubeDl; -use crate::utils::poise_context_extension::ContextExt; -use crate::types::{Context, Error}; +use crate::types::{Context, ContextExt, Error}; use crate::commands::voice::voice_utils::autocomplete_channel; use super::connect; diff --git a/src/commands/voice/player_common.rs b/src/commands/voice/player_common.rs index f87031c..8eee740 100644 --- a/src/commands/voice/player_common.rs +++ b/src/commands/voice/player_common.rs @@ -1,11 +1,11 @@ use std::vec; +use poise::CreateReply; use songbird::input::{File, Input}; use crate::utils::debug::send_error; -use crate::utils::poise_context_extension::ContextExt; +use crate::types::{Context, ContextExt, Error}; use crate::utils::utilities::get_local_songs; -use crate::types::{Context, Error}; use super::voice_utils::{connect, autocomplete_channel}; @@ -114,3 +114,48 @@ pub async fn play_local(ctx: Context<'_>, ctx.reply_ephemeral("Done!").await?; Ok(()) } + + +#[poise::command( + slash_command, + description_localized("en-US", "Display currently playing info") +)] +pub async fn playing(ctx: Context<'_>) -> Result<(), Error> { + + let Some(guild_id) = ctx.guild_id() else { + ctx.reply_ephemeral("Guild id not found").await?; + return Ok(()) + }; + + let manager = songbird::get(ctx.serenity_context()) + .await + .expect("Songbird Voice client placed in at initialisation.") + .clone(); + + let Some(_) = manager.get(guild_id) else { + ctx.reply_ephemeral("I am not connected to any voice channel right now").await?; + return Ok(()) + }; + + // println!("here"); + + let embed = { + let mutex_hashmap = ctx.data().playing_info.lock().await; + let Some(playing_info) = mutex_hashmap.get(&guild_id) else { + ctx.reply_ephemeral("Entry not found, try to reconnect me").await?; + return Ok(()); + }; + + playing_info.generate_embed().await + }; + + dbg!(&embed); + + ctx.send( + CreateReply::default() + .embed(embed) + ).await?; + + Ok(()) +} + diff --git a/src/commands/voice/radio/radio_player.rs b/src/commands/voice/radio/radio_player.rs index 599c610..f669429 100644 --- a/src/commands/voice/radio/radio_player.rs +++ b/src/commands/voice/radio/radio_player.rs @@ -1,17 +1,22 @@ use std::vec; -use radiobrowser::RadioBrowserAPI; +use poise::ChoiceParameter; use reqwest::Client; use songbird::input::Input; use songbird::input::HttpRequest; use super::super::connect; -use crate::utils::poise_context_extension::ContextExt; +use super::link_or_string; +use super::parse_radio_autocomplete; +use super::LinkString; +use crate::commands::voice_types::NumberOfEntries; +use crate::commands::voice_types::PlayingInfoType; +use crate::types::ContextExt; use crate::types::{Context, Error}; use crate::commands::voice::voice_utils::autocomplete_channel; -use super::radio_utils::paginate_search; +use super::radio_utils::paginate_search_stations; use super::super::voice_utils::MAX_ENTRIES; @@ -24,6 +29,8 @@ pub async fn radio(_ctx: Context<'_>) -> Result<(), Error> { Ok(()) } +// TODO: deduplicate you use a lot of the same code + // TODO: autocomplete radio stream URLs #[poise::command( slash_command, @@ -43,6 +50,47 @@ pub async fn play(ctx: Context<'_>, return Ok(()); } + let api = &ctx.data().radio_browser; + + let stations_result = match link_or_string(&name) { + LinkString::Link => { + if name.ends_with(".m3u") { + ctx.reply_ephemeral("Sorry, currently I don't support m3u files").await?; + return Ok(()); + } + + api.get_stations().byurl(name).await + }, + LinkString::String => { + let (name, country, language) = match parse_radio_autocomplete(&name) { + Some(tuple) => tuple, + None => { + ctx.reply_ephemeral("Please use either direct URL or provided autocomplete").await?; + return Ok(()) + } + }; + + api.get_stations() + .name_exact(true) + .name(name) + .country_exact(true) + .country(country) + .language_exact(true) + .language(language) + .send().await + } + }; + + let Ok(stations) = stations_result else { + ctx.reply_ephemeral("There was an error with radio API!").await?; + return Ok(()) + }; + + let Some(station) = stations.first() else { + ctx.reply_ephemeral("Radio station not found!").await?; + return Ok(()) + }; + let manager = songbird::get(ctx.serenity_context()) .await .expect("Songbird Voice client placed in at initialisation.") @@ -54,8 +102,9 @@ pub async fn play(ctx: Context<'_>, }; if manager.get(guild_id).is_none() { - if let Err(e) = connect(&ctx, guild_id, channel).await { + if let Err(e) = connect(&ctx, guild_id, channel).await { ctx.reply_ephemeral(&e.to_string()).await?; + println!("SONGBIRD MANAGER ERROR: {}", e.to_string()); return Ok(()) } } @@ -64,7 +113,7 @@ pub async fn play(ctx: Context<'_>, let mut handler = handler_lock.lock().await; let client = Client::new(); - let request = HttpRequest::new(client, name); + let request = HttpRequest::new(client, station.url.clone()); let input = Input::from(request); handler.play_only_input(input); } @@ -73,6 +122,11 @@ pub async fn play(ctx: Context<'_>, return Ok(()) } + { + let mut hash_map = ctx.data().playing_info.lock().await; + hash_map.insert(guild_id, PlayingInfoType::RadioInfo(station.clone())); + } + ctx.reply_ephemeral("Done!").await?; Ok(()) } @@ -82,17 +136,7 @@ async fn autocomplete_radio( partial: &str ) -> Vec { - let api = { - match &ctx.data().radio_browser { - Some(v) => v.clone(), - None => { - let Ok(radio_browser) = RadioBrowserAPI::new().await else { - return vec!["There was an error with radio API!".to_owned()] - }; - radio_browser - } - } - }; + let api = &ctx.data().radio_browser; let stations: Vec = match api.get_stations() .limit(MAX_ENTRIES) @@ -100,14 +144,14 @@ async fn autocomplete_radio( .hidebroken(true) .send().await { Ok(stations) => { - stations.iter().map(|station| - format!("Name: {} Language: {} Bitrate: {}", station.name, station.countrycode, station.bitrate) + stations.iter().map(|station: &radiobrowser::ApiStation| + format!("Name: {} Country: {} Language: {}", station.name, station.country, station.language) ).collect() }, Err(_) => return vec!["".to_owned()] }; - dbg!(&stations); + // dbg!(&stations); return stations // return vec![]; @@ -118,7 +162,11 @@ async fn autocomplete_radio( // search with buttons and list in embed with direct links to stream // embed showing currently playing song +// use trace::trace; +// trace::init_depth_var!(); + // TODO: autocomplete radio stream URLs +// #[trace] #[poise::command( slash_command, description_localized("en-US", "Search for a radio") @@ -129,27 +177,23 @@ pub async fn search(ctx: Context<'_>, #[description = "Country: "] country: Option, #[description = "Tag: "] - tag: Option + tag: Option, + #[description = "Number of entries on page: "] + entries: Option ) -> Result<(), Error> { - let api = match &ctx.data().radio_browser { - Some(v) => v.clone(), - None => { - let Ok(radio_browser) = RadioBrowserAPI::new().await else { - let _ = ctx.reply_ephemeral("There was an error with radio API!").await; - return Ok(()) - }; - radio_browser - } - }; + let api = &ctx.data().radio_browser; - let station_search_builder = api.get_stations() + let entries = entries.unwrap_or(NumberOfEntries::Ten); + + let search_builder = api.get_stations() + .limit(entries.name()) .name(name) .tag(tag.unwrap_or("".to_owned())) .country(country.unwrap_or("".to_owned())) .hidebroken(true); - paginate_search(ctx, station_search_builder); + paginate_search_stations(&ctx, &search_builder, entries).await?; Ok(()) } diff --git a/src/commands/voice/radio/radio_utils.rs b/src/commands/voice/radio/radio_utils.rs index de1832c..9889928 100644 --- a/src/commands/voice/radio/radio_utils.rs +++ b/src/commands/voice/radio/radio_utils.rs @@ -1,83 +1,144 @@ -use poise::{ChoiceParameter, CreateReply}; -use radiobrowser::StationSearchBuilder; -use serenity::{all::{CreateActionRow, CreateButton, CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage}, futures::SinkExt}; +use poise::CreateReply; +use radiobrowser::{ApiStation, StationSearchBuilder}; +use regex::Regex; +use serenity::all::{CreateActionRow, CreateButton, CreateEmbed, CreateEmbedFooter, CreateInteractionResponse, CreateInteractionResponseMessage}; -use crate::types::Context; +use crate::{commands::voice_types::NumberOfEntries, types::Context}; -#[derive(ChoiceParameter)] -pub enum WelcomeChoice { - #[name = "5"] - A, - #[name = "10"] - B, - #[name = "15"] - C -} - -pub async fn paginate_search( - ctx: Context<'_>, - search_builder: StationSearchBuilder, +pub async fn paginate_search_stations( + ctx: &Context<'_>, + search_builder: &StationSearchBuilder, + limit: NumberOfEntries ) -> Result<(), serenity::Error> { // Define some unique identifiers for the navigation buttons let ctx_id = ctx.id(); let prev_button_id = format!("{}prev", ctx_id); let next_button_id = format!("{}next", ctx_id); - - let Ok(stations) = search_builder.send().await else { - let _ = ctx.reply("Something went wrong, try searching again").await; + + let search_builder = search_builder; + + let Ok(stations) = search_builder.clone().send().await else { + ctx.reply("Something went wrong, try searching again").await?; return Ok(()) }; - + + let mut page = 0; + + let embed = create_station_list_embed(&stations, page); + // Send the embed with the first page as content let reply = { let components = CreateActionRow::Buttons(vec![ CreateButton::new(&prev_button_id).emoji('◀'), CreateButton::new(&next_button_id).emoji('▶'), - ]); - - CreateReply::default() - .embed(CreateEmbed::new()) + ]); + + CreateReply::default() + .embed(embed) .components(vec![components]) - }; - - ctx.send(reply).await?; - - // Loop through incoming interactions with the navigation buttons - let mut current_page = 0; - while let Some(press) = serenity::collector::ComponentInteractionCollector::new(ctx) + }; + + ctx.send(reply).await?; + + // Loop through incoming interactions with the navigation buttons + let mut offset = 0; + let limit_int = limit as u32; + while let Some(press) = serenity::collector::ComponentInteractionCollector::new(ctx) // We defined our button IDs to start with `ctx_id`. If they don't, some other command's // button was pressed .filter(move |press| press.data.custom_id.starts_with(&ctx_id.to_string())) // Timeout when no navigation button has been pressed for 24 hours .timeout(std::time::Duration::from_secs(3600 * 24)) .await - { - // Depending on which button was pressed, go to next or previous page + { + // Depending on which button was pressed, go to next or previous page if press.data.custom_id == next_button_id { - current_page += 1; - // TODO find a way to check end - // if current_page >= pages.len() { - // current_page = 0; - // } + offset += limit_int; + page += 1; } else if press.data.custom_id == prev_button_id { - // TODO find a way to get pages len - // current_page = current_page.checked_sub(1).unwrap_or(pages.len() - 1); + offset = if offset < limit_int { offset } else { offset - limit_int }; + page = if page == 0 { 0 } else { page - 1 }; } else { // This is an unrelated button interaction continue; } + let Ok(mut stations) = search_builder.clone().offset(offset.to_string()).send().await else { + ctx.reply("Something went wrong, try searching again").await?; + return Ok(()) + }; + + if stations.is_empty() { + offset = 0; + page = 0; + + let Ok(new_stations) = search_builder.clone().offset(offset.to_string()).send().await else { + ctx.reply("Something went wrong, try searching again").await?; + return Ok(()) + }; + stations = new_stations; + } + + let embed = create_station_list_embed(&stations, page); + // Update the message with the new page contents press - .create_response( - ctx.serenity_context(), - CreateInteractionResponse::UpdateMessage( - CreateInteractionResponseMessage::new() - .embed(CreateEmbed::new()), - ), - ) - .await?; - } - - Ok(()) + .create_response( + ctx.serenity_context(), + CreateInteractionResponse::UpdateMessage( + CreateInteractionResponseMessage::new() + .embed(embed), + ), + ) + .await?; +} + +Ok(()) +} + +fn create_station_list_embed(stations: &Vec, page: u32) -> CreateEmbed { + let result = CreateEmbed::new() + .fields( + stations.iter().map(|station| { + ( + station.name.clone(), + format!("Country: {} Stream: {}", + station.country, station.url), + false + ) + }) + ) + .footer(CreateEmbedFooter::new(format!("Page: {}", page + 1))); + + result +} + +pub enum LinkString { + Link, + String +} + + +pub fn link_or_string(haystack: &str) -> LinkString { + let Ok(re) = Regex::new(r"^https?://([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$") else { + panic!("Wrong regex expression!"); + }; + + return if re.is_match(haystack) { LinkString::Link } else { LinkString::String } +} + +pub fn parse_radio_autocomplete(haystack: &str) -> Option<(String, String, String)> { + let Ok(re) = Regex::new(r"^Name: (.*) Country: (.*) Language: (.*)") else { + panic!("Wrong regex expression!"); + }; + + let Some(captures) = re.captures(haystack) else { + return None + }; + + return Some(( + String::from(&captures[1]), + String::from(&captures[2]), + String::from(&captures[3]) + )) } diff --git a/src/commands/voice/voice_types.rs b/src/commands/voice/voice_types.rs new file mode 100644 index 0000000..60fe865 --- /dev/null +++ b/src/commands/voice/voice_types.rs @@ -0,0 +1,91 @@ +use poise::ChoiceParameter; +use radiobrowser::ApiStation; +use serenity::{all::CreateEmbed, async_trait}; + +use crate::utils::utilities::hash_to_u32; + +#[derive(ChoiceParameter, Debug)] +pub enum NumberOfEntries { + #[name = "5"] + Five = 5, + #[name = "10"] + Ten = 10, + #[name = "15"] + Fifteen = 15 +} + +#[async_trait] +pub trait GenerateEmbed { + async fn generate_embed(&self) -> CreateEmbed; +} + +#[allow(dead_code)] +pub struct SpotifyInfo { + pub name: String, + pub interpret: String, + // client + pub duration: String, +} + +#[allow(dead_code)] +pub struct GeneralInfo { + pub name: String, + pub site: String, + // client + pub duration: Option +} + + +#[async_trait] +impl GenerateEmbed for GeneralInfo { + async fn generate_embed(&self) -> CreateEmbed { + CreateEmbed::new() + } +} + +#[async_trait] +impl GenerateEmbed for SpotifyInfo { + async fn generate_embed(&self) -> CreateEmbed { + CreateEmbed::new() + } +} + +#[async_trait] +impl GenerateEmbed for ApiStation { + async fn generate_embed(&self) -> CreateEmbed { + let embed= CreateEmbed::new() + .title("Current station:") + .thumbnail(&self.favicon) + .field("Name:", &self.name, true) + .field("Country:", &self.country, true) + .field("Language:", &self.language, true) + .field("Website:", &self.homepage, true) + .field("Stream:", &self.url, true) + .field("Tags:", &self.tags, false) + .color(hash_to_u32(&self.stationuuid)); + + embed + } +} + +// pub struct PlayingInfo { +// pub data: T, +// pub create_embed: Box CreateEmbed + Send + Sync> +// } + +#[allow(dead_code)] +pub enum PlayingInfoType { + SpotifyInfo(SpotifyInfo), + RadioInfo(ApiStation), + GeneralInfo(GeneralInfo) +} + +impl PlayingInfoType { + pub async fn generate_embed(&self) -> CreateEmbed { + match self { + PlayingInfoType::SpotifyInfo(v) => v.generate_embed().await, + PlayingInfoType::RadioInfo(v) => v.generate_embed().await, + PlayingInfoType::GeneralInfo(v) => v.generate_embed().await + } + } +} diff --git a/src/commands/voice/voice_utils.rs b/src/commands/voice/voice_utils.rs index d9e4a8c..45f490b 100644 --- a/src/commands/voice/voice_utils.rs +++ b/src/commands/voice/voice_utils.rs @@ -1,5 +1,4 @@ -use poise::{CreateReply}; -use serenity::all::{ChannelId, CreateActionRow, CreateButton, CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage, Embed, GuildId}; +use serenity::all::{ChannelId, GuildId}; use serenity::async_trait; use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler}; diff --git a/src/main.rs b/src/main.rs index a36e45a..417f31c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::future::Future; use std::pin::Pin; use std::sync::Arc; @@ -6,6 +7,7 @@ use std::error; use std::env; use serenity::async_trait; +use serenity::futures::lock::Mutex; use serenity::prelude::GatewayIntents; use serenity::client::Context; use serenity::model::gateway::Ready; @@ -19,6 +21,8 @@ use dotenv::dotenv; use songbird::SerenityInit; use tokio_cron_scheduler::{JobScheduler, Job}; +use radiobrowser::RadioBrowserAPI; + mod message_handler; use message_handler::handle; @@ -90,6 +94,7 @@ async fn main() -> anyhow::Result<()> { commands::radio::radio(), commands::general_player::play(), commands::player_common::disconnect(), + commands::player_common::playing() ], prefix_options: poise::PrefixFrameworkOptions { prefix: Some("/".into()), @@ -131,7 +136,8 @@ async fn main() -> anyhow::Result<()> { Ok(Data { http_client: HttpClient::new(), - radio_browser: RadioBrowserAPI::new().await.ok() + radio_browser: RadioBrowserAPI::new().await?, + playing_info: Mutex::new(HashMap::new()) }) }) }) diff --git a/src/types.rs b/src/types.rs index 068d8e4..00ef4f9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,23 +1,37 @@ -// pub struct Data {} - -use std::{ffi::OsString, path::PathBuf}; +use std::collections::HashMap; +use poise::CreateReply; use radiobrowser::RadioBrowserAPI; use reqwest::Client as HttpClient; +use serenity::{all::{futures::lock::Mutex, GuildId}, async_trait}; + +use crate::commands::voice_types::PlayingInfoType; // TODO: this should be probably expanded also to be used by multiple servers and commands // radio and spotify commands always create new HttpClient - pub struct Data { pub http_client: HttpClient, - pub radio_browser: Option, + pub radio_browser: RadioBrowserAPI, + pub playing_info: Mutex> } pub type Error = Box; // replace () with Data if you ever need to store some additional data pub type Context<'a> = poise::Context<'a, Data, Error>; -pub struct Track { - pub path: PathBuf, - pub name: OsString, +/// Trait to extend `Context` with additional methods. +#[async_trait] +pub trait ContextExt { + async fn reply_ephemeral(&self, content: &str) -> anyhow::Result<()>; +} + +#[async_trait] +impl ContextExt for Context<'_> { + async fn reply_ephemeral(&self, content: &str) -> anyhow::Result<()> { + self.send(CreateReply::default() + .ephemeral(true) + .content(content) + ).await?; + Ok(()) + } } diff --git a/src/utils.rs b/src/utils.rs index c23251b..fabda60 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,5 @@ +pub use utilities::*; + pub mod debug; pub mod utilities; pub mod gifs; -pub mod poise_context_extension; diff --git a/src/utils/poise_context_extension.rs b/src/utils/poise_context_extension.rs deleted file mode 100644 index 39a9475..0000000 --- a/src/utils/poise_context_extension.rs +++ /dev/null @@ -1,22 +0,0 @@ -use poise::CreateReply; -use serenity::async_trait; - -use crate::types::Context; - - -/// Trait to extend `Context` with additional methods. -#[async_trait] -pub trait ContextExt { - async fn reply_ephemeral(&self, content: &str) -> anyhow::Result<()>; -} - -#[async_trait] -impl ContextExt for Context<'_> { - async fn reply_ephemeral(&self, content: &str) -> anyhow::Result<()> { - self.send(CreateReply::default() - .ephemeral(true) - .content(content) - ).await?; - Ok(()) - } -} diff --git a/src/utils/utilities.rs b/src/utils/utilities.rs index c36912b..f24e427 100644 --- a/src/utils/utilities.rs +++ b/src/utils/utilities.rs @@ -1,7 +1,13 @@ -use std::{fs, io, path::Path, sync::Arc, vec}; +use std::{fs, hash::{DefaultHasher, Hash, Hasher}, io, path::Path, sync::Arc, vec}; use serenity::{all::{ChannelId, ChannelType, CreateMessage, GuildId, GuildRef, Message}, http::Http}; +use poise::CreateReply; +use serenity::async_trait; + +use crate::types::Context; + + pub async fn get_system_channel(guild_id: GuildId, http: &Http) -> anyhow::Result { use anyhow::Context; return http.get_guild(guild_id).await?.system_channel_id @@ -58,3 +64,10 @@ pub fn get_local_songs(partial: &str) -> io::Result> { Ok(result) } + +pub fn hash_to_u32(from: &T) -> u32 { + let mut hasher = DefaultHasher::new(); + from.hash(&mut hasher); + let hash_val = hasher.finish(); + (hash_val & 0xFFFFFF) as u32 +} From d331ba9b522d846d3f9c1365c199aa478d821f5a Mon Sep 17 00:00:00 2001 From: Ladislav Hano Date: Sun, 26 Jan 2025 22:47:06 +0100 Subject: [PATCH 19/19] chore: cleaned the code a bit --- src/commands/user_interactions/interaction.rs | 4 --- src/commands/voice/player_common.rs | 1 + src/commands/voice/radio/radio_player.rs | 29 ++++--------------- src/commands/voice/radio/radio_utils.rs | 1 - 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/commands/user_interactions/interaction.rs b/src/commands/user_interactions/interaction.rs index f495f3e..d53002e 100644 --- a/src/commands/user_interactions/interaction.rs +++ b/src/commands/user_interactions/interaction.rs @@ -34,7 +34,3 @@ pub(super) async fn send_with_embed(ctx: Context<'_>, query: &str, title: &str, Ok(()) } - -pub(super) async fn send(ctx: Context<'_>, msg: &str) -> anyhow::Result<()> { - Ok(()) -} \ No newline at end of file diff --git a/src/commands/voice/player_common.rs b/src/commands/voice/player_common.rs index 8eee740..ed92390 100644 --- a/src/commands/voice/player_common.rs +++ b/src/commands/voice/player_common.rs @@ -50,6 +50,7 @@ pub async fn disconnect( } } +#[allow(dead_code)] async fn autocomplete_song( _ctx: Context<'_>, partial: &str, diff --git a/src/commands/voice/radio/radio_player.rs b/src/commands/voice/radio/radio_player.rs index f669429..f33b54a 100644 --- a/src/commands/voice/radio/radio_player.rs +++ b/src/commands/voice/radio/radio_player.rs @@ -8,18 +8,15 @@ use songbird::input::HttpRequest; use super::super::connect; use super::link_or_string; -use super::parse_radio_autocomplete; use super::LinkString; -use crate::commands::voice_types::NumberOfEntries; -use crate::commands::voice_types::PlayingInfoType; -use crate::types::ContextExt; -use crate::types::{Context, Error}; -use crate::commands::voice::voice_utils::autocomplete_channel; - +use super::parse_radio_autocomplete; use super::radio_utils::paginate_search_stations; - use super::super::voice_utils::MAX_ENTRIES; +use crate::commands::voice_types::{NumberOfEntries, PlayingInfoType}; +use crate::types::{Context, Error, ContextExt}; +use crate::commands::voice::voice_utils::autocomplete_channel; + #[poise::command( slash_command, description_localized("en-US", "Plays music from URL source"), @@ -29,9 +26,6 @@ pub async fn radio(_ctx: Context<'_>) -> Result<(), Error> { Ok(()) } -// TODO: deduplicate you use a lot of the same code - -// TODO: autocomplete radio stream URLs #[poise::command( slash_command, description_localized("en-US", "Plays music from URL source") @@ -151,22 +145,9 @@ async fn autocomplete_radio( Err(_) => return vec!["".to_owned()] }; - // dbg!(&stations); - return stations - // return vec![]; } -// TODO -// autocomplete -// search with buttons and list in embed with direct links to stream -// embed showing currently playing song - -// use trace::trace; -// trace::init_depth_var!(); - -// TODO: autocomplete radio stream URLs -// #[trace] #[poise::command( slash_command, description_localized("en-US", "Search for a radio") diff --git a/src/commands/voice/radio/radio_utils.rs b/src/commands/voice/radio/radio_utils.rs index 9889928..c207dfc 100644 --- a/src/commands/voice/radio/radio_utils.rs +++ b/src/commands/voice/radio/radio_utils.rs @@ -118,7 +118,6 @@ pub enum LinkString { String } - pub fn link_or_string(haystack: &str) -> LinkString { let Ok(re) = Regex::new(r"^https?://([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$") else { panic!("Wrong regex expression!");