Created
February 18, 2021 18:11
-
-
Save reactormonk/e4e92973cab25318f3133b67dc0899c6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use serenity::prelude::Mutex; | |
use songbird::Call; | |
use std::sync::Arc; | |
use songbird::Event; | |
use songbird::ffmpeg; | |
use songbird::SerenityInit; | |
use serenity::async_trait; | |
use serenity::client::{Client, Context, EventHandler}; | |
use serenity::model::channel::Message; | |
use serenity::client::bridge::gateway::GatewayIntents; | |
use serenity::framework::standard::{ | |
StandardFramework, | |
CommandResult, | |
macros::{ | |
command, | |
group | |
} | |
}; | |
use serenity::Result as SerenityResult; | |
use songbird::{ | |
EventContext, | |
EventHandler as VoiceEventHandler, | |
TrackEvent, | |
}; | |
use std::env; | |
#[group] | |
#[commands(ping)] | |
struct General; | |
struct Handler; | |
#[async_trait] | |
impl EventHandler for Handler {} | |
#[tokio::main] | |
async fn main() { | |
let framework = StandardFramework::new() | |
.configure(|c| c.prefix("~")) // set the bot's prefix to "~" | |
.group(&GENERAL_GROUP); | |
// Login with a bot token from the environment | |
let token = env::var("DISCORD_TOKEN").expect("token"); | |
let mut client = Client::builder(token) | |
.event_handler(Handler) | |
.framework(framework) | |
.intents(GatewayIntents::non_privileged() | GatewayIntents::GUILDS | GatewayIntents::GUILD_VOICE_STATES) | |
.register_songbird() | |
.await | |
.expect("Error creating client"); | |
// start listening for events by starting a single shard | |
if let Err(why) = client.start().await { | |
println!("An error occurred while running the client: {:?}", why); | |
} | |
} | |
#[command] | |
async fn ping(ctx: &Context, msg: &Message) -> CommandResult { | |
msg.reply(ctx, "Pong!").await?; | |
let guild = msg.guild(&ctx.cache).await; | |
match guild { | |
None => {}, | |
Some(g) => { | |
let channel_id = g | |
.voice_states.get(&msg.author.id) | |
.and_then(|voice_state| voice_state.channel_id); | |
let connect_to = match channel_id { | |
Some(channel) => channel, | |
None => { | |
check_msg(msg.reply(ctx, "Not in a voice channel").await); | |
return Ok(()); | |
} | |
}; | |
let manager = songbird::serenity::get(ctx).await | |
.expect("Songbird Voice client placed in at initialisation.").clone(); | |
let (call, _err) = manager.join(g.id, connect_to).await; | |
if let Some(handler_lock) = manager.get(g.id) { | |
let mut handler = handler_lock.lock().await; | |
let source = match ffmpeg("Rick Astley - Never Gonna Give You Up (Video)-dQw4w9WgXcQ.opus").await { | |
Ok(source) => source, | |
Err(why) => { | |
println!("Err starting source: {:?}", why); | |
check_msg(msg.channel_id.say(&ctx.http, "Error sourcing ffmpeg").await); | |
return Ok(()); | |
}, | |
}; | |
let song = handler.play_only_source(source); | |
song.set_volume(0.3)?; | |
// This shows how to fire an event once an audio track completes, | |
// either due to hitting the end of the bytestream or stopped by user code. | |
let _ = song.add_event( | |
Event::Track(TrackEvent::End), | |
SongEndNotifier { | |
call, | |
}, | |
); | |
} | |
} | |
} | |
Ok(()) | |
} | |
fn check_msg(result: SerenityResult<Message>) { | |
if let Err(why) = result { | |
println!("Error sending message: {:?}", why); | |
} | |
} | |
struct SongEndNotifier { | |
call: Arc<Mutex<Call>>, | |
} | |
#[async_trait] | |
impl VoiceEventHandler for SongEndNotifier { | |
async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> { | |
if let Err(e) = (*self.call).lock().await.leave().await { | |
println!("Error sending message: {:?}", e); | |
} | |
None | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment