Get voices working again!
This commit is contained in:
parent
c329a2f387
commit
1d5b44128b
117
Cargo.lock
generated
117
Cargo.lock
generated
@ -1002,6 +1002,12 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "extended"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@ -1098,6 +1104,7 @@ dependencies = [
|
|||||||
"sha3",
|
"sha3",
|
||||||
"songbird",
|
"songbird",
|
||||||
"structopt",
|
"structopt",
|
||||||
|
"symphonia",
|
||||||
"tera",
|
"tera",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tonic",
|
"tonic",
|
||||||
@ -3885,8 +3892,71 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
|
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"symphonia-bundle-flac",
|
||||||
|
"symphonia-bundle-mp3",
|
||||||
|
"symphonia-codec-adpcm",
|
||||||
|
"symphonia-codec-pcm",
|
||||||
|
"symphonia-codec-vorbis",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-format-mkv",
|
||||||
|
"symphonia-format-ogg",
|
||||||
|
"symphonia-format-riff",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-bundle-flac"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
"symphonia-metadata",
|
"symphonia-metadata",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-bundle-mp3"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-adpcm"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-pcm"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-vorbis"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3902,6 +3972,43 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-mkv"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-ogg"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-riff"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50"
|
||||||
|
dependencies = [
|
||||||
|
"extended",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-metadata"
|
name = "symphonia-metadata"
|
||||||
version = "0.5.4"
|
version = "0.5.4"
|
||||||
@ -3914,6 +4021,16 @@ dependencies = [
|
|||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-utils-xiph"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe"
|
||||||
|
dependencies = [
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
|
|||||||
@ -15,7 +15,6 @@ tera = "1.19.1"
|
|||||||
ndm = "0.9.10"
|
ndm = "0.9.10"
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
magick_rust = "1.0.0"
|
magick_rust = "1.0.0"
|
||||||
songbird = "0.5.0"
|
|
||||||
json = "0.12.4"
|
json = "0.12.4"
|
||||||
axum = "0.8.1"
|
axum = "0.8.1"
|
||||||
sha3 = "0.10.8"
|
sha3 = "0.10.8"
|
||||||
@ -35,3 +34,11 @@ log = "0.4.26"
|
|||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1.35.1"
|
version = "1.35.1"
|
||||||
features = ["macros", "rt-multi-thread"]
|
features = ["macros", "rt-multi-thread"]
|
||||||
|
|
||||||
|
[dependencies.songbird]
|
||||||
|
version = "0.5.0"
|
||||||
|
features = ["builtin-queue"]
|
||||||
|
|
||||||
|
[dependencies.symphonia]
|
||||||
|
version = "0.5"
|
||||||
|
features = ["mp3", "wav"]
|
||||||
|
|||||||
@ -58,14 +58,12 @@ impl BotConfig {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BotState {
|
pub struct BotState {
|
||||||
pub accepted_nsfw: Option<UserId>,
|
pub accepted_nsfw: Option<UserId>,
|
||||||
pub speak_lock: Mutex<()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BotState {
|
impl BotState {
|
||||||
pub async fn new() -> Result<Self, Error> {
|
pub async fn new() -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
accepted_nsfw: None,
|
accepted_nsfw: None,
|
||||||
speak_lock: Mutex::new(()),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,6 +74,7 @@ pub struct GlobalData {
|
|||||||
pub bot_state: Mutex<BotState>,
|
pub bot_state: Mutex<BotState>,
|
||||||
pub db: Database,
|
pub db: Database,
|
||||||
pub picox: AlbumManager,
|
pub picox: AlbumManager,
|
||||||
|
pub speak_lock: Mutex<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalData {
|
impl GlobalData {
|
||||||
@ -100,6 +99,7 @@ impl GlobalData {
|
|||||||
db,
|
db,
|
||||||
cfg: cfg.clone(),
|
cfg: cfg.clone(),
|
||||||
picox: AlbumManager::new(cfg.picox.api_base_url, &cfg.picox.token),
|
picox: AlbumManager::new(cfg.picox.api_base_url, &cfg.picox.token),
|
||||||
|
speak_lock: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ mod joke;
|
|||||||
mod little_fren;
|
mod little_fren;
|
||||||
mod motivate;
|
mod motivate;
|
||||||
pub(crate) mod shop;
|
pub(crate) mod shop;
|
||||||
|
pub(crate) mod voices;
|
||||||
|
|
||||||
use crate::config::GlobalData;
|
use crate::config::GlobalData;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
@ -24,6 +25,7 @@ use poise::serenity_prelude::{GuildId, Http, Message, ReactionType, RoleId};
|
|||||||
use poise::{find_command, serenity_prelude as serenity, FrameworkOptions};
|
use poise::{find_command, serenity_prelude as serenity, FrameworkOptions};
|
||||||
use rand::prelude::IteratorRandom;
|
use rand::prelude::IteratorRandom;
|
||||||
use rand::rng;
|
use rand::rng;
|
||||||
|
use songbird::SerenityInit;
|
||||||
|
|
||||||
pub type Context<'a> = poise::Context<'a, Arc<GlobalData>, Error>;
|
pub type Context<'a> = poise::Context<'a, Arc<GlobalData>, Error>;
|
||||||
|
|
||||||
@ -207,6 +209,9 @@ pub async fn run_bot(global_data: GlobalData) {
|
|||||||
shop::sell_item(),
|
shop::sell_item(),
|
||||||
shop::shop(),
|
shop::shop(),
|
||||||
shop::use_item(),
|
shop::use_item(),
|
||||||
|
voices::list_voices(),
|
||||||
|
voices::list_words(),
|
||||||
|
voices::say(),
|
||||||
],
|
],
|
||||||
event_handler: |ctx, event, framework, data| {
|
event_handler: |ctx, event, framework, data| {
|
||||||
Box::pin(event_handler(ctx, event, framework, data))
|
Box::pin(event_handler(ctx, event, framework, data))
|
||||||
@ -234,6 +239,7 @@ pub async fn run_bot(global_data: GlobalData) {
|
|||||||
|
|
||||||
let mut client = serenity::ClientBuilder::new(token, intents)
|
let mut client = serenity::ClientBuilder::new(token, intents)
|
||||||
.framework(framework)
|
.framework(framework)
|
||||||
|
.register_songbird()
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,21 @@
|
|||||||
use crate::{command, group, GlobalData};
|
use crate::discord::Context;
|
||||||
use serenity::all::CreateAttachment;
|
use crate::error::Error;
|
||||||
use serenity::builder::CreateMessage;
|
use magick_rust::bindings::wchar_t;
|
||||||
use serenity::client::Context;
|
use poise::async_trait;
|
||||||
use serenity::framework::standard::{Args, CommandResult};
|
use poise::serenity_prelude::all::CreateAttachment;
|
||||||
use serenity::model::channel::Message;
|
use poise::serenity_prelude::builder::CreateMessage;
|
||||||
use serenity::model::id::UserId;
|
use poise::serenity_prelude::model::channel::Message;
|
||||||
use serenity::model::prelude::GuildId;
|
use poise::serenity_prelude::model::id::UserId;
|
||||||
use serenity::utils::MessageBuilder;
|
use poise::serenity_prelude::model::prelude::GuildId;
|
||||||
|
use poise::serenity_prelude::utils::MessageBuilder;
|
||||||
use songbird::driver::Bitrate;
|
use songbird::driver::Bitrate;
|
||||||
use songbird::input;
|
|
||||||
use songbird::input::cached::Compressed;
|
use songbird::input::cached::Compressed;
|
||||||
|
use songbird::{input, Event, EventContext, EventHandler, Songbird, TrackEvent};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::sync::Arc;
|
||||||
#[group]
|
|
||||||
#[commands(say, list_words, list_voices)]
|
|
||||||
pub struct Voices;
|
|
||||||
|
|
||||||
async fn get_voice_dictionary(path: &Path) -> Result<HashMap<String, PathBuf>, tokio::io::Error> {
|
async fn get_voice_dictionary(path: &Path) -> Result<HashMap<String, PathBuf>, tokio::io::Error> {
|
||||||
let mut dir = tokio::fs::read_dir(path).await?;
|
let mut dir = tokio::fs::read_dir(path).await?;
|
||||||
@ -85,7 +83,7 @@ pub enum VoiceError {
|
|||||||
VoiceNotFound(String),
|
VoiceNotFound(String),
|
||||||
WordNotFound(String),
|
WordNotFound(String),
|
||||||
NotInVoiceChannel,
|
NotInVoiceChannel,
|
||||||
Serenity(serenity::Error),
|
Serenity(poise::serenity_prelude::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for VoiceError {
|
impl Display for VoiceError {
|
||||||
@ -99,30 +97,44 @@ impl Display for VoiceError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<serenity::Error> for VoiceError {
|
impl From<poise::serenity_prelude::Error> for VoiceError {
|
||||||
fn from(value: serenity::Error) -> Self {
|
fn from(value: poise::serenity_prelude::Error) -> Self {
|
||||||
Self::Serenity(value)
|
Self::Serenity(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for VoiceError {}
|
impl std::error::Error for VoiceError {}
|
||||||
|
|
||||||
|
struct LeaveHandler {
|
||||||
|
guild: GuildId,
|
||||||
|
manager: Arc<Songbird>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl EventHandler for LeaveHandler {
|
||||||
|
async fn act(&self, ctx: &EventContext<'_>) -> Option<Event> {
|
||||||
|
if let EventContext::Track(_track) = ctx {
|
||||||
|
let has_handler = self.manager.get(self.guild).is_some();
|
||||||
|
|
||||||
|
if has_handler {
|
||||||
|
let _ = self.manager.remove(self.guild).await.is_ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn speak(
|
pub async fn speak(
|
||||||
ctx: &Context,
|
ctx: Context<'_>,
|
||||||
guild_id: GuildId,
|
guild_id: GuildId,
|
||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
voice: &str,
|
voice: &str,
|
||||||
phrase: &str,
|
phrase: &str,
|
||||||
) -> Result<(), VoiceError> {
|
) -> Result<(), VoiceError> {
|
||||||
let data = ctx.data.read().await;
|
let _ = ctx.data().speak_lock.lock();
|
||||||
let global_data = data.get::<GlobalData>().unwrap();
|
|
||||||
|
|
||||||
let _ = global_data.bot_state.speak_lock.lock().await;
|
let voice_path = match find_voice(&ctx.data().cfg.voice_path, voice).await.unwrap() {
|
||||||
|
|
||||||
let voice_path = match find_voice(&global_data.cfg.voice_path, voice)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
{
|
|
||||||
None => return Err(VoiceError::VoiceNotFound(voice.to_string())),
|
None => return Err(VoiceError::VoiceNotFound(voice.to_string())),
|
||||||
Some(voice_path) => voice_path,
|
Some(voice_path) => voice_path,
|
||||||
};
|
};
|
||||||
@ -160,7 +172,7 @@ pub async fn speak(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let channel_id = {
|
let channel_id = {
|
||||||
let guild = ctx.cache.guild(guild_id).unwrap();
|
let guild = ctx.cache().guild(guild_id).unwrap();
|
||||||
|
|
||||||
let channel_id = guild
|
let channel_id = guild
|
||||||
.voice_states
|
.voice_states
|
||||||
@ -177,7 +189,7 @@ pub async fn speak(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let manager = songbird::get(ctx)
|
let manager = songbird::get(ctx.serenity_context())
|
||||||
.await
|
.await
|
||||||
.expect("Songbird not initialized")
|
.expect("Songbird not initialized")
|
||||||
.clone();
|
.clone();
|
||||||
@ -186,8 +198,8 @@ pub async fn speak(
|
|||||||
|
|
||||||
if let Ok(handler_lock) = handler_lock {
|
if let Ok(handler_lock) = handler_lock {
|
||||||
let mut handler = handler_lock.lock().await;
|
let mut handler = handler_lock.lock().await;
|
||||||
for word in sentence {
|
for (ndx, word) in sentence.iter().enumerate() {
|
||||||
let word_path = dict.get(&word).cloned().unwrap();
|
let word_path = dict.get(word).cloned().unwrap();
|
||||||
|
|
||||||
let src = input::File::new(word_path);
|
let src = input::File::new(word_path);
|
||||||
|
|
||||||
@ -197,34 +209,44 @@ pub async fn speak(
|
|||||||
|
|
||||||
let _ = audio_src.raw.spawn_loader();
|
let _ = audio_src.raw.spawn_loader();
|
||||||
|
|
||||||
let voice = handler.play_input(audio_src.into());
|
let handle = handler.enqueue_input(audio_src.into()).await;
|
||||||
voice.set_volume(0.5).unwrap();
|
handle.set_volume(0.50).unwrap();
|
||||||
|
|
||||||
//tokio::time::sleep(duration).await;
|
if ndx == sentence.len() - 1 {
|
||||||
|
// add task to disconnect bot
|
||||||
|
|
||||||
|
handle
|
||||||
|
.add_event(
|
||||||
|
Event::Track(TrackEvent::End),
|
||||||
|
LeaveHandler {
|
||||||
|
guild: ctx.guild_id().unwrap(),
|
||||||
|
manager: manager.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.leave().await.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[poise::command(prefix_command, category = "Voice", guild_only)]
|
||||||
#[only_in(guilds)]
|
pub async fn say(
|
||||||
#[min_args(1)]
|
ctx: Context<'_>,
|
||||||
async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
#[description = "Voice to use"] voice: String,
|
||||||
let guild_id = msg.guild_id.unwrap();
|
#[description = "message to say"]
|
||||||
|
#[rest]
|
||||||
|
phrase: String,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let guild_id = ctx.guild_id().unwrap();
|
||||||
|
|
||||||
let voice = args.parse::<String>()?;
|
if let Err(err) = speak(ctx, guild_id, ctx.author().id, &voice, &phrase).await {
|
||||||
args.advance();
|
|
||||||
let phrase = args.rest();
|
|
||||||
|
|
||||||
if let Err(err) = speak(ctx, guild_id, msg.author.id, &voice, phrase).await {
|
|
||||||
match err {
|
match err {
|
||||||
VoiceError::VoiceNotFound(_)
|
VoiceError::VoiceNotFound(_)
|
||||||
| VoiceError::WordNotFound(_)
|
| VoiceError::WordNotFound(_)
|
||||||
| VoiceError::NotInVoiceChannel => {
|
| VoiceError::NotInVoiceChannel => {
|
||||||
msg.reply(&ctx.http, format!("Error: {}", err)).await?;
|
ctx.reply(format!("Error: {}", err)).await?;
|
||||||
}
|
}
|
||||||
_ => return Err(err.into()),
|
_ => return Err(err.into()),
|
||||||
}
|
}
|
||||||
@ -233,18 +255,14 @@ async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[poise::command(prefix_command, category = "Voice", guild_only)]
|
||||||
#[only_in(guilds)]
|
pub async fn list_words(
|
||||||
#[min_args(1)]
|
ctx: Context<'_>,
|
||||||
async fn list_words(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
#[description = "Get all words for this voice"] voice: String,
|
||||||
let data = ctx.data.read().await;
|
) -> Result<(), Error> {
|
||||||
let global_data = data.get::<GlobalData>().unwrap();
|
match find_voice(&ctx.data().cfg.voice_path, &voice).await? {
|
||||||
|
|
||||||
let voice = args.parse::<String>().unwrap();
|
|
||||||
|
|
||||||
match find_voice(&global_data.cfg.voice_path, &voice).await? {
|
|
||||||
None => {
|
None => {
|
||||||
msg.reply(&ctx.http, format!("No voice found called '{}'", voice))
|
ctx.reply(format!("No voice found called '{}'", voice))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
Some(voice_path) => {
|
Some(voice_path) => {
|
||||||
@ -265,9 +283,9 @@ async fn list_words(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
let file_data = file_data.as_bytes();
|
let file_data = file_data.as_bytes();
|
||||||
let file_data = Cow::from(file_data);
|
let file_data = Cow::from(file_data);
|
||||||
|
|
||||||
msg.channel_id
|
ctx.channel_id()
|
||||||
.send_message(
|
.send_message(
|
||||||
&ctx.http,
|
&ctx,
|
||||||
CreateMessage::new()
|
CreateMessage::new()
|
||||||
.add_file(CreateAttachment::bytes(file_data, "words.txt".to_string())),
|
.add_file(CreateAttachment::bytes(file_data, "words.txt".to_string())),
|
||||||
)
|
)
|
||||||
@ -278,20 +296,16 @@ async fn list_words(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[poise::command(prefix_command, category = "Voice", guild_only)]
|
||||||
#[only_in(guilds)]
|
pub async fn list_voices(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
async fn list_voices(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
|
||||||
let data = ctx.data.read().await;
|
|
||||||
let global_data = data.get::<GlobalData>().unwrap();
|
|
||||||
|
|
||||||
let mut voice_message = MessageBuilder::new();
|
let mut voice_message = MessageBuilder::new();
|
||||||
|
|
||||||
for voice in get_voices(&global_data.cfg.voice_path).await? {
|
for voice in get_voices(&ctx.data().cfg.voice_path).await? {
|
||||||
voice_message.push("* ");
|
voice_message.push("* ");
|
||||||
voice_message.push_line(voice);
|
voice_message.push_line(voice);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.reply(&ctx.http, voice_message.build()).await?;
|
ctx.reply(voice_message.build()).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::discord::voices::VoiceError;
|
||||||
use crate::user;
|
use crate::user;
|
||||||
use magick_rust::MagickError;
|
use magick_rust::MagickError;
|
||||||
use serde::ser::StdError;
|
use serde::ser::StdError;
|
||||||
@ -19,6 +20,7 @@ pub enum Error {
|
|||||||
MagickError(magick_rust::MagickError),
|
MagickError(magick_rust::MagickError),
|
||||||
CommandError(String),
|
CommandError(String),
|
||||||
IoError(std::io::Error),
|
IoError(std::io::Error),
|
||||||
|
VoiceError(VoiceError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdError for Error {}
|
impl StdError for Error {}
|
||||||
@ -71,6 +73,12 @@ impl From<std::io::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<VoiceError> for Error {
|
||||||
|
fn from(value: VoiceError) -> Self {
|
||||||
|
Self::VoiceError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@ -86,6 +94,7 @@ impl Display for Error {
|
|||||||
Error::MagickError(err) => write!(f, "ImageMagick error: {}", err),
|
Error::MagickError(err) => write!(f, "ImageMagick error: {}", err),
|
||||||
Error::CommandError(err_msg) => write!(f, "{}", err_msg),
|
Error::CommandError(err_msg) => write!(f, "{}", err_msg),
|
||||||
Error::IoError(err) => write!(f, "IO Error: {}", err),
|
Error::IoError(err) => write!(f, "IO Error: {}", err),
|
||||||
|
Error::VoiceError(err) => write!(f, "Voice error: {}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user