#[macro_use] extern crate serenity; extern crate parking_lot; extern crate serde_json; extern crate typemap; #[macro_use] extern crate framework; // Import the client's bridge to the voice manager. Since voice is a standalone // feature, it's not as ergonomic to work with as it could be. The client // provides a clean bridged integration with voice. use serenity::client::bridge::voice::ClientVoiceManager; use serenity::client::{Client, Context, EventHandler, CACHE}; use serenity::framework::StandardFramework; use serenity::model::channel::Message; use serenity::model::gateway::Ready; use serenity::model::misc::Mentionable; // Import the `Context` from the client and `parking_lot`'s `Mutex`. // // `parking_lot` offers much more efficient implementations of `std::sync`'s // types. You can read more about it here: // // use serenity::prelude::Mutex; use serenity::Result as SerenityResult; use std::sync::Arc; use typemap::Key; use framework::prelude::*; mod player; mod youtube; use player::*; /* const fn empty_vec() -> Vec { Vec::new() } */ pub struct VoiceManager; impl Key for VoiceManager { type Value = Arc>; } struct Handler; impl EventHandler for Handler { fn ready(&self, _: Context, ready: Ready) { println!("{} is connected!", ready.user.name); } } fn main() { // read config file let config = check_result_return!(read_config("bot.conf")); let token = match config.get("Meta") { Some(info) => match info.get("token") { Some(token_pair) => { let mut token = String::new(); display_error!(token_pair.set_value(&mut token)); token } None => { println!("couldn't find token inside meta section"); return; } }, None => { println!("couldn't find Meta section in config file"); return; } }; let mut client = Client::new(&token, Handler).expect("Err creating client"); // Obtain a lock to the data owned by the client, and insert the client's // voice manager into it. This allows the voice manager to be accessible by // event handlers and framework commands. { let mut data = client.data.lock(); data.insert::(Arc::clone(&client.voice_manager)); } let media_data = Arc::new(MediaData::default()); client.with_framework( StandardFramework::new() .configure(|c| c.prefix("~").on_mention(true)) .cmd("deafen", deafen) .cmd("join", join) .cmd("leave", leave) .cmd("mute", mute) .cmd("play", Play::new(media_data.clone())) .cmd("pause", Pause::new(media_data.clone())) .cmd("ping", ping) .cmd("undeafen", undeafen) .cmd("unmute", unmute), ); let _ = client .start() .map_err(|why| println!("Client ended: {:?}", why)); } command!(deafen(ctx, msg) { let guild_id = match CACHE.read().guild_channel(msg.channel_id) { Some(channel) => channel.read().guild_id, None => { check_msg(msg.channel_id.say("Groups and DMs not supported")); return Ok(()); }, }; let mut manager_lock = ctx.data.lock().get::().cloned().unwrap(); let mut manager = manager_lock.lock(); let handler = match manager.get_mut(guild_id) { Some(handler) => handler, None => { check_msg(msg.reply("Not in a voice channel")); return Ok(()); }, }; if handler.self_deaf { check_msg(msg.channel_id.say("Already deafened")); } else { handler.deafen(true); check_msg(msg.channel_id.say("Deafened")); } }); command!(join(ctx, msg) { let guild = match msg.guild() { Some(guild) => guild, None => { check_msg(msg.channel_id.say("Groups and DMs not supported")); return Ok(()); } }; let guild_id = guild.read().id; let channel_id = guild .read() .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("Not in a voice channel")); return Ok(()); } }; let mut manager_lock = ctx.data.lock().get::().cloned().unwrap(); let mut manager = manager_lock.lock(); if manager.join(guild_id, connect_to).is_some() { check_msg(msg.channel_id.say(&format!("Joined {}", connect_to.mention()))); } else { check_msg(msg.channel_id.say("Error joining the channel")); } }); command!(leave(ctx, msg) { let guild_id = match CACHE.read().guild_channel(msg.channel_id) { Some(channel) => channel.read().guild_id, None => { check_msg(msg.channel_id.say("Groups and DMs not supported")); return Ok(()); }, }; let mut manager_lock = ctx.data.lock().get::().cloned().unwrap(); let mut manager = manager_lock.lock(); let has_handler = manager.get(guild_id).is_some(); if has_handler { manager.remove(guild_id); check_msg(msg.channel_id.say("Left voice channel")); } else { check_msg(msg.reply("Not in a voice channel")); } }); command!(mute(ctx, msg) { let guild_id = match CACHE.read().guild_channel(msg.channel_id) { Some(channel) => channel.read().guild_id, None => { check_msg(msg.channel_id.say("Groups and DMs not supported")); return Ok(()); }, }; let mut manager_lock = ctx.data.lock().get::().cloned().unwrap(); let mut manager = manager_lock.lock(); let handler = match manager.get_mut(guild_id) { Some(handler) => handler, None => { check_msg(msg.reply("Not in a voice channel")); return Ok(()); }, }; if handler.self_mute { check_msg(msg.channel_id.say("Already muted")); } else { handler.mute(true); check_msg(msg.channel_id.say("Now muted")); } }); command!(ping(_context, msg) { check_msg(msg.channel_id.say("Pong!")); }); command!(undeafen(ctx, msg) { let guild_id = match CACHE.read().guild_channel(msg.channel_id) { Some(channel) => channel.read().guild_id, None => { check_msg(msg.channel_id.say("Error finding channel info")); return Ok(()); }, }; let mut manager_lock = ctx.data.lock().get::().cloned().unwrap(); let mut manager = manager_lock.lock(); if let Some(handler) = manager.get_mut(guild_id) { handler.deafen(false); check_msg(msg.channel_id.say("Undeafened")); } else { check_msg(msg.channel_id.say("Not in a voice channel to undeafen in")); } }); command!(unmute(ctx, msg) { let guild_id = match CACHE.read().guild_channel(msg.channel_id) { Some(channel) => channel.read().guild_id, None => { check_msg(msg.channel_id.say("Error finding channel info")); return Ok(()); }, }; let mut manager_lock = ctx.data.lock().get::().cloned().unwrap(); let mut manager = manager_lock.lock(); if let Some(handler) = manager.get_mut(guild_id) { handler.mute(false); check_msg(msg.channel_id.say("Unmuted")); } else { check_msg(msg.channel_id.say("Not in a voice channel to undeafen in")); } }); /// Checks that a message successfully sent; if not, then logs why to stdout. fn check_msg(result: SerenityResult) { if let Err(why) = result { println!("Error sending message: {:?}", why); } }