Initial commit
This commit is contained in:
commit
048351f22b
5 changed files with 1740 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
**/*.rs.bk
|
1392
Cargo.lock
generated
Normal file
1392
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
28
Cargo.toml
Normal file
28
Cargo.toml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[package]
|
||||||
|
name = "RMusicBot"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["hodasemi <michaelh.95@t-online.de>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
typemap = "~0.3"
|
||||||
|
|
||||||
|
[dependencies.serenity]
|
||||||
|
default-features = false
|
||||||
|
features = [
|
||||||
|
"builder",
|
||||||
|
"cache",
|
||||||
|
"client",
|
||||||
|
"framework",
|
||||||
|
"gateway",
|
||||||
|
"model",
|
||||||
|
"standard_framework",
|
||||||
|
"utils",
|
||||||
|
"voice"
|
||||||
|
]
|
||||||
|
version = "0.5"
|
||||||
|
|
||||||
|
[dependencies.framework]
|
||||||
|
git = "ssh://git@141.30.224.77:23/hodasemi/framework.git"
|
||||||
|
branch = "Animations"
|
||||||
|
default-features = false
|
||||||
|
features = [ "helper" ]
|
3
bot.conf
Normal file
3
bot.conf
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[Meta]
|
||||||
|
token = NDc4NTQ1NzY1MDc4MjY5OTU2.DlMQjQ.lqep6rd5w-uBOGst_cuEOQptt84
|
||||||
|
|
315
src/main.rs
Normal file
315
src/main.rs
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
#[macro_use] extern crate serenity;
|
||||||
|
|
||||||
|
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::{CACHE, Client, Context, EventHandler};
|
||||||
|
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::voice;
|
||||||
|
use serenity::Result as SerenityResult;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use typemap::Key;
|
||||||
|
|
||||||
|
use framework::prelude::*;
|
||||||
|
|
||||||
|
struct VoiceManager;
|
||||||
|
|
||||||
|
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"));
|
||||||
|
|
||||||
|
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::<VoiceManager>(Arc::clone(&client.voice_manager));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
.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::<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!(play(ctx, msg, args) {
|
||||||
|
let url = match args.single::<String>() {
|
||||||
|
Ok(url) => url,
|
||||||
|
Err(_) => {
|
||||||
|
check_msg(msg.channel_id.say("Must provide a URL to a video or audio"));
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if !url.starts_with("http") {
|
||||||
|
check_msg(msg.channel_id.say("Must provide a valid URL"));
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
let source = match voice::ytdl(&url) {
|
||||||
|
Ok(source) => source,
|
||||||
|
Err(why) => {
|
||||||
|
println!("Err starting source: {:?}", why);
|
||||||
|
|
||||||
|
check_msg(msg.channel_id.say("Error sourcing ffmpeg"));
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
handler.play(source);
|
||||||
|
|
||||||
|
check_msg(msg.channel_id.say("Playing song"));
|
||||||
|
} else {
|
||||||
|
check_msg(msg.channel_id.say("Not in a voice channel to play in"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue