add explicit join/leave

This commit is contained in:
Gabriel Fontes
2022-02-01 23:38:10 -03:00
parent de564d2a2b
commit d48c1c2a9f
3 changed files with 83 additions and 47 deletions

2
Cargo.lock generated
View File

@@ -486,7 +486,7 @@ dependencies = [
[[package]] [[package]]
name = "disconic" name = "disconic"
version = "0.2.0" version = "0.2.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"dotenv", "dotenv",

View File

@@ -1,7 +1,7 @@
[package] [package]
name = "disconic" name = "disconic"
description = "Discord bot for interacting with subsonic music libraries" description = "Discord bot for interacting with subsonic music libraries"
version = "0.2.0" version = "0.2.1"
authors = [ "Gabriel Fontes <eu@misterio.me>" ] authors = [ "Gabriel Fontes <eu@misterio.me>" ]
edition = "2018" edition = "2018"
homepage = "https://misterio.me" homepage = "https://misterio.me"

View File

@@ -7,21 +7,26 @@ use serenity::{
Args, CommandResult, Args, CommandResult,
}, },
model::channel::Message, model::channel::Message,
prelude::Mutex,
utils::MessageBuilder, utils::MessageBuilder,
}; };
use songbird::input::{Input, Metadata}; use songbird::{
use std::sync::Arc; input::{Input, Metadata},
Call,
};
use sunk::{ use sunk::{
search::{self, SearchPage}, search::{self, SearchPage},
song::Song, song::Song,
Streamable, Streamable,
}; };
use std::sync::Arc;
use crate::MusicClient; use crate::MusicClient;
#[group] #[group]
#[commands( #[commands(
song, random, skip, stop, pause, resume, queue, nowplaying, remove, album song, random, skip, stop, pause, resume, queue, nowplaying, remove, album, join, leave
)] )]
pub struct General; pub struct General;
@@ -38,6 +43,37 @@ pub async fn after_hook(ctx: &Context, msg: &Message, cmd_name: &str, error: Com
} }
} }
#[command]
async fn leave(ctx: &Context, msg: &Message) -> CommandResult {
let guild = msg.guild(&ctx.cache).await.unwrap();
let guild_id = guild.id;
let manager = songbird::get(ctx)
.await
.ok_or_else(|| anyhow!("Couldn't start manager"))?;
manager.remove(guild_id).await?;
Ok(())
}
#[command]
async fn join(ctx: &Context, msg: &Message) -> CommandResult {
let guild = msg.guild(&ctx.cache).await.unwrap();
let guild_id = guild.id;
let channel = guild
.voice_states
.get(&msg.author.id)
.and_then(|voice_state| voice_state.channel_id)
.ok_or_else(|| anyhow!("You must be in a voice channel to use this command"))?;
let manager = songbird::get(ctx)
.await
.ok_or_else(|| anyhow!("Couldn't start manager"))?;
let _handler = manager.join(guild_id, channel).await;
Ok(())
}
#[command] #[command]
#[aliases(s, p, play)] #[aliases(s, p, play)]
/// Play a named song /// Play a named song
@@ -58,7 +94,7 @@ async fn song(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let song = result let song = result
.first() .first()
.ok_or_else(|| anyhow!("No song matching search found"))?; .ok_or_else(|| anyhow!("No song matching search found"))?;
queue_song(ctx, msg, &song, &music_client).await?; queue_song(ctx, msg, song, music_client).await?;
Ok(()) Ok(())
} }
@@ -85,7 +121,7 @@ async fn album(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
.ok_or_else(|| anyhow!("No albums matching search found"))?; .ok_or_else(|| anyhow!("No albums matching search found"))?;
for song in album.songs(music_client).await? { for song in album.songs(music_client).await? {
queue_song(ctx, msg, &song, &music_client).await?; queue_song(ctx, msg, &song, music_client).await?;
} }
Ok(()) Ok(())
@@ -100,12 +136,12 @@ async fn random(ctx: &Context, msg: &Message) -> CommandResult {
.get::<MusicClient>() .get::<MusicClient>()
.expect("Couldn't retrieve music client"); .expect("Couldn't retrieve music client");
let result = Song::random(&music_client, 1).await?; let result = Song::random(music_client, 1).await?;
let song = result let song = result
.first() .first()
.ok_or_else(|| anyhow!("No song matching search found"))?; .ok_or_else(|| anyhow!("No song matching search found"))?;
queue_song(ctx, msg, &song, &music_client).await?; queue_song(ctx, msg, song, music_client).await?;
Ok(()) Ok(())
} }
@@ -113,7 +149,7 @@ async fn random(ctx: &Context, msg: &Message) -> CommandResult {
#[command] #[command]
/// Skip current song /// Skip current song
async fn skip(ctx: &Context, msg: &Message) -> CommandResult { async fn skip(ctx: &Context, msg: &Message) -> CommandResult {
let call = join_channel(&ctx, &msg).await?; let call = get_handler(ctx, msg).await?;
let handler = call.lock().await; let handler = call.lock().await;
let queue = handler.queue(); let queue = handler.queue();
@@ -127,7 +163,7 @@ async fn skip(ctx: &Context, msg: &Message) -> CommandResult {
#[command] #[command]
/// Clear queue and stop playing /// Clear queue and stop playing
async fn stop(ctx: &Context, msg: &Message) -> CommandResult { async fn stop(ctx: &Context, msg: &Message) -> CommandResult {
let call = join_channel(&ctx, &msg).await?; let call = get_handler(ctx, msg).await?;
let handler = call.lock().await; let handler = call.lock().await;
let queue = handler.queue(); let queue = handler.queue();
@@ -141,7 +177,7 @@ async fn stop(ctx: &Context, msg: &Message) -> CommandResult {
#[command] #[command]
/// Pause playing current song /// Pause playing current song
async fn pause(ctx: &Context, msg: &Message) -> CommandResult { async fn pause(ctx: &Context, msg: &Message) -> CommandResult {
let call = join_channel(&ctx, &msg).await?; let call = get_handler(ctx, msg).await?;
let handler = call.lock().await; let handler = call.lock().await;
let queue = handler.queue(); let queue = handler.queue();
@@ -159,7 +195,7 @@ async fn pause(ctx: &Context, msg: &Message) -> CommandResult {
#[aliases(resume)] #[aliases(resume)]
/// Resume playing current song /// Resume playing current song
async fn resume(ctx: &Context, msg: &Message) -> CommandResult { async fn resume(ctx: &Context, msg: &Message) -> CommandResult {
let call = join_channel(&ctx, &msg).await?; let call = get_handler(ctx, msg).await?;
let handler = call.lock().await; let handler = call.lock().await;
let queue = handler.queue(); let queue = handler.queue();
@@ -174,7 +210,7 @@ async fn resume(ctx: &Context, msg: &Message) -> CommandResult {
#[aliases(nowplaying, now, np, playing)] #[aliases(nowplaying, now, np, playing)]
/// Show currently playing song /// Show currently playing song
async fn nowplaying(ctx: &Context, msg: &Message) -> CommandResult { async fn nowplaying(ctx: &Context, msg: &Message) -> CommandResult {
let call = join_channel(&ctx, &msg).await?; let call = get_handler(ctx, msg).await?;
let handler = call.lock().await; let handler = call.lock().await;
let queue = handler.queue(); let queue = handler.queue();
@@ -192,7 +228,7 @@ async fn nowplaying(ctx: &Context, msg: &Message) -> CommandResult {
#[aliases(q)] #[aliases(q)]
/// Show song queue /// Show song queue
async fn queue(ctx: &Context, msg: &Message) -> CommandResult { async fn queue(ctx: &Context, msg: &Message) -> CommandResult {
let call = join_channel(&ctx, &msg).await?; let call = get_handler(ctx, msg).await?;
let handler = call.lock().await; let handler = call.lock().await;
let current_queue = handler.queue().current_queue(); let current_queue = handler.queue().current_queue();
@@ -203,7 +239,7 @@ async fn queue(ctx: &Context, msg: &Message) -> CommandResult {
let mut text = String::new(); let mut text = String::new();
for (i, track) in current_queue.iter().enumerate() { for (i, track) in current_queue.iter().enumerate() {
text.push_str(&song_message(Some(i), track.metadata())); text.push_str(&song_message(Some(i), track.metadata()));
text.push_str("\n"); text.push('\n');
} }
text text
}; };
@@ -215,7 +251,7 @@ async fn queue(ctx: &Context, msg: &Message) -> CommandResult {
#[command] #[command]
/// Remove song from queue, given id /// Remove song from queue, given id
async fn remove(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { async fn remove(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let call = join_channel(&ctx, &msg).await?; let call = get_handler(ctx, msg).await?;
let handler = call.lock().await; let handler = call.lock().await;
let index = args.single()?; let index = args.single()?;
@@ -253,7 +289,7 @@ fn song_message(index: Option<usize>, metadata: &Metadata) -> String {
"{} - {} ({})", "{} - {} ({})",
metadata.artist.to_owned().unwrap_or_default(), metadata.artist.to_owned().unwrap_or_default(),
metadata.track.to_owned().unwrap_or_default(), metadata.track.to_owned().unwrap_or_default(),
duration.to_owned().unwrap_or_default(), duration.unwrap_or_default(),
); );
MessageBuilder::new() MessageBuilder::new()
@@ -268,10 +304,19 @@ async fn queue_song(
song: &Song, song: &Song,
client: &sunk::Client, client: &sunk::Client,
) -> Result<()> { ) -> Result<()> {
let input = load_song(song, client).await?; let guild = msg
println!("{:?}", input); .guild(&ctx.cache)
let call = join_channel(&ctx, &msg).await?; .await
.ok_or_else(|| anyhow!("Couldn't get guild id"))?;
let manager = songbird::get(ctx)
.await
.ok_or_else(|| anyhow!("Couldn't start manager"))?;
let call = manager
.get(guild.id)
.ok_or_else(|| anyhow!("Not currently in a channel"))?;
let mut handler = call.lock().await; let mut handler = call.lock().await;
let input = load_song(song, client).await?;
handler.enqueue_source(input); handler.enqueue_source(input);
let song_info = format!( let song_info = format!(
@@ -295,33 +340,24 @@ async fn queue_song(
Ok(()) Ok(())
} }
async fn join_channel( async fn get_handler(ctx: &Context, msg: &Message) -> Result<Arc<Mutex<Call>>> {
ctx: &Context, let guild = msg
msg: &Message, .guild(&ctx.cache)
) -> Result<Arc<serenity::prelude::Mutex<songbird::Call>>> { .await
let guild = msg.guild(&ctx.cache).await.unwrap(); .ok_or_else(|| anyhow!("Couldn't get guild id"))?;
let guild_id = guild.id; let manager = songbird::get(ctx)
.await
let caller_channel = guild .ok_or_else(|| anyhow!("Couldn't start manager"))?;
.voice_states Ok(manager
.get(&msg.author.id) .get(guild.id)
.and_then(|voice_state| voice_state.channel_id); .ok_or_else(|| anyhow!("Not currently in a channel"))?)
let connect_to = match caller_channel {
Some(channel) => channel,
None => {
return Err(anyhow!(
"You must be in a voice channel to use this command"
));
}
};
let manager = songbird::get(ctx).await.unwrap();
let handler = manager.join(guild_id, connect_to).await.0;
Ok(handler)
} }
async fn load_song(song: &Song, client: &sunk::Client) -> Result<Input> { async fn load_song(song: &Song, client: &sunk::Client) -> Result<Input> {
let url = song.stream_url(&client)?; let url = song.stream_url(client)?;
Ok(songbird::ffmpeg(url).await?) let mut input = songbird::ffmpeg(&url).await?;
input.metadata.track = Some(song.title.clone());
input.metadata.artist = song.artist.clone();
input.metadata.source_url = Some(url);
Ok(input)
} }