extern crate discord;
use std::env;
use discord::{Discord, State};
use discord::model::Event;
pub fn main() {
let discord = Discord::from_bot_token(
&env::var("DISCORD_TOKEN").expect("Expected token"),
).expect("login failed");
let (mut connection, ready) = discord.connect().expect("connect failed");
println!("[Ready] {} is serving {} servers", ready.user.username, ready.servers.len());
let mut state = State::new(ready);
connection.sync_calls(&state.all_private_channels());
loop {
let event = match connection.recv_event() {
Ok(event) => event,
Err(err) => {
println!("[Warning] Receive error: {:?}", err);
if let discord::Error::WebSocket(..) = err {
let (new_connection, ready) = discord.connect().expect("connect failed");
connection = new_connection;
state = State::new(ready);
println!("[Ready] Reconnected successfully.");
}
if let discord::Error::Closed(..) = err {
break
}
continue
},
};
state.update(&event);
match event {
Event::MessageCreate(message) => {
use std::ascii::AsciiExt;
if message.author.id == state.user().id {
continue
}
let mut split = message.content.split(' ');
let first_word = split.next().unwrap_or("");
let argument = split.next().unwrap_or("");
if first_word.eq_ignore_ascii_case("!dj") {
let vchan = state.find_voice_user(message.author.id);
if argument.eq_ignore_ascii_case("stop") {
vchan.map(|(sid, _)| connection.voice(sid).stop());
} else if argument.eq_ignore_ascii_case("quit") {
vchan.map(|(sid, _)| connection.drop_voice(sid));
} else {
let output = if let Some((server_id, channel_id)) = vchan {
match discord::voice::open_ytdl_stream(argument) {
Ok(stream) => {
let voice = connection.voice(server_id);
voice.set_deaf(true);
voice.connect(channel_id);
voice.play(stream);
String::new()
},
Err(error) => format!("Error: {}", error),
}
} else {
"You must be in a voice channel to DJ".to_owned()
};
if !output.is_empty() {
warn(discord.send_message(message.channel_id, &output, "", false));
}
}
}
}
Event::VoiceStateUpdate(server_id, _) => {
if let Some(cur_channel) = connection.voice(server_id).current_channel() {
match server_id {
Some(server_id) => if let Some(srv) = state.servers().iter().find(|srv| srv.id == server_id) {
if srv.voice_states.iter().filter(|vs| vs.channel_id == Some(cur_channel)).count() <= 1 {
connection.voice(Some(server_id)).disconnect();
}
},
None => if let Some(call) = state.calls().get(&cur_channel) {
if call.voice_states.len() <= 1 {
connection.voice(server_id).disconnect();
}
}
}
}
}
_ => {}, }
}
}
fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
match result {
Ok(_) => {},
Err(err) => println!("[Warning] {:?}", err)
}
}