255 lines
7.1 KiB
Rust
255 lines
7.1 KiB
Rust
use serenity;
|
|
use serenity::model::id::ChannelId;
|
|
use serenity::voice::ffmpeg;
|
|
use serenity::voice::LockedAudio;
|
|
|
|
use std::cell::RefCell;
|
|
use std::sync::{Arc, Mutex, MutexGuard};
|
|
|
|
use super::prelude::*;
|
|
|
|
use rusqlite::{params, Connection};
|
|
|
|
pub struct Song {
|
|
pub name: String,
|
|
}
|
|
|
|
pub struct MediaData {
|
|
playlist: Mutex<RefCell<Vec<Song>>>,
|
|
current_song: Mutex<RefCell<Option<LockedAudio>>>,
|
|
song_name: Mutex<RefCell<String>>,
|
|
pub next_callback: RefCell<Option<Arc<Fn() -> ()>>>,
|
|
|
|
sql_data_base: Mutex<Connection>,
|
|
}
|
|
|
|
impl MediaData {
|
|
pub fn new(file: &str) -> Result<MediaData, String> {
|
|
let connection = match Connection::open(file) {
|
|
Ok(file) => file,
|
|
Err(_) => return Err(format!("can't open {}", file)),
|
|
};
|
|
|
|
match connection.execute(
|
|
"CREATE TABLE IF NOT EXISTS Vulva3 (
|
|
name TEXT PRIMARY KEY,
|
|
link TEXT NOT NULL
|
|
)",
|
|
params![],
|
|
) {
|
|
Ok(_) => (),
|
|
Err(err) => {
|
|
println!("{}", err);
|
|
return Err(format!("can't create table"));
|
|
}
|
|
};
|
|
|
|
Ok(MediaData {
|
|
playlist: Mutex::new(RefCell::new(Vec::new())),
|
|
current_song: Mutex::new(RefCell::new(None)),
|
|
song_name: Mutex::new(RefCell::new(String::new())),
|
|
next_callback: RefCell::new(None),
|
|
|
|
sql_data_base: Mutex::new(connection),
|
|
})
|
|
}
|
|
|
|
pub fn reset(
|
|
&self,
|
|
ctx: &mut serenity::client::Context,
|
|
msg: &serenity::model::channel::Message,
|
|
) -> Result<(), String> {
|
|
{
|
|
let playlist = self.playlist_mut()?;
|
|
playlist.borrow_mut().clear();
|
|
}
|
|
|
|
{
|
|
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() {
|
|
let mut manager = manager_lock.lock();
|
|
|
|
let guild_id = match guild_id(msg.channel_id) {
|
|
Some(guild_id) => guild_id,
|
|
None => return Ok(()),
|
|
};
|
|
|
|
{
|
|
let handler = match handler(guild_id, &mut manager) {
|
|
Some(handler) => handler,
|
|
None => return Ok(()),
|
|
};
|
|
|
|
println!("stopped handler");
|
|
|
|
handler.stop();
|
|
}
|
|
|
|
manager.remove(guild_id);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn lock_db(&self) -> Result<MutexGuard<Connection>, String> {
|
|
match self.sql_data_base.lock() {
|
|
Ok(sql) => Ok(sql),
|
|
Err(_) => Err("failed locking db".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn song_mut(&self) -> Result<MutexGuard<RefCell<Option<LockedAudio>>>, String> {
|
|
match self.current_song.lock() {
|
|
Ok(sql) => Ok(sql),
|
|
Err(_) => Err("failed locking current song".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn playlist_mut(&self) -> Result<MutexGuard<RefCell<Vec<Song>>>, String> {
|
|
match self.playlist.lock() {
|
|
Ok(sql) => Ok(sql),
|
|
Err(_) => Err("failed locking playlist".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn name_mut(&self) -> Result<MutexGuard<RefCell<String>>, String> {
|
|
match self.song_name.lock() {
|
|
Ok(sql) => Ok(sql),
|
|
Err(_) => Err("failed locking current song name".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn start_playing(
|
|
mediadata: &Arc<MediaData>,
|
|
callback: Arc<Fn() -> ()>,
|
|
channel_id: ChannelId,
|
|
manager_lock: &Arc<
|
|
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
|
|
>,
|
|
) {
|
|
// check if there is already playing
|
|
let already_started = {
|
|
let song_lock = match mediadata.song_mut() {
|
|
Ok(song) => song,
|
|
Err(msg) => {
|
|
println!("{}", msg);
|
|
return;
|
|
}
|
|
};
|
|
|
|
let song = song_lock.borrow();
|
|
song.is_some()
|
|
};
|
|
|
|
// if there isnt already a song playing, start a new one
|
|
if !already_started {
|
|
*mediadata.next_callback.borrow_mut() = Some(callback.clone());
|
|
|
|
Self::next_song(mediadata, channel_id, manager_lock, callback);
|
|
}
|
|
}
|
|
|
|
pub fn next_song(
|
|
mediadata: &Arc<MediaData>,
|
|
channel_id: ChannelId,
|
|
manager_lock: &Arc<
|
|
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
|
|
>,
|
|
callback: Arc<Fn() -> ()>,
|
|
) {
|
|
let mut manager = manager_lock.lock();
|
|
|
|
let guild_id = match guild_id(channel_id) {
|
|
Some(id) => id,
|
|
None => {
|
|
println!("error getting guild_id");
|
|
return;
|
|
}
|
|
};
|
|
|
|
let mut need_to_leave = false;
|
|
|
|
{
|
|
let handler = {
|
|
match handler(guild_id, &mut manager) {
|
|
Some(handler) => handler,
|
|
None => {
|
|
println!("error getting handler");
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
let playlist_lock = match mediadata.playlist_mut() {
|
|
Ok(playlist) => playlist,
|
|
Err(msg) => {
|
|
println!("{}", msg);
|
|
return;
|
|
}
|
|
};
|
|
let mut playlist = playlist_lock.borrow_mut();
|
|
|
|
let song_name_lock = match mediadata.name_mut() {
|
|
Ok(name) => name,
|
|
Err(msg) => {
|
|
println!("{}", msg);
|
|
return;
|
|
}
|
|
};
|
|
let mut name = song_name_lock.borrow_mut();
|
|
|
|
let song_lock = match mediadata.song_mut() {
|
|
Ok(song) => song,
|
|
Err(msg) => {
|
|
println!("{}", msg);
|
|
return;
|
|
}
|
|
};
|
|
let mut song = song_lock.borrow_mut();
|
|
|
|
if playlist.is_empty() {
|
|
need_to_leave = true;
|
|
handler.stop();
|
|
*song = None;
|
|
*name = String::new();
|
|
} else {
|
|
handler.stop();
|
|
|
|
let first = playlist.remove(0);
|
|
|
|
let source = match ffmpeg(first.name.clone()) {
|
|
Ok(mpeg) => mpeg,
|
|
Err(_) => {
|
|
playlist.clear();
|
|
|
|
return;
|
|
}
|
|
};
|
|
|
|
*song = Some(handler.play_returning_and_callback(source, callback));
|
|
*name = first.name.clone();
|
|
|
|
print_error!(channel_id.say(format!("Playing song: {}", first.name)));
|
|
}
|
|
}
|
|
|
|
if need_to_leave {
|
|
manager.remove(guild_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
unsafe impl Send for MediaData {}
|
|
unsafe impl Sync for MediaData {}
|