Start implementing serenity 0.6
This commit is contained in:
parent
da1c9a5d2e
commit
4276428a8b
14 changed files with 557 additions and 628 deletions
32
src/main.rs
32
src/main.rs
|
@ -11,8 +11,24 @@ mod confighandler;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod player;
|
mod player;
|
||||||
|
|
||||||
use serenity::client::Client;
|
use serenity::{
|
||||||
use serenity::framework::StandardFramework;
|
framework::standard::{
|
||||||
|
help_commands,
|
||||||
|
macros::{check, command, group, help},
|
||||||
|
Args, CheckResult, CommandGroup, CommandOptions, CommandResult, DispatchError, HelpOptions,
|
||||||
|
StandardFramework,
|
||||||
|
},
|
||||||
|
model::{
|
||||||
|
channel::{Channel, Message},
|
||||||
|
gateway::Ready,
|
||||||
|
id::UserId,
|
||||||
|
},
|
||||||
|
utils::{content_safe, ContentSafeOptions},
|
||||||
|
};
|
||||||
|
|
||||||
|
// This imports `typemap`'s `Key` as `TypeMapKey`.
|
||||||
|
use serenity::prelude::*;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use confighandler::*;
|
use confighandler::*;
|
||||||
|
@ -32,6 +48,12 @@ impl Default for Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group!({
|
||||||
|
name: "general",
|
||||||
|
options: {},
|
||||||
|
commands: [ip]
|
||||||
|
});
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// read config file
|
// read config file
|
||||||
let config_file = check_result_return!(read_config("bot.conf"));
|
let config_file = check_result_return!(read_config("bot.conf"));
|
||||||
|
@ -71,13 +93,15 @@ fn main() {
|
||||||
// voice manager into it. This allows the voice manager to be accessible by
|
// voice manager into it. This allows the voice manager to be accessible by
|
||||||
// event handlers and framework commands.
|
// event handlers and framework commands.
|
||||||
{
|
{
|
||||||
let mut data = client.data.lock();
|
let mut data = client.data.write();
|
||||||
data.insert::<VoiceManager>(Arc::clone(&client.voice_manager));
|
data.insert::<VoiceManager>(Arc::clone(&client.voice_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
let media_data =
|
let media_data =
|
||||||
Arc::new(MediaData::new("Penis1").expect("failed to create media data handle"));
|
Arc::new(MediaData::new("Penis1").expect("failed to create media data handle"));
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
client.with_framework(
|
client.with_framework(
|
||||||
StandardFramework::new()
|
StandardFramework::new()
|
||||||
.configure(|c| c.prefix(&config.prefix).on_mention(true))
|
.configure(|c| c.prefix(&config.prefix).on_mention(true))
|
||||||
|
@ -109,4 +133,6 @@ fn main() {
|
||||||
let _ = client
|
let _ = client
|
||||||
.start()
|
.start()
|
||||||
.map_err(|why| println!("Client ended: {:?}", why));
|
.map_err(|why| println!("Client ended: {:?}", why));
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
use serenity;
|
|
||||||
|
|
||||||
pub struct Help {
|
|
||||||
prefix: String,
|
|
||||||
commands: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Help {
|
|
||||||
pub fn new(prefix: &String, commands: Vec<String>) -> Help {
|
|
||||||
Help {
|
|
||||||
prefix: prefix.clone(),
|
|
||||||
commands: commands,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl serenity::framework::standard::Command for Help {
|
|
||||||
#[allow(unreachable_code, unused_mut)]
|
|
||||||
fn execute(
|
|
||||||
&self,
|
|
||||||
_: &mut serenity::client::Context,
|
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
_: serenity::framework::standard::Args,
|
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
let mut output = String::new();
|
|
||||||
|
|
||||||
output += "Available commands:\n";
|
|
||||||
|
|
||||||
for command in &self.commands {
|
|
||||||
output += &format!("\t{}{}\n", self.prefix, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
print_error!(msg.channel_id.say(output));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +1,35 @@
|
||||||
use serenity;
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This imports `typemap`'s `Key` as `TypeMapKey`.
|
||||||
|
use serenity::prelude::*;
|
||||||
|
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
|
|
||||||
pub struct IP {}
|
#[command]
|
||||||
|
fn ip(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
let args = ["ifconfig.me"];
|
||||||
|
|
||||||
impl IP {
|
let out = match Command::new("curl")
|
||||||
pub fn new() -> IP {
|
.args(&args)
|
||||||
IP {}
|
.stdin(Stdio::null())
|
||||||
}
|
.output()
|
||||||
}
|
{
|
||||||
|
Ok(out) => out,
|
||||||
impl serenity::framework::standard::Command for IP {
|
Err(_) => return Ok(()),
|
||||||
#[allow(unreachable_code, unused_mut)]
|
};
|
||||||
fn execute(
|
|
||||||
&self,
|
if !out.status.success() {
|
||||||
_: &mut serenity::client::Context,
|
return Ok(());
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
_: serenity::framework::standard::Args,
|
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
let args = ["ifconfig.me"];
|
|
||||||
|
|
||||||
let out = match Command::new("curl")
|
|
||||||
.args(&args)
|
|
||||||
.stdin(Stdio::null())
|
|
||||||
.output()
|
|
||||||
{
|
|
||||||
Ok(out) => out,
|
|
||||||
Err(_) => return Ok(()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if !out.status.success() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
match from_utf8(out.stdout.as_slice()) {
|
|
||||||
Ok(string) => print_error!(msg.author.direct_message(|m| m.content(string))),
|
|
||||||
Err(_) => print_error!(msg.channel_id.say("error getting IP string")),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match from_utf8(out.stdout.as_slice()) {
|
||||||
|
Ok(string) => print_error!(msg.author.direct_message(|m| m.content(string))),
|
||||||
|
Err(_) => print_error!(msg.channel_id.say("error getting IP string")),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,52 @@
|
||||||
use serenity;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::super::prelude::*;
|
use super::super::prelude::*;
|
||||||
|
|
||||||
pub struct List {
|
use serenity::prelude::*;
|
||||||
media: Arc<MediaData>,
|
use serenity::{
|
||||||
}
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
};
|
||||||
|
|
||||||
impl List {
|
#[command]
|
||||||
pub fn new(media_data: Arc<MediaData>) -> List {
|
fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
|
||||||
List { media: media_data }
|
if !channel_contains_author(ctx, msg) {
|
||||||
|
println!(
|
||||||
|
"user {} is not in the same voice channel as the bot",
|
||||||
|
msg.author.name
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl serenity::framework::standard::Command for List {
|
let mut output = String::new();
|
||||||
#[allow(unreachable_code, unused_mut)]
|
|
||||||
fn execute(
|
let data = ctx.data.read();
|
||||||
&self,
|
let media = match data.get::<MediaData>() {
|
||||||
ctx: &mut serenity::client::Context,
|
Ok(media) => media,
|
||||||
msg: &serenity::model::channel::Message,
|
Err(_) => {
|
||||||
_: serenity::framework::standard::Args,
|
msg.channel_id.say("could not find media data");
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
if !channel_contains_author(ctx, msg) {
|
|
||||||
println!(
|
|
||||||
"user {} is not in the same voice channel as the bot",
|
|
||||||
msg.author.name
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut output = String::new();
|
let playlist = media.playlist();
|
||||||
|
|
||||||
{
|
output += &format!(
|
||||||
let playlist_mutex = self.media.playlist_mut()?;
|
"{} {} queued\n",
|
||||||
let playlist = playlist_mutex.borrow();
|
playlist.len(),
|
||||||
|
if playlist.len() == 1 { "song" } else { "songs" }
|
||||||
|
);
|
||||||
|
|
||||||
output += &format!(
|
let max_output = 5;
|
||||||
"{} {} queued\n",
|
|
||||||
playlist.len(),
|
|
||||||
if playlist.len() == 1 { "song" } else { "songs" }
|
|
||||||
);
|
|
||||||
|
|
||||||
let max_output = 5;
|
for (i, song) in playlist.iter().enumerate() {
|
||||||
|
if i < max_output {
|
||||||
for (i, song) in playlist.iter().enumerate() {
|
output += &format!("\t{}.\t{}\n", i + 1, song.name.clone());
|
||||||
if i < max_output {
|
} else {
|
||||||
output += &format!("\t{}.\t{}\n", i + 1, song.name.clone());
|
output += &format!("\t... and {} more", playlist.len() - max_output);
|
||||||
} else {
|
break;
|
||||||
output += &format!("\t... and {} more", playlist.len() - max_output);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_error!(msg.channel_id.say(output));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_error!(msg.channel_id.say(output));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
pub mod help;
|
|
||||||
pub mod ip;
|
pub mod ip;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod pause;
|
pub mod pause;
|
||||||
|
|
|
@ -1,45 +1,33 @@
|
||||||
use serenity;
|
use serenity;
|
||||||
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::super::prelude::*;
|
use super::super::prelude::*;
|
||||||
|
|
||||||
pub struct Pause {
|
use serenity::prelude::*;
|
||||||
media: Arc<MediaData>,
|
use serenity::{
|
||||||
}
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
};
|
||||||
|
|
||||||
impl Pause {
|
#[command]
|
||||||
pub fn new(media_data: Arc<MediaData>) -> Pause {
|
fn pause(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
|
||||||
Pause { media: media_data }
|
if !channel_contains_author(ctx, msg) {
|
||||||
|
println!(
|
||||||
|
"user {} is not in the same voice channel as the bot",
|
||||||
|
msg.author.name
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl serenity::framework::standard::Command for Pause {
|
let data = ctx.data.read();
|
||||||
#[allow(unreachable_code, unused_mut)]
|
let media = match data.get::<MediaData>() {
|
||||||
fn execute(
|
Ok(media) => media,
|
||||||
&self,
|
Err(_) => {
|
||||||
ctx: &mut serenity::client::Context,
|
msg.channel_id.say("could not find media data");
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
_: serenity::framework::standard::Args,
|
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
if !channel_contains_author(ctx, msg) {
|
|
||||||
println!(
|
|
||||||
"user {} is not in the same voice channel as the bot",
|
|
||||||
msg.author.name
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let song_lock = self.media.song_mut()?;
|
media.song().pause();
|
||||||
|
|
||||||
if let Some(song) = song_lock.borrow_mut().deref_mut() {
|
Ok(())
|
||||||
let song_clone = song.clone();
|
|
||||||
let mut audio_lock = song_clone.lock();
|
|
||||||
|
|
||||||
audio_lock.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use parking_lot;
|
use parking_lot;
|
||||||
|
|
||||||
use serenity;
|
|
||||||
use serenity::voice::LockedAudio;
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::{Arc, MutexGuard};
|
use std::sync::{Arc, MutexGuard};
|
||||||
|
@ -13,301 +10,300 @@ use super::super::prelude::*;
|
||||||
|
|
||||||
use rusqlite::params;
|
use rusqlite::params;
|
||||||
|
|
||||||
pub struct Play {
|
use serenity::prelude::*;
|
||||||
media: Arc<MediaData>,
|
use serenity::voice::LockedAudio;
|
||||||
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
fn play(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
if !channel_contains_author(ctx, msg) {
|
||||||
|
println!(
|
||||||
|
"user {} is not in the same voice channel as the bot",
|
||||||
|
msg.author.name
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = ctx.data.read();
|
||||||
|
let mut media = match data.get_mut::<MediaData>() {
|
||||||
|
Ok(media) => media,
|
||||||
|
Err(_) => {
|
||||||
|
msg.channel_id.say("could not find media data");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if args.len() == 0 {
|
||||||
|
if !Self::check_for_continue(self.media.song_mut()?) {
|
||||||
|
print_error!(msg.channel_id.say("Must provide a URL to a video or audio"));
|
||||||
|
}
|
||||||
|
} else if args.len() == 1 {
|
||||||
|
let arg = match args.single::<String>() {
|
||||||
|
Ok(arg) => arg,
|
||||||
|
// can't happen, since we tested for length == 1
|
||||||
|
Err(_) => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if arg == "--local" {
|
||||||
|
self.handle_local_request(ctx, msg)?;
|
||||||
|
} else if arg.starts_with("http") {
|
||||||
|
self.handle_http_request(ctx, msg, &arg)?;
|
||||||
|
} else {
|
||||||
|
self.handle_song_request(ctx, msg, &arg)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_error!(msg.channel_id.say("Unsupported argument list"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Play {
|
fn check_for_continue(song_lock: MutexGuard<RefCell<Option<LockedAudio>>>) -> bool {
|
||||||
pub fn new(media_data: Arc<MediaData>) -> Play {
|
match song_lock.borrow_mut().deref_mut() {
|
||||||
Play { media: media_data }
|
Some(song) => {
|
||||||
|
let song_clone = song.clone();
|
||||||
|
let mut audio_lock = song_clone.lock();
|
||||||
|
|
||||||
|
audio_lock.play();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_join_channel(
|
||||||
|
manager_lock: &Arc<parking_lot::Mutex<serenity::client::bridge::voice::ClientVoiceManager>>,
|
||||||
|
msg: &serenity::model::channel::Message,
|
||||||
|
) {
|
||||||
|
let guild = match msg.guild() {
|
||||||
|
Some(guild) => guild,
|
||||||
|
None => {
|
||||||
|
display_error!(msg.channel_id.say("Groups and DMs not supported"));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
display_error!(msg.reply("Not in a voice channel"));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut manager = manager_lock.lock();
|
||||||
|
|
||||||
|
manager.join(guild_id, connect_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append_songs(
|
||||||
|
media: &mut MediaData,
|
||||||
|
ctx: &mut serenity::client::Context,
|
||||||
|
msg: &serenity::model::channel::Message,
|
||||||
|
mut source: Vec<Song>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
{
|
||||||
|
let playlist_mutex = self.media.playlist_mut()?;
|
||||||
|
playlist_mutex.borrow_mut().append(&mut source);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_continue(song_lock: MutexGuard<RefCell<Option<LockedAudio>>>) -> bool {
|
if let Some(manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() {
|
||||||
match song_lock.borrow_mut().deref_mut() {
|
Self::check_join_channel(&manager_lock, msg);
|
||||||
Some(song) => {
|
|
||||||
let song_clone = song.clone();
|
|
||||||
let mut audio_lock = song_clone.lock();
|
|
||||||
|
|
||||||
audio_lock.play();
|
let check_finished = {
|
||||||
true
|
let media_clone = self.media.clone();
|
||||||
}
|
let channel_id = msg.channel_id;
|
||||||
None => false,
|
let manager_lock_clone = manager_lock.clone();
|
||||||
}
|
|
||||||
|
Arc::new(move || {
|
||||||
|
let callback = match media_clone.next_callback.borrow().deref() {
|
||||||
|
Some(callback) => callback.clone(),
|
||||||
|
None => {
|
||||||
|
println!("next_callback not set!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MediaData::next_song(&media_clone, channel_id, &manager_lock_clone, callback);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
MediaData::start_playing(&self.media, check_finished, msg.channel_id, &manager_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_join_channel(
|
Ok(())
|
||||||
manager_lock: &Arc<parking_lot::Mutex<serenity::client::bridge::voice::ClientVoiceManager>>,
|
}
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
) {
|
|
||||||
let guild = match msg.guild() {
|
|
||||||
Some(guild) => guild,
|
|
||||||
None => {
|
|
||||||
display_error!(msg.channel_id.say("Groups and DMs not supported"));
|
|
||||||
|
|
||||||
return;
|
fn handle_http_request(
|
||||||
}
|
media: &mut MediaData,
|
||||||
|
ctx: &mut serenity::client::Context,
|
||||||
|
msg: &serenity::model::channel::Message,
|
||||||
|
url: &String,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let sql = self.media.lock_db()?;
|
||||||
|
|
||||||
|
let mut stmt = match sql.prepare("SELECT name FROM Vulva3 WHERE link = ?") {
|
||||||
|
Ok(statement) => statement,
|
||||||
|
Err(_) => return Err("failed preparing data base access".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rows = match stmt.query_map(&[url], |row| row.get(0) as rusqlite::Result<String>) {
|
||||||
|
Ok(rows) => rows,
|
||||||
|
Err(_) => return Err("failed querying rows".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut names = Vec::new();
|
||||||
|
for name_result in rows {
|
||||||
|
let name = match name_result {
|
||||||
|
Ok(name) => name,
|
||||||
|
Err(_) => return Err("failed getting name from row".to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let guild_id = guild.read().id;
|
names.push(name);
|
||||||
|
|
||||||
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 => {
|
|
||||||
display_error!(msg.reply("Not in a voice channel"));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut manager = manager_lock.lock();
|
|
||||||
|
|
||||||
manager.join(guild_id, connect_to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_songs(
|
if names.len() > 0 {
|
||||||
&self,
|
print_error!(msg.channel_id.say("song already loaded!"));
|
||||||
ctx: &mut serenity::client::Context,
|
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
mut source: Vec<Song>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
{
|
|
||||||
let playlist_mutex = self.media.playlist_mut()?;
|
|
||||||
playlist_mutex.borrow_mut().append(&mut source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() {
|
self.append_songs(
|
||||||
Self::check_join_channel(&manager_lock, msg);
|
ctx,
|
||||||
|
msg,
|
||||||
|
names.iter().map(|n| Song { name: n.clone() }).collect(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let check_finished = {
|
return Ok(());
|
||||||
let media_clone = self.media.clone();
|
|
||||||
let channel_id = msg.channel_id;
|
|
||||||
let manager_lock_clone = manager_lock.clone();
|
|
||||||
|
|
||||||
Arc::new(move || {
|
|
||||||
let callback = match media_clone.next_callback.borrow().deref() {
|
|
||||||
Some(callback) => callback.clone(),
|
|
||||||
None => {
|
|
||||||
println!("next_callback not set!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MediaData::next_song(&media_clone, channel_id, &manager_lock_clone, callback);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
MediaData::start_playing(&self.media, check_finished, msg.channel_id, &manager_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_http_request(
|
let source = match youtube_dl(&url) {
|
||||||
&self,
|
Ok(source) => source,
|
||||||
ctx: &mut serenity::client::Context,
|
Err(why) => {
|
||||||
msg: &serenity::model::channel::Message,
|
println!("Err starting source: {:?}", why);
|
||||||
url: &String,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let sql = self.media.lock_db()?;
|
|
||||||
|
|
||||||
let mut stmt = match sql.prepare("SELECT name FROM Vulva3 WHERE link = ?") {
|
print_error!(msg
|
||||||
Ok(statement) => statement,
|
.channel_id
|
||||||
Err(_) => return Err("failed preparing data base access".to_string()),
|
.say(format!("Error using youtube-dl: {}", why)));
|
||||||
};
|
|
||||||
|
|
||||||
let rows = match stmt.query_map(&[url], |row| row.get(0) as rusqlite::Result<String>) {
|
|
||||||
Ok(rows) => rows,
|
|
||||||
Err(_) => return Err("failed querying rows".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut names = Vec::new();
|
|
||||||
for name_result in rows {
|
|
||||||
let name = match name_result {
|
|
||||||
Ok(name) => name,
|
|
||||||
Err(_) => return Err("failed getting name from row".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
names.push(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if names.len() > 0 {
|
|
||||||
print_error!(msg.channel_id.say("song already loaded!"));
|
|
||||||
|
|
||||||
self.append_songs(
|
|
||||||
ctx,
|
|
||||||
msg,
|
|
||||||
names.iter().map(|n| Song { name: n.clone() }).collect(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let source = match youtube_dl(&url) {
|
let mut info = if source.len() == 1 {
|
||||||
Ok(source) => source,
|
"Finished downloading song:".to_string()
|
||||||
Err(why) => {
|
} else {
|
||||||
println!("Err starting source: {:?}", why);
|
"Finished downloading songs:".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
print_error!(msg
|
for song in &source {
|
||||||
.channel_id
|
info = format!("{}\n\t{}", info, song.name);
|
||||||
.say(format!("Error using youtube-dl: {}", why)));
|
|
||||||
|
|
||||||
return Ok(());
|
if sql
|
||||||
}
|
.execute(
|
||||||
};
|
"INSERT INTO Vulva3 (name, link)
|
||||||
|
|
||||||
let mut info = if source.len() == 1 {
|
|
||||||
"Finished downloading song:".to_string()
|
|
||||||
} else {
|
|
||||||
"Finished downloading songs:".to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
for song in &source {
|
|
||||||
info = format!("{}\n\t{}", info, song.name);
|
|
||||||
|
|
||||||
if sql
|
|
||||||
.execute(
|
|
||||||
"INSERT INTO Vulva3 (name, link)
|
|
||||||
VALUES (?1, ?2)",
|
VALUES (?1, ?2)",
|
||||||
params![song.name, url],
|
params![song.name, url],
|
||||||
)
|
)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
return Err("failed inserting songs into db".to_string());
|
return Err("failed inserting songs into db".to_string());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_error!(msg.channel_id.say(info));
|
|
||||||
|
|
||||||
self.append_songs(ctx, msg, source)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_local_request(
|
print_error!(msg.channel_id.say(info));
|
||||||
&self,
|
|
||||||
ctx: &mut serenity::client::Context,
|
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let sql = self.media.lock_db()?;
|
|
||||||
|
|
||||||
let mut stmt = match sql.prepare("SELECT name FROM Vulva3") {
|
self.append_songs(ctx, msg, source)?;
|
||||||
Ok(statement) => statement,
|
|
||||||
Err(_) => return Err("failed preparing data base access".to_string()),
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_local_request(
|
||||||
|
media: &mut MediaData,
|
||||||
|
ctx: &mut serenity::client::Context,
|
||||||
|
msg: &serenity::model::channel::Message,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let sql = self.media.lock_db()?;
|
||||||
|
|
||||||
|
let mut stmt = match sql.prepare("SELECT name FROM Vulva3") {
|
||||||
|
Ok(statement) => statement,
|
||||||
|
Err(_) => return Err("failed preparing data base access".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
||||||
|
Ok(rows) => rows,
|
||||||
|
Err(_) => return Err("failed querying rows".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut songs = Vec::new();
|
||||||
|
for name_result in rows {
|
||||||
|
let name = match name_result {
|
||||||
|
Ok(name) => name,
|
||||||
|
Err(_) => return Err("failed getting name from row".to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
songs.push(Song { name });
|
||||||
Ok(rows) => rows,
|
}
|
||||||
Err(_) => return Err("failed querying rows".to_string()),
|
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
songs.shuffle(&mut rng);
|
||||||
|
|
||||||
|
self.append_songs(ctx, msg, songs)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_song_request(
|
||||||
|
media: &mut MediaData,
|
||||||
|
ctx: &mut serenity::client::Context,
|
||||||
|
msg: &serenity::model::channel::Message,
|
||||||
|
pattern: &str,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let sql = self.media.lock_db()?;
|
||||||
|
|
||||||
|
let mut stmt = match sql.prepare(&format!(
|
||||||
|
"SELECT name FROM Vulva3 WHERE name LIKE '%{}%'",
|
||||||
|
pattern
|
||||||
|
)) {
|
||||||
|
Ok(statement) => statement,
|
||||||
|
Err(_) => return Err("failed preparing data base access".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
||||||
|
Ok(rows) => rows,
|
||||||
|
Err(_) => return Err("failed querying rows".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut songs = Vec::new();
|
||||||
|
for name_result in rows {
|
||||||
|
let name = match name_result {
|
||||||
|
Ok(name) => name,
|
||||||
|
Err(_) => return Err("failed getting name from row".to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut songs = Vec::new();
|
songs.push(Song { name });
|
||||||
for name_result in rows {
|
}
|
||||||
let name = match name_result {
|
|
||||||
Ok(name) => name,
|
|
||||||
Err(_) => return Err("failed getting name from row".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
songs.push(Song { name });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if !songs.is_empty() {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
songs.shuffle(&mut rng);
|
songs.shuffle(&mut rng);
|
||||||
|
|
||||||
self.append_songs(ctx, msg, songs)?;
|
self.append_songs(ctx, msg, songs)?;
|
||||||
|
} else {
|
||||||
Ok(())
|
print_error!(msg
|
||||||
|
.channel_id
|
||||||
|
.say(format!("no song found with pattern {}", pattern)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_song_request(
|
Ok(())
|
||||||
&self,
|
|
||||||
ctx: &mut serenity::client::Context,
|
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
pattern: &str,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let sql = self.media.lock_db()?;
|
|
||||||
|
|
||||||
let mut stmt = match sql.prepare(&format!(
|
|
||||||
"SELECT name FROM Vulva3 WHERE name LIKE '%{}%'",
|
|
||||||
pattern
|
|
||||||
)) {
|
|
||||||
Ok(statement) => statement,
|
|
||||||
Err(_) => return Err("failed preparing data base access".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
|
||||||
Ok(rows) => rows,
|
|
||||||
Err(_) => return Err("failed querying rows".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut songs = Vec::new();
|
|
||||||
for name_result in rows {
|
|
||||||
let name = match name_result {
|
|
||||||
Ok(name) => name,
|
|
||||||
Err(_) => return Err("failed getting name from row".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
songs.push(Song { name });
|
|
||||||
}
|
|
||||||
|
|
||||||
if !songs.is_empty() {
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
songs.shuffle(&mut rng);
|
|
||||||
|
|
||||||
self.append_songs(ctx, msg, songs)?;
|
|
||||||
} else {
|
|
||||||
print_error!(msg
|
|
||||||
.channel_id
|
|
||||||
.say(format!("no song found with pattern {}", pattern)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl serenity::framework::standard::Command for Play {
|
|
||||||
#[allow(unreachable_code, unused_mut)]
|
|
||||||
fn execute(
|
|
||||||
&self,
|
|
||||||
mut ctx: &mut serenity::client::Context,
|
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
mut args: serenity::framework::standard::Args,
|
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
if !channel_contains_author(ctx, msg) {
|
|
||||||
println!(
|
|
||||||
"user {} is not in the same voice channel as the bot",
|
|
||||||
msg.author.name
|
|
||||||
);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.len() == 0 {
|
|
||||||
if !Self::check_for_continue(self.media.song_mut()?) {
|
|
||||||
print_error!(msg.channel_id.say("Must provide a URL to a video or audio"));
|
|
||||||
}
|
|
||||||
} else if args.len() == 1 {
|
|
||||||
let arg = match args.single::<String>() {
|
|
||||||
Ok(arg) => arg,
|
|
||||||
// can't happen, since we tested for length == 1
|
|
||||||
Err(_) => return Ok(()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if arg == "--local" {
|
|
||||||
self.handle_local_request(ctx, msg)?;
|
|
||||||
} else if arg.starts_with("http") {
|
|
||||||
self.handle_http_request(ctx, msg, &arg)?;
|
|
||||||
} else {
|
|
||||||
self.handle_song_request(ctx, msg, &arg)?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print_error!(msg.channel_id.say("Unsupported argument list"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,50 @@
|
||||||
use serenity;
|
use serenity;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::super::prelude::*;
|
use super::super::prelude::*;
|
||||||
|
|
||||||
use rusqlite::params;
|
use rusqlite::params;
|
||||||
|
|
||||||
pub struct Remove {
|
use serenity::prelude::*;
|
||||||
media: Arc<MediaData>,
|
use serenity::{
|
||||||
}
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
};
|
||||||
|
|
||||||
impl Remove {
|
#[command]
|
||||||
pub fn new(media_data: Arc<MediaData>) -> Remove {
|
fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
|
||||||
Remove { media: media_data }
|
let data = ctx.data.read();
|
||||||
}
|
let media = match data.get::<MediaData>() {
|
||||||
}
|
Ok(media) => media,
|
||||||
|
Err(_) => {
|
||||||
impl serenity::framework::standard::Command for Remove {
|
msg.channel_id.say("could not find media data");
|
||||||
#[allow(unreachable_code, unused_mut)]
|
return Ok(());
|
||||||
fn execute(
|
|
||||||
&self,
|
|
||||||
mut _ctx: &mut serenity::client::Context,
|
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
mut _args: serenity::framework::standard::Args,
|
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
// (1)
|
|
||||||
|
|
||||||
let song_name = self.media.name_mut()?;
|
|
||||||
let name: String = song_name.borrow().clone();
|
|
||||||
|
|
||||||
let sql = self.media.lock_db()?;
|
|
||||||
|
|
||||||
if let Err(_) = sql.execute("DELETE FROM Vulva3 WHERE name = ?", params![name]) {
|
|
||||||
return Err(serenity::framework::standard::CommandError(
|
|
||||||
"failed executing sql delete".to_string(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if !name.is_empty() {
|
let song_name = media.song_name();
|
||||||
match fs::remove_file(&name) {
|
let sql = media.db();
|
||||||
Ok(_) => print_error!(msg
|
|
||||||
.channel_id
|
|
||||||
.say(format!("Remove current song ({}) from local disk", name))),
|
|
||||||
Err(err) => print_error!(msg.channel_id.say(format!(
|
|
||||||
"Error removing file ({}): {:?}",
|
|
||||||
name,
|
|
||||||
err.kind()
|
|
||||||
))),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
if let Err(_) = sql.execute("DELETE FROM Vulva3 WHERE name = ?", params![song_name]) {
|
||||||
|
return Err(serenity::framework::standard::CommandError(
|
||||||
|
"failed executing sql delete".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !song_name.is_empty() {
|
||||||
|
match fs::remove_file(&song_name) {
|
||||||
|
Ok(_) => print_error!(msg.channel_id.say(format!(
|
||||||
|
"Remove current song ({}) from local disk",
|
||||||
|
song_name
|
||||||
|
))),
|
||||||
|
Err(err) => print_error!(msg.channel_id.say(format!(
|
||||||
|
"Error removing file ({}): {:?}",
|
||||||
|
song_name,
|
||||||
|
err.kind()
|
||||||
|
))),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,94 +1,99 @@
|
||||||
use serenity;
|
use serenity;
|
||||||
use serenity::voice::ffmpeg;
|
use serenity::voice::ffmpeg;
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::super::prelude::*;
|
use super::super::prelude::*;
|
||||||
|
|
||||||
pub struct Skip {
|
use serenity::prelude::*;
|
||||||
media: Arc<MediaData>,
|
use serenity::{
|
||||||
}
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
};
|
||||||
|
|
||||||
impl Skip {
|
#[command]
|
||||||
pub fn new(media_data: Arc<MediaData>) -> Skip {
|
fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
|
||||||
Skip { media: media_data }
|
if !channel_contains_author(ctx, msg) {
|
||||||
|
println!(
|
||||||
|
"user {} is not in the same voice channel as the bot",
|
||||||
|
msg.author.name
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl serenity::framework::standard::Command for Skip {
|
if let Some(mut manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() {
|
||||||
#[allow(unreachable_code, unused_mut)]
|
let mut manager = manager_lock.lock();
|
||||||
fn execute(
|
|
||||||
&self,
|
|
||||||
ctx: &mut serenity::client::Context,
|
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
_: serenity::framework::standard::Args,
|
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
if !channel_contains_author(ctx, msg) {
|
|
||||||
println!(
|
|
||||||
"user {} is not in the same voice channel as the bot",
|
|
||||||
msg.author.name
|
|
||||||
);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(mut manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() {
|
let guild_id = match guild_id(msg.channel_id) {
|
||||||
let mut manager = manager_lock.lock();
|
Some(id) => id,
|
||||||
|
None => {
|
||||||
|
println!("error getting guild id");
|
||||||
|
print_error!(msg.channel_id.say("error getting guild id"));
|
||||||
|
|
||||||
let guild_id = match guild_id(msg.channel_id) {
|
return Ok(());
|
||||||
Some(id) => id,
|
}
|
||||||
None => {
|
};
|
||||||
println!("error getting guild id");
|
|
||||||
print_error!(msg.channel_id.say("error getting guild id"));
|
|
||||||
|
|
||||||
|
if let Some(handler) = handler(guild_id, &mut manager) {
|
||||||
|
let data = ctx.data.read();
|
||||||
|
let mut media = match data.get_mut::<MediaData>() {
|
||||||
|
Ok(media) => media,
|
||||||
|
Err(_) => {
|
||||||
|
msg.channel_id.say("could not find media data");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(handler) = handler(guild_id, &mut manager) {
|
let mut playlist = media.playlist_mut();
|
||||||
let playlist_mutex = self.media.playlist_mut()?;
|
let mut song = media.song_mut();
|
||||||
let mut playlist = playlist_mutex.borrow_mut();
|
|
||||||
|
|
||||||
let song_mutex = self.media.song_mut()?;
|
// if current song is the last song in this playlist, just return
|
||||||
let mut song = song_mutex.borrow_mut();
|
if playlist.is_empty() {
|
||||||
|
print_error!(msg
|
||||||
|
.channel_id
|
||||||
|
.say("playlist is empty, no next song available"));
|
||||||
|
|
||||||
if playlist.is_empty() {
|
return Ok(());
|
||||||
print_error!(msg
|
} else {
|
||||||
.channel_id
|
// remove the current song from the playlist
|
||||||
.say("playlist is empty, no next song available"));
|
let first = playlist.remove(0);
|
||||||
|
|
||||||
return Ok(());
|
// stop the current song from playing
|
||||||
} else {
|
handler.stop();
|
||||||
let first = playlist.remove(0);
|
|
||||||
|
|
||||||
handler.stop();
|
// load next song into memory
|
||||||
|
let source = match ffmpeg(first.name.clone()) {
|
||||||
|
Ok(mpeg) => mpeg,
|
||||||
|
Err(_) => {
|
||||||
|
playlist.clear();
|
||||||
|
*song = None;
|
||||||
|
|
||||||
let source = match ffmpeg(first.name.clone()) {
|
return Ok(());
|
||||||
Ok(mpeg) => mpeg,
|
|
||||||
Err(_) => {
|
|
||||||
playlist.clear();
|
|
||||||
*song = None;
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.media.next_callback.borrow().as_ref() {
|
|
||||||
Some(callback) => {
|
|
||||||
*song =
|
|
||||||
Some(handler.play_returning_and_callback(source, callback.clone()));
|
|
||||||
let song_name = self.media.name_mut()?;
|
|
||||||
*song_name.borrow_mut() = first.name.clone();
|
|
||||||
|
|
||||||
print_error!(msg
|
|
||||||
.channel_id
|
|
||||||
.say(format!("Skipped current song, now playing: {}", first.name)));
|
|
||||||
}
|
|
||||||
None => println!("error getting callback from media"),
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// start the next song if possible
|
||||||
|
/*
|
||||||
|
match self.media.next_callback.borrow().as_ref() {
|
||||||
|
Some(callback) => {
|
||||||
|
*song = Some(handler.play_returning_and_callback(source, callback.clone()));
|
||||||
|
let song_name = self.media.name_mut()?;
|
||||||
|
*song_name.borrow_mut() = first.name.clone();
|
||||||
|
|
||||||
|
print_error!(msg
|
||||||
|
.channel_id
|
||||||
|
.say(format!("Skipped current song, now playing: {}", first.name)));
|
||||||
|
}
|
||||||
|
None => println!("error getting callback from media"),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
*song = Some(handler.play_returning(source));
|
||||||
|
*media.song_name_mut() = first.name.clone();
|
||||||
|
|
||||||
|
print_error!(msg
|
||||||
|
.channel_id
|
||||||
|
.say(format!("Skipped current song, now playing: {}", first.name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,31 @@
|
||||||
use serenity;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::super::prelude::*;
|
use super::super::prelude::*;
|
||||||
|
|
||||||
pub struct Stop {
|
use serenity::prelude::*;
|
||||||
media: Arc<MediaData>,
|
use serenity::{
|
||||||
}
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
};
|
||||||
|
|
||||||
impl Stop {
|
#[command]
|
||||||
pub fn new(media_data: Arc<MediaData>) -> Stop {
|
fn stop(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
|
||||||
Stop { media: media_data }
|
if !channel_contains_author(ctx, msg) {
|
||||||
|
println!(
|
||||||
|
"user {} is not in the same voice channel as the bot",
|
||||||
|
msg.author.name
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl serenity::framework::standard::Command for Stop {
|
let data = ctx.data.read();
|
||||||
#[allow(unreachable_code, unused_mut)]
|
let mut media = match data.get_mut::<MediaData>() {
|
||||||
fn execute(
|
Ok(media) => media,
|
||||||
&self,
|
Err(_) => {
|
||||||
ctx: &mut serenity::client::Context,
|
msg.channel_id.say("could not find media data");
|
||||||
msg: &serenity::model::channel::Message,
|
|
||||||
_: serenity::framework::standard::Args,
|
|
||||||
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
||||||
if !channel_contains_author(ctx, msg) {
|
|
||||||
println!(
|
|
||||||
"user {} is not in the same voice channel as the bot",
|
|
||||||
msg.author.name
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
print_error!(self.media.reset(ctx, msg));
|
print_error!(data.reset(ctx, msg));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@ use serenity::model::id::ChannelId;
|
||||||
use serenity::voice::ffmpeg;
|
use serenity::voice::ffmpeg;
|
||||||
use serenity::voice::LockedAudio;
|
use serenity::voice::LockedAudio;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::sync::Arc;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
|
||||||
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
|
|
||||||
|
@ -15,12 +14,12 @@ pub struct Song {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MediaData {
|
pub struct MediaData {
|
||||||
playlist: Mutex<RefCell<Vec<Song>>>,
|
playlist: Vec<Song>,
|
||||||
current_song: Mutex<RefCell<Option<LockedAudio>>>,
|
current_song: Option<LockedAudio>,
|
||||||
song_name: Mutex<RefCell<String>>,
|
song_name: String,
|
||||||
pub next_callback: RefCell<Option<Arc<Fn() -> ()>>>,
|
pub next_callback: Option<Arc<Fn() -> ()>>,
|
||||||
|
|
||||||
sql_data_base: Mutex<Connection>,
|
sql_data_base: Connection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaData {
|
impl MediaData {
|
||||||
|
@ -32,9 +31,9 @@ impl MediaData {
|
||||||
|
|
||||||
match connection.execute(
|
match connection.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS Vulva3 (
|
"CREATE TABLE IF NOT EXISTS Vulva3 (
|
||||||
name TEXT PRIMARY KEY,
|
name TEXT PRIMARY KEY,
|
||||||
link TEXT NOT NULL
|
link TEXT NOT NULL
|
||||||
)",
|
)",
|
||||||
params![],
|
params![],
|
||||||
) {
|
) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
|
@ -45,38 +44,24 @@ impl MediaData {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(MediaData {
|
Ok(MediaData {
|
||||||
playlist: Mutex::new(RefCell::new(Vec::new())),
|
playlist: Vec::new(),
|
||||||
current_song: Mutex::new(RefCell::new(None)),
|
current_song: None,
|
||||||
song_name: Mutex::new(RefCell::new(String::new())),
|
song_name: String::new(),
|
||||||
next_callback: RefCell::new(None),
|
next_callback: None,
|
||||||
|
|
||||||
sql_data_base: Mutex::new(connection),
|
sql_data_base: connection,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(
|
pub fn reset(
|
||||||
&self,
|
&mut self,
|
||||||
ctx: &mut serenity::client::Context,
|
ctx: &mut serenity::client::Context,
|
||||||
msg: &serenity::model::channel::Message,
|
msg: &serenity::model::channel::Message,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
{
|
self.playlist().clear();
|
||||||
let playlist = self.playlist_mut()?;
|
self.song = None;
|
||||||
playlist.borrow_mut().clear();
|
self.name = String::new();
|
||||||
}
|
self.next_callback = None();
|
||||||
|
|
||||||
{
|
|
||||||
let song = self.song_mut()?;
|
|
||||||
*song.borrow_mut() = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let name = self.name_mut()?;
|
|
||||||
*name.borrow_mut() = String::new();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
*self.next_callback.borrow_mut() = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() {
|
if let Some(manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() {
|
||||||
let mut manager = manager_lock.lock();
|
let mut manager = manager_lock.lock();
|
||||||
|
@ -103,32 +88,32 @@ impl MediaData {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lock_db(&self) -> Result<MutexGuard<Connection>, String> {
|
pub fn db(&self) -> &Connection {
|
||||||
match self.sql_data_base.lock() {
|
&self.sql_data_base
|
||||||
Ok(sql) => Ok(sql),
|
|
||||||
Err(_) => Err("failed locking db".to_string()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn song_mut(&self) -> Result<MutexGuard<RefCell<Option<LockedAudio>>>, String> {
|
pub fn song(&self) -> &Option<LockedAudio> {
|
||||||
match self.current_song.lock() {
|
&self.current_song
|
||||||
Ok(sql) => Ok(sql),
|
|
||||||
Err(_) => Err("failed locking current song".to_string()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn playlist_mut(&self) -> Result<MutexGuard<RefCell<Vec<Song>>>, String> {
|
pub fn song_mut(&mut self) -> &mut Option<LockedAudio> {
|
||||||
match self.playlist.lock() {
|
&mut self.current_song
|
||||||
Ok(sql) => Ok(sql),
|
|
||||||
Err(_) => Err("failed locking playlist".to_string()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_mut(&self) -> Result<MutexGuard<RefCell<String>>, String> {
|
pub fn playlist(&self) -> &Vec<Song> {
|
||||||
match self.song_name.lock() {
|
&self.playlist
|
||||||
Ok(sql) => Ok(sql),
|
}
|
||||||
Err(_) => Err("failed locking current song name".to_string()),
|
|
||||||
}
|
pub fn playlist_mut(&mut self) -> &mut Vec<Song> {
|
||||||
|
&mut self.playlist
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn song_name(&self) -> &String {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn song_name_mut(&mut self) -> &mut String {
|
||||||
|
&mut self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_playing(
|
pub fn start_playing(
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use parking_lot;
|
use parking_lot::MutexGuard;
|
||||||
|
|
||||||
use serenity;
|
use serenity;
|
||||||
use serenity::client::CACHE;
|
|
||||||
use serenity::model::id::{ChannelId, GuildId};
|
use serenity::model::id::{ChannelId, GuildId};
|
||||||
use serenity::voice::Handler;
|
use serenity::voice::Handler;
|
||||||
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
|
|
||||||
pub fn guild_id(channel_id: ChannelId) -> Option<GuildId> {
|
pub fn guild_id(channel_id: ChannelId) -> Option<GuildId> {
|
||||||
|
/*
|
||||||
match CACHE.read().guild_channel(channel_id) {
|
match CACHE.read().guild_channel(channel_id) {
|
||||||
Some(channel) => Some(channel.read().guild_id),
|
Some(channel) => Some(channel.read().guild_id),
|
||||||
None => {
|
None => {
|
||||||
|
@ -15,14 +14,13 @@ pub fn guild_id(channel_id: ChannelId) -> Option<GuildId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handler<'a>(
|
pub fn handler<'a>(
|
||||||
guild_id: GuildId,
|
guild_id: GuildId,
|
||||||
manager: &'a mut parking_lot::MutexGuard<
|
manager: &'a mut MutexGuard<'_, serenity::client::bridge::voice::ClientVoiceManager>,
|
||||||
'_,
|
|
||||||
serenity::client::bridge::voice::ClientVoiceManager,
|
|
||||||
>,
|
|
||||||
) -> Option<&'a mut Handler> {
|
) -> Option<&'a mut Handler> {
|
||||||
manager.get_mut(guild_id)
|
manager.get_mut(guild_id)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +30,7 @@ pub fn channel_contains_author(
|
||||||
msg: &serenity::model::channel::Message,
|
msg: &serenity::model::channel::Message,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let (guild_id, voice_channel_id_bot) = {
|
let (guild_id, voice_channel_id_bot) = {
|
||||||
match ctx.data.lock().get::<VoiceManager>().cloned() {
|
match ctx.data.read().get::<VoiceManager>().cloned() {
|
||||||
Some(manager_lock) => {
|
Some(manager_lock) => {
|
||||||
let mut manager = manager_lock.lock();
|
let mut manager = manager_lock.lock();
|
||||||
let guild_id = match guild_id(msg.channel_id) {
|
let guild_id = match guild_id(msg.channel_id) {
|
||||||
|
@ -68,7 +66,7 @@ pub fn channel_contains_author(
|
||||||
|
|
||||||
let author = &msg.author;
|
let author = &msg.author;
|
||||||
|
|
||||||
let guild = match guild_id.to_guild_cached() {
|
let guild = match guild_id.to_guild_cached(&ctx) {
|
||||||
Some(guild) => guild,
|
Some(guild) => guild,
|
||||||
None => {
|
None => {
|
||||||
println!("error getting guild from cache");
|
println!("error getting guild from cache");
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
pub use super::mediadata::{MediaData, Song};
|
pub use super::mediadata::{MediaData, Song};
|
||||||
|
|
||||||
pub use super::commands::help::Help;
|
pub use super::commands::ip::*;
|
||||||
pub use super::commands::ip::IP;
|
pub use super::commands::list::*;
|
||||||
pub use super::commands::list::List;
|
pub use super::commands::pause::*;
|
||||||
pub use super::commands::pause::Pause;
|
pub use super::commands::play::*;
|
||||||
pub use super::commands::play::Play;
|
pub use super::commands::remove::*;
|
||||||
pub use super::commands::remove::Remove;
|
pub use super::commands::skip::*;
|
||||||
pub use super::commands::skip::Skip;
|
pub use super::commands::stop::*;
|
||||||
pub use super::commands::stop::Stop;
|
|
||||||
|
|
||||||
pub use super::eventhandler::Handler;
|
pub use super::eventhandler::Handler;
|
||||||
pub use super::voicemanager::VoiceManager;
|
pub use super::voicemanager::VoiceManager;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use parking_lot::Mutex;
|
||||||
use serenity::client::bridge::voice::ClientVoiceManager;
|
use serenity::client::bridge::voice::ClientVoiceManager;
|
||||||
use serenity::prelude::Mutex;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use typemap::Key;
|
use typemap::Key;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue