RMusicBot/src/main.rs

286 lines
7.8 KiB
Rust
Raw Normal View History

2018-08-14 16:42:53 +00:00
#[macro_use]
extern crate serenity;
2018-08-13 16:45:49 +00:00
2018-08-14 16:42:53 +00:00
extern crate parking_lot;
extern crate serde_json;
2018-08-13 16:45:49 +00:00
extern crate typemap;
2018-08-14 17:08:13 +00:00
mod confighandler;
mod macros;
2018-08-13 16:45:49 +00:00
// 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;
2018-08-14 16:42:53 +00:00
use serenity::client::{Client, Context, EventHandler, CACHE};
2018-08-13 16:45:49 +00:00
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:
//
// <https://github.com/Amanieu/parking_lot#features>
use serenity::prelude::Mutex;
use serenity::Result as SerenityResult;
use std::sync::Arc;
use typemap::Key;
2018-08-14 17:08:13 +00:00
use confighandler::*;
2018-08-13 16:45:49 +00:00
2018-08-14 16:42:53 +00:00
mod player;
mod youtube;
use player::*;
/*
const fn empty_vec<T>() -> Vec<T> {
Vec::new()
}
*/
pub struct VoiceManager;
2018-08-13 16:45:49 +00:00
impl Key for VoiceManager {
type Value = Arc<Mutex<ClientVoiceManager>>;
}
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"));
2018-08-14 16:42:53 +00:00
2018-08-13 16:45:49 +00:00
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;
}
};
2018-08-14 16:42:53 +00:00
2018-08-13 16:45:49 +00:00
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::<VoiceManager>(Arc::clone(&client.voice_manager));
}
2018-08-14 16:42:53 +00:00
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));
2018-08-13 16:45:49 +00:00
}
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::<VoiceManager>().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::<VoiceManager>().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::<VoiceManager>().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::<VoiceManager>().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::<VoiceManager>().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::<VoiceManager>().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<Message>) {
if let Err(why) = result {
println!("Error sending message: {:?}", why);
}
}