Update deps and error handling
This commit is contained in:
parent
767ced2df0
commit
17d4a3e02a
7 changed files with 361 additions and 60 deletions
|
@ -7,10 +7,9 @@ authors = ["hodasemi <michaelh.95@t-online.de>"]
|
|||
[dependencies]
|
||||
typemap = "~0.3"
|
||||
serde_json = "*"
|
||||
utilities = { git = "http://gavania.de/hodasemi/context" }
|
||||
rusqlite = { version = "*", features = ["bundled"] }
|
||||
serenity = { version = "0.8", default-features = false, features = [ "builder", "cache", "client", "framework", "gateway", "model", "standard_framework", "utils", "voice", "rustls_backend"]}
|
||||
parking_lot = "*"
|
||||
failure = "*"
|
||||
anyhow = "*"
|
||||
hey_listen = "*"
|
||||
white_rabbit = "*"
|
||||
rand = "*"
|
||||
|
|
304
src/config_handler.rs
Normal file
304
src/config_handler.rs
Normal file
|
@ -0,0 +1,304 @@
|
|||
#![allow(unused)]
|
||||
|
||||
//! Config file handler
|
||||
//! Cares about formatting and type conversion
|
||||
use anyhow::{Context, Result};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{BufRead, BufReader, Write},
|
||||
path::Path,
|
||||
str::FromStr,
|
||||
};
|
||||
/// Value abstraction to convert to and from values
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Value {
|
||||
Value(String),
|
||||
Array(Vec<String>),
|
||||
}
|
||||
struct ConfigSection {
|
||||
header: String,
|
||||
body: HashMap<String, Value>,
|
||||
}
|
||||
impl Value {
|
||||
/// Creates an empty value
|
||||
pub fn empty() -> Value {
|
||||
Value::Value("".to_string())
|
||||
}
|
||||
/// Creates an empty array value
|
||||
pub fn empty_array() -> Value {
|
||||
Value::Array(Vec::new())
|
||||
}
|
||||
/// Create a value `Value::Array(Vec<String>)`, internal conversion to string
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// `array` array of type, type has to implement `Display` trait
|
||||
#[deprecated]
|
||||
pub fn from_array<T: Display>(array: &[T]) -> Self {
|
||||
Value::Array(array.iter().map(|v| format!("{}", v)).collect())
|
||||
}
|
||||
/// Creates a value `Value::Value(String)`, internal conversion to string
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// `value` type has to implement `Display` trait
|
||||
#[deprecated]
|
||||
pub fn from_value<T: Display>(value: &T) -> Self {
|
||||
Value::Value(format!("{}", value))
|
||||
}
|
||||
pub fn to_array<T: FromStr>(&self) -> Result<Vec<T>> {
|
||||
match self {
|
||||
Value::Array(value_array) => {
|
||||
let mut target_array = Vec::with_capacity(value_array.len());
|
||||
for value_string in value_array {
|
||||
match value_string.parse::<T>() {
|
||||
Ok(val) => target_array.push(val),
|
||||
Err(_) => {
|
||||
return Err(anyhow::Error::msg(format!(
|
||||
"ConfigHandler: Error while parsing Value Array: {}",
|
||||
value_string
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(target_array)
|
||||
}
|
||||
_ => Err(anyhow::Error::msg(
|
||||
"ConfigHandler: Error when requesting the wrong value type",
|
||||
)),
|
||||
}
|
||||
}
|
||||
pub fn to_value<T: FromStr>(&self) -> Result<T> {
|
||||
match self {
|
||||
Value::Value(value_string) => match value_string.parse::<T>() {
|
||||
Ok(val) => Ok(val),
|
||||
Err(_) => Err(anyhow::Error::msg(format!(
|
||||
"ConfigHandler: Error while parsing Value Array: {}",
|
||||
value_string
|
||||
))),
|
||||
},
|
||||
_ => Err(anyhow::Error::msg(
|
||||
"ConfigHandler: Error when requesting the wrong value type",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, T: Display> From<&'a T> for Value {
|
||||
fn from(v: &'a T) -> Self {
|
||||
Value::Value(format!("{}", v))
|
||||
}
|
||||
}
|
||||
impl<'a, T: Display> From<&'a [T]> for Value {
|
||||
fn from(v: &'a [T]) -> Self {
|
||||
Value::Array(v.iter().map(|v| format!("{}", v)).collect())
|
||||
}
|
||||
}
|
||||
/// Handler struct
|
||||
pub struct ConfigHandler {}
|
||||
impl ConfigHandler {
|
||||
/// Reads the given config file
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// `file_name` file that is going to be read
|
||||
pub fn read_config(
|
||||
file_name: impl AsRef<Path>,
|
||||
) -> Result<HashMap<String, HashMap<String, Value>>> {
|
||||
let file = File::open(&file_name).with_context({
|
||||
let file_name = file_name.as_ref().to_str().unwrap().to_string();
|
||||
|| file_name
|
||||
})?;
|
||||
let mut infos = HashMap::new();
|
||||
let mut current_section: Option<ConfigSection> = None;
|
||||
for line_res in BufReader::new(file).lines() {
|
||||
if let Ok(line) = line_res {
|
||||
let mut trimmed = line.trim().to_string();
|
||||
if trimmed.starts_with('#') || trimmed.is_empty() {
|
||||
continue;
|
||||
} else if trimmed.starts_with('[') && trimmed.ends_with(']') {
|
||||
trimmed.remove(0);
|
||||
trimmed.pop();
|
||||
if let Some(ref section) = current_section {
|
||||
infos.insert(section.header.clone(), section.body.clone());
|
||||
}
|
||||
current_section = Some(ConfigSection {
|
||||
header: trimmed,
|
||||
body: HashMap::new(),
|
||||
});
|
||||
} else {
|
||||
let mut split = trimmed.split('=');
|
||||
let key = match split.nth(0) {
|
||||
Some(key) => key.trim().to_string(),
|
||||
None => {
|
||||
println!("cannot get key from line: {}", trimmed);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let value = match split.last() {
|
||||
Some(value) => value.trim().to_string(),
|
||||
None => {
|
||||
println!("cannot get value from line: {}", trimmed);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if value.starts_with('[') && value.ends_with(']') {
|
||||
let mut trimmed_value = value;
|
||||
trimmed_value.remove(0);
|
||||
trimmed_value.pop();
|
||||
let value_split = trimmed_value.split(',');
|
||||
let mut value_array = Vec::new();
|
||||
for v in value_split {
|
||||
let trimmed = v.trim();
|
||||
if !trimmed.is_empty() {
|
||||
value_array.push(trimmed.to_string());
|
||||
}
|
||||
}
|
||||
if let Some(ref mut section) = current_section {
|
||||
section.body.insert(key, Value::Array(value_array));
|
||||
}
|
||||
} else if let Some(ref mut section) = current_section {
|
||||
section.body.insert(key, Value::Value(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// also push the last section
|
||||
if let Some(section) = current_section {
|
||||
infos.insert(section.header, section.body);
|
||||
}
|
||||
Ok(infos)
|
||||
}
|
||||
/// writes a formatted config file
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// `file_name` the file to which the config gets written
|
||||
/// `sections` the sections and keys that are going to be written
|
||||
pub fn write_config(
|
||||
file_name: impl AsRef<Path>,
|
||||
sections: &[(&str, Vec<(&str, Value)>)],
|
||||
) -> Result<()> {
|
||||
let mut file = File::create(file_name)?;
|
||||
for (header, body) in sections {
|
||||
let fmt_header = format!("[{}]\n", header);
|
||||
file.write_all(fmt_header.as_bytes())?;
|
||||
for (key, value) in body.iter() {
|
||||
let fmt_key_value = format!(
|
||||
"{} = {}\n",
|
||||
key,
|
||||
match value {
|
||||
Value::Value(val) => val.clone(),
|
||||
Value::Array(array) => {
|
||||
let mut array_value = "[".to_string();
|
||||
for (i, val) in array.iter().enumerate() {
|
||||
// if element is not the last one
|
||||
if i != array.len() - 1 {
|
||||
array_value = format!("{}{}, ", array_value, val);
|
||||
} else {
|
||||
array_value = format!("{}{}", array_value, val);
|
||||
}
|
||||
}
|
||||
format!("{}]", array_value)
|
||||
}
|
||||
}
|
||||
);
|
||||
file.write_all(fmt_key_value.as_bytes())?;
|
||||
}
|
||||
file.write_all("\n".as_bytes())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! create_settings_section {
|
||||
($struct_name:ident, $section_key:expr, {$($var:ident: $var_type:ty,)* $([$array:ident: $array_type:ty],)*} $(,$($derive:ident,)*)?) => {
|
||||
#[derive(Default, Debug, Clone, PartialEq $(, $($derive,)* )? )]
|
||||
pub struct $struct_name {
|
||||
$(
|
||||
pub $var: $var_type,
|
||||
)*
|
||||
$(
|
||||
pub $array: Vec<$array_type>,
|
||||
)*
|
||||
}
|
||||
impl $struct_name {
|
||||
const SECTION_KEY: &'static str = $section_key;
|
||||
pub fn load(
|
||||
parsed_config: &std::collections::HashMap<String, std::collections::HashMap<String, Value>>
|
||||
) -> anyhow::Result<Self> {
|
||||
let mut me = Self::default();
|
||||
if let Some(section) = parsed_config.get(Self::SECTION_KEY) {
|
||||
$(
|
||||
if let Some(value) = section.get(stringify!($var)) {
|
||||
me.$var = value.to_value()?;
|
||||
}
|
||||
)*
|
||||
$(
|
||||
if let Some(array) = section.get(stringify!($array)) {
|
||||
me.$array = array.to_array()?;
|
||||
}
|
||||
)*
|
||||
}
|
||||
Ok(me)
|
||||
}
|
||||
pub fn store(&self) -> (&str, Vec<(&str, Value)>) {
|
||||
(
|
||||
Self::SECTION_KEY,
|
||||
vec![
|
||||
$(
|
||||
(stringify!($var), Value::from(&self.$var)),
|
||||
)*
|
||||
$(
|
||||
(stringify!($array), Value::from(self.$array.as_slice())),
|
||||
)*
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! create_settings_container {
|
||||
($struct_name:ident, {$($var:ident: $var_type:ty$(,)?)*} $(,$($derive:ident,)*)? ) => {
|
||||
#[derive(Default, Debug, Clone, PartialEq $(, $($derive,)* )? )]
|
||||
pub struct $struct_name {
|
||||
pub file_name: assetpath::AssetPath,
|
||||
$(
|
||||
pub $var: $var_type,
|
||||
)*
|
||||
}
|
||||
impl $struct_name {
|
||||
pub fn load(file: impl Into<assetpath::AssetPath>) -> anyhow::Result<Self> {
|
||||
let file = file.into();
|
||||
let parsed_stats_settings = ConfigHandler::read_config(&file.full_path())?;
|
||||
Ok($struct_name {
|
||||
file_name: file,
|
||||
$(
|
||||
$var: <$var_type>::load(&parsed_stats_settings)?,
|
||||
)*
|
||||
})
|
||||
}
|
||||
pub fn load_with_default(&mut self, file: impl Into<assetpath::AssetPath>) -> anyhow::Result<()> {
|
||||
let file = file.into();
|
||||
let parsed_stats_settings = ConfigHandler::read_config(&file.full_path())?;
|
||||
self.file_name = file;
|
||||
$(
|
||||
self.$var = <$var_type>::load(&parsed_stats_settings)?;
|
||||
)*
|
||||
Ok(())
|
||||
}
|
||||
pub fn store(&self) -> anyhow::Result<()> {
|
||||
ConfigHandler::write_config(
|
||||
&self.file_name.full_path(),
|
||||
&[
|
||||
$(
|
||||
self.$var.store(),
|
||||
)*
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -6,6 +6,7 @@ extern crate parking_lot;
|
|||
extern crate serde_json;
|
||||
extern crate typemap;
|
||||
|
||||
mod config_handler;
|
||||
mod player;
|
||||
|
||||
use serenity::{
|
||||
|
@ -18,15 +19,15 @@ use serenity::{
|
|||
};
|
||||
|
||||
// This imports `typemap`'s `Key` as `TypeMapKey`.
|
||||
use anyhow::Result;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use config_handler::{ConfigHandler, Value};
|
||||
use player::prelude::*;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use utilities::prelude::*;
|
||||
|
||||
create_settings_section!(
|
||||
Config,
|
||||
"Meta",
|
||||
|
@ -53,7 +54,7 @@ fn my_help(
|
|||
help_commands::with_embeds(context, msg, args, &help_options, groups, owners)
|
||||
}
|
||||
|
||||
fn main() -> VerboseResult<()> {
|
||||
fn main() -> Result<()> {
|
||||
// read config file
|
||||
let config_file = ConfigHandler::read_config("bot.conf")?;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use serenity::{
|
|||
model::channel::Message,
|
||||
};
|
||||
|
||||
use utilities::prelude::*;
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
use std::sync::Once;
|
||||
use std::thread;
|
||||
|
@ -127,7 +127,7 @@ fn append_songs(
|
|||
ctx: &Context,
|
||||
msg: &Message,
|
||||
mut source: Vec<Song>,
|
||||
) -> VerboseResult<()> {
|
||||
) -> Result<()> {
|
||||
media.playlist_mut().append(&mut source);
|
||||
|
||||
println!("start playing");
|
||||
|
@ -141,7 +141,7 @@ fn handle_http_request(
|
|||
ctx: &serenity::client::Context,
|
||||
msg: &serenity::model::channel::Message,
|
||||
url: &str,
|
||||
) -> VerboseResult<()> {
|
||||
) -> Result<()> {
|
||||
let mut names = Vec::new();
|
||||
|
||||
{
|
||||
|
@ -149,18 +149,18 @@ fn handle_http_request(
|
|||
|
||||
let mut stmt = match sql.prepare("SELECT name FROM Vulva3 WHERE link = ?") {
|
||||
Ok(statement) => statement,
|
||||
Err(_) => create_error!("failed preparing data base access"),
|
||||
Err(_) => return Err(anyhow!("failed preparing data base access")),
|
||||
};
|
||||
|
||||
let rows = match stmt.query_map(&[url], |row| row.get(0) as rusqlite::Result<String>) {
|
||||
Ok(rows) => rows,
|
||||
Err(_) => create_error!("failed querying rows"),
|
||||
Err(_) => return Err(anyhow!("failed querying rows")),
|
||||
};
|
||||
|
||||
for name_result in rows {
|
||||
let name = match name_result {
|
||||
Ok(name) => name,
|
||||
Err(_) => create_error!("failed getting name from row"),
|
||||
Err(_) => return Err(anyhow!("failed getting name from row")),
|
||||
};
|
||||
|
||||
names.push(name);
|
||||
|
@ -170,7 +170,7 @@ fn handle_http_request(
|
|||
if names.len() > 0 {
|
||||
msg.channel_id
|
||||
.say(&ctx.http, "song already loaded!")
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
.map_err(|err| anyhow!("{}", err))?;
|
||||
|
||||
append_songs(
|
||||
media,
|
||||
|
@ -186,7 +186,7 @@ fn handle_http_request(
|
|||
|
||||
msg.channel_id
|
||||
.say(&ctx.http, format!("Error using youtube-dl: {}", why))
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
.map_err(|err| anyhow!("{}", err))?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -212,14 +212,14 @@ fn handle_http_request(
|
|||
)
|
||||
.is_err()
|
||||
{
|
||||
create_error!("failed inserting songs into db");
|
||||
return Err(anyhow!("failed inserting songs into db"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg.channel_id
|
||||
.say(&ctx.http, info)
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
.map_err(|err| anyhow!("{}", err))?;
|
||||
|
||||
append_songs(media, ctx, msg, source)?;
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ fn handle_local_request(
|
|||
media: &mut MediaData,
|
||||
ctx: &serenity::client::Context,
|
||||
msg: &serenity::model::channel::Message,
|
||||
) -> VerboseResult<()> {
|
||||
) -> Result<()> {
|
||||
let mut songs = Vec::new();
|
||||
|
||||
{
|
||||
|
@ -239,18 +239,18 @@ fn handle_local_request(
|
|||
|
||||
let mut stmt = match sql.prepare("SELECT name FROM Vulva3") {
|
||||
Ok(statement) => statement,
|
||||
Err(_) => create_error!("failed preparing data base access"),
|
||||
Err(_) => return Err(anyhow!("failed preparing data base access")),
|
||||
};
|
||||
|
||||
let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
||||
Ok(rows) => rows,
|
||||
Err(_) => create_error!("failed querying rows"),
|
||||
Err(_) => return Err(anyhow!("failed querying rows")),
|
||||
};
|
||||
|
||||
for name_result in rows {
|
||||
let name = match name_result {
|
||||
Ok(name) => name,
|
||||
Err(_) => create_error!("failed getting name from row"),
|
||||
Err(_) => return Err(anyhow!("failed getting name from row")),
|
||||
};
|
||||
|
||||
songs.push(Song { name });
|
||||
|
@ -270,7 +270,7 @@ fn handle_song_request(
|
|||
ctx: &serenity::client::Context,
|
||||
msg: &serenity::model::channel::Message,
|
||||
pattern: &str,
|
||||
) -> VerboseResult<()> {
|
||||
) -> Result<()> {
|
||||
println!("song request ({})", pattern);
|
||||
|
||||
let mut songs = Vec::new();
|
||||
|
@ -283,18 +283,18 @@ fn handle_song_request(
|
|||
pattern
|
||||
)) {
|
||||
Ok(statement) => statement,
|
||||
Err(_) => create_error!("failed preparing data base access"),
|
||||
Err(_) => return Err(anyhow!("failed preparing data base access")),
|
||||
};
|
||||
|
||||
let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
||||
Ok(rows) => rows,
|
||||
Err(_) => create_error!("failed querying rows"),
|
||||
Err(_) => return Err(anyhow!("failed querying rows")),
|
||||
};
|
||||
|
||||
for name_result in rows {
|
||||
let name = match name_result {
|
||||
Ok(name) => name,
|
||||
Err(_) => create_error!("failed getting name from row"),
|
||||
Err(_) => return Err(anyhow!("failed getting name from row")),
|
||||
};
|
||||
|
||||
songs.push(Song { name });
|
||||
|
@ -313,7 +313,7 @@ fn handle_song_request(
|
|||
} else {
|
||||
msg.channel_id
|
||||
.say(&ctx.http, format!("no song found with pattern {}", pattern))
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
.map_err(|err| anyhow!("{}", err))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -324,7 +324,7 @@ fn handle_tag_request(
|
|||
ctx: &serenity::client::Context,
|
||||
msg: &serenity::model::channel::Message,
|
||||
pattern: &str,
|
||||
) -> VerboseResult<()> {
|
||||
) -> Result<()> {
|
||||
let mut songs = Vec::new();
|
||||
|
||||
{
|
||||
|
@ -333,37 +333,37 @@ fn handle_tag_request(
|
|||
pattern
|
||||
)) {
|
||||
Ok(statement) => statement,
|
||||
Err(_) => create_error!("failed preparing data base access"),
|
||||
Err(_) => return Err(anyhow!("failed preparing data base access")),
|
||||
};
|
||||
|
||||
let mut rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>)
|
||||
{
|
||||
Ok(rows) => rows,
|
||||
Err(_) => create_error!("failed querying rows"),
|
||||
Err(_) => return Err(anyhow!("failed querying rows")),
|
||||
};
|
||||
|
||||
if let None = rows.next() {
|
||||
msg.channel_id
|
||||
.say(&ctx.http, format!("tag ({}) not found", pattern))
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
.map_err(|err| anyhow!("{}", err))?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut stmt = match media.db().prepare(&format!("SELECT name FROM {}", pattern)) {
|
||||
Ok(statement) => statement,
|
||||
Err(_) => create_error!("failed preparing data base access"),
|
||||
Err(_) => return Err(anyhow!("failed preparing data base access")),
|
||||
};
|
||||
|
||||
let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
||||
Ok(rows) => rows,
|
||||
Err(_) => create_error!("failed querying rows"),
|
||||
Err(_) => return Err(anyhow!("failed querying rows")),
|
||||
};
|
||||
|
||||
for name_result in rows {
|
||||
let name = match name_result {
|
||||
Ok(name) => name,
|
||||
Err(_) => create_error!("failed getting name from row"),
|
||||
Err(_) => return Err(anyhow!("failed getting name from row")),
|
||||
};
|
||||
|
||||
songs.push(Song { name });
|
||||
|
|
|
@ -13,10 +13,9 @@ use super::prelude::*;
|
|||
|
||||
use std::fs;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use rusqlite::{params, Connection};
|
||||
|
||||
use utilities::prelude::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Song {
|
||||
pub name: String,
|
||||
|
@ -74,7 +73,7 @@ impl MediaData {
|
|||
&mut self,
|
||||
ctx: &serenity::client::Context,
|
||||
msg: &serenity::model::channel::Message,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<()> {
|
||||
self.playlist.clear();
|
||||
self.current_song = None;
|
||||
self.song_name = String::new();
|
||||
|
@ -124,11 +123,7 @@ impl MediaData {
|
|||
&mut self.song_name
|
||||
}
|
||||
|
||||
pub fn start_playing(
|
||||
ctx: &Context,
|
||||
mediadata: &mut MediaData,
|
||||
msg: &Message,
|
||||
) -> VerboseResult<()> {
|
||||
pub fn start_playing(ctx: &Context, mediadata: &mut MediaData, msg: &Message) -> Result<()> {
|
||||
// check if there is already playing
|
||||
let already_started = mediadata.song().is_some();
|
||||
|
||||
|
@ -141,7 +136,7 @@ impl MediaData {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn check_for_next(&mut self, ctx: &Context, msg: &Message) -> VerboseResult<String> {
|
||||
fn check_for_next(&mut self, ctx: &Context, msg: &Message) -> Result<String> {
|
||||
println!("check for next");
|
||||
|
||||
while !self.playlist().is_empty() {
|
||||
|
@ -158,7 +153,7 @@ impl MediaData {
|
|||
&first
|
||||
),
|
||||
)
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
.map_err(|err| anyhow!("{}", err))?;
|
||||
|
||||
let sql = self.db();
|
||||
|
||||
|
@ -166,19 +161,19 @@ impl MediaData {
|
|||
let mut stmt =
|
||||
match sql.prepare("SELECT name FROM sqlite_master WHERE type='table'") {
|
||||
Ok(statement) => statement,
|
||||
Err(_) => create_error!("failed preparing data base access"),
|
||||
Err(_) => return Err(anyhow!("failed preparing data base access")),
|
||||
};
|
||||
|
||||
let rows =
|
||||
match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>) {
|
||||
Ok(rows) => rows,
|
||||
Err(_) => create_error!("failed querying rows"),
|
||||
Err(_) => return Err(anyhow!("failed querying rows")),
|
||||
};
|
||||
|
||||
for row in rows {
|
||||
let table_name = match row {
|
||||
Ok(name) => name,
|
||||
Err(_) => create_error!("failed getting name from row"),
|
||||
Err(_) => return Err(anyhow!("failed getting name from row")),
|
||||
};
|
||||
|
||||
if let Err(_) = sql.execute(
|
||||
|
@ -194,14 +189,14 @@ impl MediaData {
|
|||
}
|
||||
|
||||
println!("no song found!");
|
||||
create_error!("no suitable song found!")
|
||||
Err(anyhow!("no suitable song found!"))
|
||||
}
|
||||
|
||||
fn check_for_channel<T: RawMutex>(
|
||||
manager: &mut MutexGuard<T, ClientVoiceManager>,
|
||||
ctx: &Context,
|
||||
msg: &Message,
|
||||
) -> VerboseResult<()> {
|
||||
) -> Result<()> {
|
||||
println!("check for channel!");
|
||||
|
||||
let guild = guild(ctx, msg)?;
|
||||
|
@ -216,7 +211,7 @@ impl MediaData {
|
|||
.and_then(|voice_state| voice_state.channel_id)
|
||||
{
|
||||
Some(channel) => channel,
|
||||
None => create_error!("author is not in a voice channel!"),
|
||||
None => return Err(anyhow!("author is not in a voice channel!")),
|
||||
};
|
||||
|
||||
println!("got author channel");
|
||||
|
@ -238,7 +233,7 @@ impl MediaData {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn next_song(ctx: &Context, mediadata: &mut MediaData, msg: &Message) -> VerboseResult<()> {
|
||||
pub fn next_song(ctx: &Context, mediadata: &mut MediaData, msg: &Message) -> Result<()> {
|
||||
println!("start next song");
|
||||
let voice_manager = mediadata.voice_manager.clone();
|
||||
let mut manager = voice_manager.lock();
|
||||
|
@ -269,7 +264,7 @@ impl MediaData {
|
|||
Some(handler) => handler,
|
||||
None => {
|
||||
println!("failed getting handler");
|
||||
create_error!("error getting handler");
|
||||
return Err(anyhow!("error getting handler"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -278,7 +273,7 @@ impl MediaData {
|
|||
|
||||
let source = match ffmpeg(first.clone()) {
|
||||
Ok(mpeg) => mpeg,
|
||||
Err(_) => create_error!(format!("failed loading: {}", &first)),
|
||||
Err(_) => return Err(anyhow!(format!("failed loading: {}", &first))),
|
||||
};
|
||||
|
||||
handler.stop();
|
||||
|
@ -295,7 +290,7 @@ impl MediaData {
|
|||
|
||||
msg.channel_id
|
||||
.say(&ctx.http, format!("Playing song: {}", first))
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
.map_err(|err| anyhow!("{}", err))?;
|
||||
}
|
||||
|
||||
if need_to_leave {
|
||||
|
|
|
@ -8,14 +8,14 @@ use serenity::voice::Handler;
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use utilities::prelude::*;
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
// This imports `typemap`'s `Key` as `TypeMapKey`.
|
||||
use serenity::prelude::*;
|
||||
|
||||
use super::prelude::*;
|
||||
|
||||
pub fn guild(ctx: &Context, msg: &Message) -> Result<Arc<SerRwLock<Guild>>, String> {
|
||||
pub fn guild(ctx: &Context, msg: &Message) -> Result<Arc<SerRwLock<Guild>>> {
|
||||
match msg.guild(&ctx.cache) {
|
||||
Some(guild) => Ok(guild),
|
||||
None => {
|
||||
|
@ -25,12 +25,12 @@ pub fn guild(ctx: &Context, msg: &Message) -> Result<Arc<SerRwLock<Guild>>, Stri
|
|||
.is_err()
|
||||
{}
|
||||
|
||||
Err("failed getting Guild".to_string())
|
||||
Err(anyhow!("failed getting Guild"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn guild_id(ctx: &Context, msg: &Message) -> Result<GuildId, String> {
|
||||
pub fn guild_id(ctx: &Context, msg: &Message) -> Result<GuildId> {
|
||||
let guild = guild(ctx, msg)?;
|
||||
let guild_read = guild.read();
|
||||
|
||||
|
@ -47,7 +47,7 @@ pub fn handler<'a, T: RawMutex>(
|
|||
pub fn channel_contains_author(
|
||||
ctx: &mut serenity::client::Context,
|
||||
msg: &serenity::model::channel::Message,
|
||||
) -> VerboseResult<()> {
|
||||
) -> Result<()> {
|
||||
let guild = guild(ctx, msg)?;
|
||||
let guild_id = guild.read().id;
|
||||
|
||||
|
@ -58,7 +58,7 @@ pub fn channel_contains_author(
|
|||
.and_then(|voice_state| voice_state.channel_id)
|
||||
{
|
||||
Some(channel) => channel,
|
||||
None => create_error!("author is not in a voice channel!"),
|
||||
None => return Err(anyhow!("author is not in a voice channel!")),
|
||||
};
|
||||
|
||||
if let Some(media) = ctx.data.read().get::<Media>() {
|
||||
|
@ -69,7 +69,9 @@ pub fn channel_contains_author(
|
|||
// check if the bot is in a channel
|
||||
if let Some(bot_channel_id) = handler.channel_id {
|
||||
if bot_channel_id != author_channel_id {
|
||||
create_error!("author is not in the same voice channel as the bot!");
|
||||
return Err(anyhow!(
|
||||
"author is not in the same voice channel as the bot!"
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@ fn convert_output(out: &Output) -> Result<Vec<String>, String> {
|
|||
let file_name = line.split_off(FIRST_LOAD_PREFIX.len());
|
||||
files.push(file_name.trim().to_string());
|
||||
} else if line.ends_with(RELOAD_SUFFIX) {
|
||||
line.split_off(line_len - RELOAD_SUFFIX.len());
|
||||
line.truncate(line_len - RELOAD_SUFFIX.len());
|
||||
let file_name = line.split_off(PREFIX.len());
|
||||
files.push(file_name.trim().to_string());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue