WIP: started to impl. songbird
This commit is contained in:
parent
d6a2cb5c8b
commit
d48de636f9
8 changed files with 1064 additions and 268 deletions
1174
Cargo.lock
generated
1174
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -13,5 +13,11 @@ tokio = { version = "1.36", features = ["macros", "rt-multi-thread"] }
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
confy = "0.6.0"
|
||||
lavalink-rs = "0.10"
|
||||
songbird = "0.4"
|
||||
chrono = "0.4"
|
||||
reqwest = "0.11"
|
||||
symphonia = "0.5"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
tracing-futures = "0.2.5"
|
||||
futures = "0.3.1"
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use chrono::Local;
|
||||
use serenity::all::{CommandInteraction, Context};
|
||||
use serenity::builder::{CreateCommand, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||
use serenity::model::application::ResolvedOption;
|
||||
|
||||
pub fn run(ctx: &Context, command: &CommandInteraction, _options: &[ResolvedOption]) -> CreateEmbed {
|
||||
pub async fn run(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
CreateEmbed::new()
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
|
||||
use chrono::Local;
|
||||
use serenity::all::{CommandInteraction, Context, ResolvedOption, ResolvedValue};
|
||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, Context, ResolvedOption, ResolvedValue};
|
||||
use serenity::builder::{CreateCommand, CreateCommandOption, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||
use serenity::model::application::CommandOptionType;
|
||||
|
||||
pub fn run(ctx: &Context, command: &CommandInteraction, options: &[ResolvedOption]) -> CreateEmbed {
|
||||
pub async fn run(ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
let options = &command.data.options;
|
||||
|
||||
let query = if let Some(ResolvedOption {
|
||||
value: ResolvedValue::String(query), ..
|
||||
}) = options.first()
|
||||
let query = if let Some(CommandDataOption {
|
||||
value: CommandDataOptionValue::String(query), ..
|
||||
}) = &options.first()
|
||||
{
|
||||
query
|
||||
} else {
|
||||
|
@ -21,6 +21,45 @@ pub fn run(ctx: &Context, command: &CommandInteraction, options: &[ResolvedOptio
|
|||
.footer(CreateEmbedFooter::new(format!(">{} | {}", current_time, username)))
|
||||
};
|
||||
|
||||
let guild_id = match &command.guild_id {
|
||||
Some(guild_id) => guild_id,
|
||||
None => {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("guildid not found")
|
||||
.description("Could not find guild id.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
}
|
||||
};
|
||||
|
||||
let (guild_id, channel_id) = {
|
||||
let guild = &ctx.cache.guild(guild_id).unwrap();
|
||||
// This may be unsafe, idk not sure yet
|
||||
let channel_id = guild
|
||||
.voice_states
|
||||
.get(&command.user.id)
|
||||
.and_then(|voice_state| voice_state.channel_id);
|
||||
(guild.id, channel_id)
|
||||
};
|
||||
|
||||
let connect_to = match channel_id {
|
||||
Some(channel) => channel,
|
||||
None => {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("You are not in a VC.")
|
||||
.description("Join one to start playing music.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
},
|
||||
};
|
||||
|
||||
let manager = &songbird::get(ctx)
|
||||
.await
|
||||
.expect("")
|
||||
.clone();
|
||||
|
||||
manager.join(guild_id, connect_to).await.expect("Cannot connect>...");
|
||||
|
||||
CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title(format!("Searching for {}", query))
|
||||
|
@ -35,4 +74,4 @@ pub fn register() -> CreateCommand {
|
|||
CreateCommandOption::new(CommandOptionType::String, "query", "Link or search term")
|
||||
.required(true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use chrono::Local;
|
||||
use serenity::all::{CommandInteraction, Context};
|
||||
use serenity::builder::{CreateCommand, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||
use serenity::model::application::ResolvedOption;
|
||||
|
||||
pub fn run(ctx: &Context, command: &CommandInteraction, _options: &[ResolvedOption]) -> CreateEmbed {
|
||||
pub async fn run(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
CreateEmbed::new()
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
use lavalink_rs::{client::LavalinkClient, model::events};
|
||||
use serenity::all::standard::macros::hook;
|
||||
|
||||
#[hook]
|
||||
pub async fn ready_event(client: LavalinkClient, _session_id: String, event: &events::Ready) {
|
||||
client.delete_all_player_contexts().await.unwrap();
|
||||
println!("Lavalink is ready for Freddy:: {:?}", event);
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
pub mod lavalink_event_handler;
|
82
src/main.rs
82
src/main.rs
|
@ -2,13 +2,9 @@ mod commands;
|
|||
mod util;
|
||||
mod handler;
|
||||
|
||||
use std::error::Error;
|
||||
|
||||
use lavalink_rs::client::LavalinkClient;
|
||||
use lavalink_rs::model::events::Events;
|
||||
use lavalink_rs::model::UserId;
|
||||
use lavalink_rs::node::NodeBuilder;
|
||||
use serenity::all::OnlineStatus;
|
||||
use std::thread::current;
|
||||
use chrono::Local;
|
||||
use serenity::all::{CommandInteraction, OnlineStatus};
|
||||
use serenity::async_trait;
|
||||
use serenity::builder::{CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, CreateInteractionResponse, CreateInteractionResponseMessage};
|
||||
use serenity::gateway::ActivityData;
|
||||
|
@ -17,27 +13,39 @@ use serenity::model::gateway::Ready;
|
|||
use serenity::prelude::*;
|
||||
use util::config;
|
||||
|
||||
use crate::handler::lavalink_event_handler;
|
||||
// This trait adds the `register_songbird` and `register_songbird_with` methods
|
||||
// to the client builder below, making it easy to install this voice client.
|
||||
// The voice client can be retrieved in any command using `songbird::get(ctx).await`.
|
||||
use songbird::SerenityInit;
|
||||
|
||||
// Event related imports to detect track creation failures.
|
||||
use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler, TrackEvent};
|
||||
|
||||
// To turn user URLs into playable audio, we'll use yt-dlp.
|
||||
use songbird::input::YoutubeDl;
|
||||
|
||||
// YtDl requests need an HTTP client to operate -- we'll create and store our own.
|
||||
use reqwest::Client as HttpClient;
|
||||
|
||||
// Import the `Context` to handle commands.
|
||||
use serenity::client::Context;
|
||||
|
||||
struct HttpKey;
|
||||
impl TypeMapKey for HttpKey {
|
||||
type Value = HttpClient;
|
||||
}
|
||||
|
||||
struct Handler;
|
||||
|
||||
pub struct Data {
|
||||
pub lavalink: LavalinkClient,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
||||
if let Interaction::Command(command) = interaction {
|
||||
let content = match command.data.name.as_str() {
|
||||
"info" => Some(commands::info::run(&ctx, &command, &command.data.options())),
|
||||
"play" => Some(commands::play::run(&ctx, &command, &command.data.options())),
|
||||
"stop" => Some(commands::stop::run(&ctx, &command, &command.data.options())),
|
||||
_ => Some(CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.description("Cannot find command")
|
||||
.footer(CreateEmbedFooter::new("Error during execution"))),
|
||||
"info" => Some(commands::info::run(&ctx, &command)),
|
||||
"play" => Some(commands::play::run(&ctx, &command)),
|
||||
"stop" => Some(commands::stop::run(&ctx, &command)),
|
||||
_ => Some(respond_with_error(&ctx, &command)),
|
||||
};
|
||||
|
||||
if let Some(embed) = content {
|
||||
|
@ -61,6 +69,17 @@ impl EventHandler for Handler {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn respond_with_error(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = &command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
|
||||
CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("Command not found")
|
||||
.description("Cannot find the executed command")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)))
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
println!(r"__________ __ .___
|
||||
|
@ -78,30 +97,13 @@ async fn main() {
|
|||
let status = OnlineStatus::DoNotDisturb;
|
||||
let activity = ActivityData::streaming("music", "https://twitch.tv/moonleaytv").unwrap();
|
||||
|
||||
let node_builder = NodeBuilder {
|
||||
hostname: config.lavalink_address,
|
||||
password: config.lavalink_password,
|
||||
user_id: UserId(config.user_id),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// let event = Events::default();
|
||||
let event = Events {
|
||||
ready: Some(lavalink_event_handler::ready_event),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Connect to lavalink
|
||||
let lavalink_client = LavalinkClient::new(event, vec![node_builder]);
|
||||
tokio::spawn(async move {
|
||||
lavalink_client.start().await;
|
||||
});
|
||||
|
||||
// Build the client
|
||||
let mut client = Client::builder(config.discord_token, GatewayIntents::empty())
|
||||
.event_handler(Handler)
|
||||
.status(status)
|
||||
.activity(activity)
|
||||
.register_songbird()
|
||||
.type_map_insert::<HttpKey>(HttpClient::new())
|
||||
.await
|
||||
.expect("Error creating client");
|
||||
|
||||
|
@ -109,7 +111,9 @@ async fn main() {
|
|||
//
|
||||
// Shards will automatically attempt to reconnect, and will perform exponential backoff until
|
||||
// it reconnects.
|
||||
if let Err(why) = client.start().await {
|
||||
if let Err(why) = client
|
||||
.start()
|
||||
.await {
|
||||
println!("Client error: {why:?}");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue