Added bot api
+ Right now can just play voices + Added commands to add api keys + clippy + fmt
This commit is contained in:
+32
-1
@@ -1,4 +1,5 @@
|
||||
use crate::config::BotConfig;
|
||||
use crate::models::api_key::Apikey;
|
||||
use crate::{command, group, GlobalData};
|
||||
use json::JsonValue;
|
||||
use serenity::client::Context;
|
||||
@@ -8,7 +9,7 @@ use serenity::model::prelude::UserId;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[group]
|
||||
#[commands(reload, dump_db, load_db)]
|
||||
#[commands(reload, dump_db, load_db, add_key)]
|
||||
pub struct ADMIN;
|
||||
|
||||
pub fn is_admin(user_id: &UserId, cfg: &BotConfig) -> bool {
|
||||
@@ -96,3 +97,33 @@ async fn load_db(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn add_key(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
let mut data = ctx.data.write().await;
|
||||
let global_data = data.get_mut::<GlobalData>().unwrap();
|
||||
|
||||
if !is_admin(&msg.author.id, &global_data.cfg) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (api_key, key) = if args.len() == 1 {
|
||||
let user_id = args.parse::<UserId>()?;
|
||||
let user = user_id.to_user(&ctx.http).await?;
|
||||
Apikey::new(&format!("{}'s Key", user.name), Some(user_id))
|
||||
} else {
|
||||
Apikey::new(&format!("{}'s Key", msg.author.name), Some(msg.author.id))
|
||||
};
|
||||
|
||||
global_data.db.insert::<Apikey>(api_key.clone())?;
|
||||
|
||||
let dm = msg.author.create_dm_channel(&ctx.http).await?;
|
||||
|
||||
dm.say(
|
||||
&ctx.http,
|
||||
format!("Key '{}' added. Api Key: {}", api_key.name, key),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ pub mod shop;
|
||||
pub mod story;
|
||||
pub mod voices;
|
||||
|
||||
use crate::api::web_server;
|
||||
use crate::discord::fren_coin::give_coin;
|
||||
use crate::discord::joke::random;
|
||||
use crate::discord::shop::restock_shop;
|
||||
@@ -126,6 +127,8 @@ impl EventHandler for Handler {
|
||||
OnlineStatus::Online,
|
||||
)
|
||||
.await;
|
||||
|
||||
tokio::spawn(async move { web_server(ctx).await });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+83
-37
@@ -2,12 +2,15 @@ use crate::{command, group, GlobalData};
|
||||
use serenity::client::Context;
|
||||
use serenity::framework::standard::{Args, CommandResult};
|
||||
use serenity::model::channel::{AttachmentType, Message};
|
||||
use serenity::model::id::UserId;
|
||||
use serenity::model::prelude::GuildId;
|
||||
use serenity::utils::MessageBuilder;
|
||||
use songbird::driver::Bitrate;
|
||||
use songbird::input;
|
||||
use songbird::input::cached::Compressed;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[group]
|
||||
@@ -75,33 +78,58 @@ async fn find_voice(voice_path: &Path, name: &str) -> Result<Option<PathBuf>, to
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[only_in(guilds)]
|
||||
#[min_args(1)]
|
||||
async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
let guild = msg.guild(&ctx.cache).unwrap();
|
||||
let guild_id = guild.id;
|
||||
#[derive(Debug)]
|
||||
pub enum VoiceError {
|
||||
VoiceNotFound(String),
|
||||
WordNotFound(String),
|
||||
NotInVoiceChannel,
|
||||
Serenity(serenity::Error),
|
||||
}
|
||||
|
||||
impl Display for VoiceError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
VoiceError::VoiceNotFound(v) => write!(f, "{} voice not found", v),
|
||||
VoiceError::WordNotFound(w) => write!(f, "{} is not in dictionary", w),
|
||||
VoiceError::Serenity(err) => write!(f, "Serenity error: {}", err),
|
||||
VoiceError::NotInVoiceChannel => write!(f, "User not in voice channel"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serenity::Error> for VoiceError {
|
||||
fn from(value: serenity::Error) -> Self {
|
||||
Self::Serenity(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for VoiceError {}
|
||||
|
||||
pub async fn speak(
|
||||
ctx: &Context,
|
||||
guild_id: GuildId,
|
||||
user_id: UserId,
|
||||
voice: &str,
|
||||
phrase: &str,
|
||||
) -> Result<(), VoiceError> {
|
||||
let data = ctx.data.read().await;
|
||||
let global_data = data.get::<GlobalData>().unwrap();
|
||||
|
||||
let voice = args.parse::<String>().unwrap();
|
||||
let _ = global_data.bot_state.speak_lock.lock().await;
|
||||
|
||||
let voice_path = match find_voice(&global_data.cfg.voice_path, &voice).await? {
|
||||
None => {
|
||||
msg.reply(&ctx.http, format!("No voice found called '{}'", voice))
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
let voice_path = match find_voice(&global_data.cfg.voice_path, voice)
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
None => return Err(VoiceError::VoiceNotFound(voice.to_string())),
|
||||
Some(voice_path) => voice_path,
|
||||
};
|
||||
|
||||
args.advance();
|
||||
let dict = get_voice_dictionary(&voice_path).await.unwrap();
|
||||
|
||||
let dict = get_voice_dictionary(&voice_path).await?;
|
||||
|
||||
let mut phrase = Vec::new();
|
||||
while let Some(word) = &args.current() {
|
||||
let mut sentence = Vec::new();
|
||||
for word in phrase.split(' ') {
|
||||
let word = word.to_lowercase();
|
||||
let mut add_period = false;
|
||||
let mut add_comma = false;
|
||||
let word = if word.ends_with(',') {
|
||||
@@ -115,38 +143,31 @@ async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
};
|
||||
|
||||
if dict.contains_key(&word) {
|
||||
phrase.push(word.to_string());
|
||||
sentence.push(word.to_string());
|
||||
} else {
|
||||
msg.reply(
|
||||
&ctx.http,
|
||||
format!("The word '{}' is not in the dictionary", word),
|
||||
)
|
||||
.await?;
|
||||
return Ok(());
|
||||
return Err(VoiceError::WordNotFound(word));
|
||||
}
|
||||
|
||||
if add_comma {
|
||||
phrase.push("_comma".to_string());
|
||||
sentence.push("_comma".to_string());
|
||||
}
|
||||
|
||||
if add_period {
|
||||
phrase.push("_period".to_string());
|
||||
sentence.push("_period".to_string());
|
||||
}
|
||||
|
||||
args.advance();
|
||||
}
|
||||
|
||||
let guild = guild_id.to_guild_cached(&ctx.cache).unwrap();
|
||||
|
||||
let channel_id = guild
|
||||
.voice_states
|
||||
.get(&msg.author.id)
|
||||
.get(&user_id)
|
||||
.and_then(|voice_state| voice_state.channel_id);
|
||||
|
||||
let connect_to = match channel_id {
|
||||
Some(channel) => channel,
|
||||
None => {
|
||||
msg.reply(ctx, "You are not in a voice channel").await?;
|
||||
|
||||
return Ok(());
|
||||
return Err(VoiceError::NotInVoiceChannel);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -157,11 +178,11 @@ async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
|
||||
let (handler_lock, success_reader) = manager.join(guild_id, connect_to).await;
|
||||
|
||||
success_reader?;
|
||||
success_reader.unwrap();
|
||||
|
||||
let mut handler = handler_lock.lock().await;
|
||||
|
||||
for word in phrase {
|
||||
for word in sentence {
|
||||
let word_path = dict.get(&word).unwrap();
|
||||
|
||||
let audio_src = Compressed::new(
|
||||
@@ -175,12 +196,37 @@ async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
|
||||
let duration = audio_src.metadata.duration.unwrap();
|
||||
let voice = handler.play_source(audio_src.into());
|
||||
voice.set_volume(0.5)?;
|
||||
voice.set_volume(0.5).unwrap();
|
||||
|
||||
tokio::time::sleep(duration).await;
|
||||
}
|
||||
|
||||
handler.leave().await?;
|
||||
handler.leave().await.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[only_in(guilds)]
|
||||
#[min_args(1)]
|
||||
async fn say(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
let guild = msg.guild(&ctx.cache).unwrap();
|
||||
let guild_id = guild.id;
|
||||
|
||||
let voice = args.parse::<String>()?;
|
||||
args.advance();
|
||||
let phrase = args.rest();
|
||||
|
||||
if let Err(err) = speak(ctx, guild_id, msg.author.id, &voice, phrase).await {
|
||||
match err {
|
||||
VoiceError::VoiceNotFound(_)
|
||||
| VoiceError::WordNotFound(_)
|
||||
| VoiceError::NotInVoiceChannel => {
|
||||
msg.reply(&ctx.http, format!("Error: {}", err)).await?;
|
||||
}
|
||||
_ => return Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user