restructured a lot. everything updated to poise.

This commit is contained in:
2022-01-26 20:33:51 +00:00
parent bb54c0d2c0
commit b350007dae
15 changed files with 775 additions and 757 deletions

View File

@ -1,4 +1,4 @@
use crate::{Context, Error, THEME_COLOR};
use crate::{consts::THEME_COLOR, Context, Error};
/// Get additional information about the bot
#[poise::command(slash_command, category = "Information")]

View File

@ -1,8 +1,14 @@
use std::time::Duration;
use poise::serenity::model::id::{GuildId, RoleId};
use tokio::fs::File;
use crate::{sound::Sound, Context, Error, MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE};
use crate::{
cmds::autocomplete_sound,
consts::{MAX_SOUNDS, PATREON_GUILD, PATREON_ROLE},
models::sound::{Sound, SoundCtx},
Context, Error,
};
/// Upload a new sound to the bot
#[poise::command(slash_command, rename = "upload", category = "Manage")]
@ -123,14 +129,16 @@ pub async fn upload_new_sound(
#[poise::command(slash_command, rename = "delete", category = "Manage")]
pub async fn delete_sound(
ctx: Context<'_>,
#[description = "Name or ID of sound to delete"] name: String,
#[description = "Name or ID of sound to delete"]
#[autocomplete = "autocomplete_sound"]
name: String,
) -> Result<(), Error> {
let pool = ctx.data().database.clone();
let uid = ctx.author().id.0;
let gid = ctx.guild_id().unwrap().0;
let sound_vec = Sound::search_for_sound(&name, gid, uid, pool.clone(), true).await?;
let sound_vec = ctx.data().search_for_sound(&name, gid, uid, true).await?;
let sound_result = sound_vec.first();
match sound_result {
@ -174,14 +182,16 @@ pub async fn delete_sound(
#[poise::command(slash_command, rename = "public", category = "Manage")]
pub async fn change_public(
ctx: Context<'_>,
#[description = "Name or ID of sound to change privacy setting of"] name: String,
#[description = "Name or ID of sound to change privacy setting of"]
#[autocomplete = "autocomplete_sound"]
name: String,
) -> Result<(), Error> {
let pool = ctx.data().database.clone();
let uid = ctx.author().id.0;
let gid = ctx.guild_id().unwrap().0;
let mut sound_vec = Sound::search_for_sound(&name, gid, uid, pool.clone(), true).await?;
let mut sound_vec = ctx.data().search_for_sound(&name, gid, uid, true).await?;
let sound_result = sound_vec.first_mut();
match sound_result {
@ -210,3 +220,39 @@ pub async fn change_public(
Ok(())
}
/// Download a sound file from the bot
#[poise::command(slash_command, rename = "download", category = "Manage")]
pub async fn download_file(
ctx: Context<'_>,
#[description = "Name or ID of sound to download"]
#[autocomplete = "autocomplete_sound"]
name: String,
) -> Result<(), Error> {
ctx.defer().await?;
let sound = ctx
.data()
.search_for_sound(&name, ctx.guild_id().unwrap(), ctx.author().id, true)
.await?;
match sound.first() {
Some(sound) => {
let source = sound
.store_sound_source(ctx.data().database.clone())
.await?;
let file = File::open(&source).await?;
let name = format!("{}-{}.opus", sound.id, sound.name);
ctx.send(|m| m.attachment((&file, name.as_str()).into()))
.await?;
}
None => {
ctx.say("No sound found by specified name/ID").await?;
}
}
Ok(())
}

View File

@ -1,6 +1,24 @@
use crate::{models::sound::SoundCtx, Context};
pub mod info;
pub mod manage;
pub mod play;
// pub mod search;
// pub mod settings;
// pub mod stop;
pub mod search;
pub mod settings;
pub mod stop;
pub async fn autocomplete_sound(
ctx: Context<'_>,
partial: String,
) -> Vec<poise::AutocompleteChoice<String>> {
ctx.data()
.autocomplete_user_sounds(&partial, ctx.author().id, ctx.guild_id().unwrap())
.await
.unwrap_or(vec![])
.iter()
.map(|s| poise::AutocompleteChoice {
name: s.name.clone(),
value: s.id.to_string(),
})
.collect()
}

View File

@ -2,32 +2,58 @@ use poise::serenity::{
builder::CreateActionRow, model::interactions::message_component::ButtonStyle,
};
use crate::{play_from_query, sound::Sound, Context, Error};
use crate::{
cmds::autocomplete_sound, models::sound::SoundCtx, utils::play_from_query, Context, Error,
};
/// Play a sound in your current voice channel
#[poise::command(slash_command)]
pub async fn play(
ctx: Context<'_>,
#[description = "Name or ID of sound to play"] name: String,
#[description = "Name or ID of sound to play"]
#[autocomplete = "autocomplete_sound"]
name: String,
) -> Result<(), Error> {
let guild = ctx.guild().unwrap();
ctx.say(play_from_query(&ctx, guild, ctx.author().id, &name, false).await)
.await?;
ctx.say(
play_from_query(
&ctx.discord(),
&ctx.data(),
guild,
ctx.author().id,
&name,
false,
)
.await,
)
.await?;
Ok(())
}
/// Loop a sound in your current voice channel
#[poise::command(slash_command)]
#[poise::command(slash_command, rename = "loop")]
pub async fn loop_play(
ctx: Context<'_>,
#[description = "Name or ID of sound to loop"] name: String,
#[description = "Name or ID of sound to loop"]
#[autocomplete = "autocomplete_sound"]
name: String,
) -> Result<(), Error> {
let guild = ctx.guild().unwrap();
ctx.say(play_from_query(&ctx, guild, ctx.author().id, &name, true).await)
.await?;
ctx.say(
play_from_query(
&ctx.discord(),
&ctx.data(),
guild,
ctx.author().id,
&name,
true,
)
.await,
)
.await?;
Ok(())
}
@ -36,36 +62,84 @@ pub async fn loop_play(
#[poise::command(slash_command, rename = "soundboard", category = "Play")]
pub async fn soundboard(
ctx: Context<'_>,
#[description = "Name or ID of sound for button 1"] sound_1: String,
#[description = "Name or ID of sound for button 2"] sound_2: Option<String>,
#[description = "Name or ID of sound for button 3"] sound_3: Option<String>,
#[description = "Name or ID of sound for button 4"] sound_4: Option<String>,
#[description = "Name or ID of sound for button 5"] sound_5: Option<String>,
#[description = "Name or ID of sound for button 6"] sound_6: Option<String>,
#[description = "Name or ID of sound for button 7"] sound_7: Option<String>,
#[description = "Name or ID of sound for button 8"] sound_8: Option<String>,
#[description = "Name or ID of sound for button 9"] sound_9: Option<String>,
#[description = "Name or ID of sound for button 10"] sound_10: Option<String>,
#[description = "Name or ID of sound for button 11"] sound_11: Option<String>,
#[description = "Name or ID of sound for button 12"] sound_12: Option<String>,
#[description = "Name or ID of sound for button 13"] sound_13: Option<String>,
#[description = "Name or ID of sound for button 14"] sound_14: Option<String>,
#[description = "Name or ID of sound for button 15"] sound_15: Option<String>,
#[description = "Name or ID of sound for button 16"] sound_16: Option<String>,
#[description = "Name or ID of sound for button 17"] sound_17: Option<String>,
#[description = "Name or ID of sound for button 18"] sound_18: Option<String>,
#[description = "Name or ID of sound for button 19"] sound_19: Option<String>,
#[description = "Name or ID of sound for button 20"] sound_20: Option<String>,
#[description = "Name or ID of sound for button 21"] sound_21: Option<String>,
#[description = "Name or ID of sound for button 22"] sound_22: Option<String>,
#[description = "Name or ID of sound for button 23"] sound_23: Option<String>,
#[description = "Name or ID of sound for button 24"] sound_24: Option<String>,
#[description = "Name or ID of sound for button 25"] sound_25: Option<String>,
#[description = "Name or ID of sound for button 1"]
#[autocomplete = "autocomplete_sound"]
sound_1: String,
#[description = "Name or ID of sound for button 2"]
#[autocomplete = "autocomplete_sound"]
sound_2: Option<String>,
#[description = "Name or ID of sound for button 3"]
#[autocomplete = "autocomplete_sound"]
sound_3: Option<String>,
#[description = "Name or ID of sound for button 4"]
#[autocomplete = "autocomplete_sound"]
sound_4: Option<String>,
#[description = "Name or ID of sound for button 5"]
#[autocomplete = "autocomplete_sound"]
sound_5: Option<String>,
#[description = "Name or ID of sound for button 6"]
#[autocomplete = "autocomplete_sound"]
sound_6: Option<String>,
#[description = "Name or ID of sound for button 7"]
#[autocomplete = "autocomplete_sound"]
sound_7: Option<String>,
#[description = "Name or ID of sound for button 8"]
#[autocomplete = "autocomplete_sound"]
sound_8: Option<String>,
#[description = "Name or ID of sound for button 9"]
#[autocomplete = "autocomplete_sound"]
sound_9: Option<String>,
#[description = "Name or ID of sound for button 10"]
#[autocomplete = "autocomplete_sound"]
sound_10: Option<String>,
#[description = "Name or ID of sound for button 11"]
#[autocomplete = "autocomplete_sound"]
sound_11: Option<String>,
#[description = "Name or ID of sound for button 12"]
#[autocomplete = "autocomplete_sound"]
sound_12: Option<String>,
#[description = "Name or ID of sound for button 13"]
#[autocomplete = "autocomplete_sound"]
sound_13: Option<String>,
#[description = "Name or ID of sound for button 14"]
#[autocomplete = "autocomplete_sound"]
sound_14: Option<String>,
#[description = "Name or ID of sound for button 15"]
#[autocomplete = "autocomplete_sound"]
sound_15: Option<String>,
#[description = "Name or ID of sound for button 16"]
#[autocomplete = "autocomplete_sound"]
sound_16: Option<String>,
#[description = "Name or ID of sound for button 17"]
#[autocomplete = "autocomplete_sound"]
sound_17: Option<String>,
#[description = "Name or ID of sound for button 18"]
#[autocomplete = "autocomplete_sound"]
sound_18: Option<String>,
#[description = "Name or ID of sound for button 19"]
#[autocomplete = "autocomplete_sound"]
sound_19: Option<String>,
#[description = "Name or ID of sound for button 20"]
#[autocomplete = "autocomplete_sound"]
sound_20: Option<String>,
#[description = "Name or ID of sound for button 21"]
#[autocomplete = "autocomplete_sound"]
sound_21: Option<String>,
#[description = "Name or ID of sound for button 22"]
#[autocomplete = "autocomplete_sound"]
sound_22: Option<String>,
#[description = "Name or ID of sound for button 23"]
#[autocomplete = "autocomplete_sound"]
sound_23: Option<String>,
#[description = "Name or ID of sound for button 24"]
#[autocomplete = "autocomplete_sound"]
sound_24: Option<String>,
#[description = "Name or ID of sound for button 25"]
#[autocomplete = "autocomplete_sound"]
sound_25: Option<String>,
) -> Result<(), Error> {
ctx.defer().await?;
let pool = ctx.data().database.clone();
let query_terms = [
Some(sound_1),
sound_2,
@ -97,14 +171,10 @@ pub async fn soundboard(
let mut sounds = vec![];
for sound in query_terms.iter().flatten() {
let search = Sound::search_for_sound(
&sound,
ctx.guild_id().unwrap(),
ctx.author().id,
pool.clone(),
true,
)
.await?;
let search = ctx
.data()
.search_for_sound(&sound, ctx.guild_id().unwrap(), ctx.author().id, true)
.await?;
if let Some(sound) = search.first() {
if !sounds.contains(sound) {

View File

@ -1,6 +1,13 @@
use crate::sound::Sound;
use poise::{serenity::constants::MESSAGE_CODE_LIMIT, CreateReply};
use crate::{
models::sound::{Sound, SoundCtx},
Context, Error,
};
fn format_search_results<'a>(search_results: Vec<Sound>) -> CreateReply<'a> {
let mut builder = CreateReply::default();
fn format_search_results(search_results: Vec<Sound>) -> CreateGenericResponse {
let mut current_character_count = 0;
let title = "Public sounds matching filter:";
@ -11,49 +18,25 @@ fn format_search_results(search_results: Vec<Sound>) -> CreateGenericResponse {
.filter(|item| {
current_character_count += item.0.len() + item.1.len();
current_character_count <= serenity::constants::MESSAGE_CODE_LIMIT - title.len()
current_character_count <= MESSAGE_CODE_LIMIT - title.len()
});
CreateGenericResponse::new().embed(|e| e.title(title).fields(field_iter))
builder.embed(|e| e.title(title).fields(field_iter));
builder
}
#[command("list")]
#[group("Search")]
#[description("Show the sounds uploaded by you or to your server")]
#[arg(
name = "me",
description = "Whether to list your sounds or server sounds (default: server)",
kind = "Boolean",
required = false
)]
#[example("`/list` - list sounds uploaded to the server you're in")]
#[example("`/list [me: True]` - list sounds you have uploaded across all servers")]
pub async fn list_sounds(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not get SQLPool from data");
/// Show the sounds uploaded to this server
#[poise::command(slash_command, rename = "list")]
pub async fn list_sounds(ctx: Context<'_>) -> Result<(), Error> {
let sounds;
let mut message_buffer;
if args.named("me").map(|i| i.to_owned()) == Some("me".to_string()) {
sounds = Sound::user_sounds(invoke.author_id(), pool).await?;
sounds = ctx.data().guild_sounds(ctx.guild_id().unwrap()).await?;
message_buffer = "All your sounds: ".to_string();
} else {
sounds = Sound::guild_sounds(invoke.guild_id().unwrap(), pool).await?;
message_buffer = "All sounds on this server: ".to_string();
}
message_buffer = "Sounds on this server: ".to_string();
// todo change this to iterator
for sound in sounds {
message_buffer.push_str(
format!(
@ -65,85 +48,77 @@ pub async fn list_sounds(
);
if message_buffer.len() > 2000 {
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(message_buffer),
)
.await?;
ctx.say(message_buffer).await?;
message_buffer = "".to_string();
}
}
if message_buffer.len() > 0 {
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(message_buffer),
)
.await?;
ctx.say(message_buffer).await?;
}
Ok(())
}
#[command("search")]
#[group("Search")]
#[description("Search for sounds")]
#[arg(
name = "query",
kind = "String",
description = "Sound name to search for",
required = true
)]
pub async fn search_sounds(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not get SQLPool from data");
/// Show all sounds you have uploaded
#[poise::command(slash_command, rename = "me")]
pub async fn list_user_sounds(ctx: Context<'_>) -> Result<(), Error> {
let sounds;
let mut message_buffer;
let query = args.named("query").unwrap();
sounds = ctx.data().user_sounds(ctx.author().id).await?;
let search_results = Sound::search_for_sound(
query,
invoke.guild_id().unwrap(),
invoke.author_id(),
pool,
false,
)
.await?;
message_buffer = "Sounds on this server: ".to_string();
invoke
.respond(ctx.http.clone(), format_search_results(search_results))
.await?;
// todo change this to iterator
for sound in sounds {
message_buffer.push_str(
format!(
"**{}** ({}), ",
sound.name,
if sound.public { "🔓" } else { "🔒" }
)
.as_str(),
);
if message_buffer.len() > 2000 {
ctx.say(message_buffer).await?;
message_buffer = "".to_string();
}
}
if message_buffer.len() > 0 {
ctx.say(message_buffer).await?;
}
Ok(())
}
#[command("random")]
#[group("Search")]
#[description("Show a page of random sounds")]
pub async fn show_random_sounds(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
_args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not get SQLPool from data");
/// Search for sounds
#[poise::command(slash_command, rename = "search", category = "Search")]
pub async fn search_sounds(
ctx: Context<'_>,
#[description = "Sound name to search for"] query: String,
) -> Result<(), Error> {
let search_results = ctx
.data()
.search_for_sound(&query, ctx.guild_id().unwrap(), ctx.author().id, false)
.await?;
ctx.send(|m| {
*m = format_search_results(search_results);
m
})
.await?;
Ok(())
}
/// Show a page of random sounds
#[poise::command(slash_command, rename = "random")]
pub async fn show_random_sounds(ctx: Context<'_>) -> Result<(), Error> {
let search_results = sqlx::query_as_unchecked!(
Sound,
"
@ -154,13 +129,14 @@ SELECT name, id, public, server_id, uploader_id
LIMIT 25
"
)
.fetch_all(&pool)
.await
.unwrap();
.fetch_all(&ctx.data().database)
.await?;
invoke
.respond(ctx.http.clone(), format_search_results(search_results))
.await?;
ctx.send(|m| {
*m = format_search_results(search_results);
m
})
.await?;
Ok(())
}

View File

@ -1,307 +1,126 @@
use regex_command_attr::command;
use serenity::{client::Context, framework::standard::CommandResult};
use crate::{
framework::{Args, CommandInvoke, CreateGenericResponse},
guild_data::CtxGuildData,
sound::{JoinSoundCtx, Sound},
MySQL,
models::{guild_data::CtxGuildData, join_sound::JoinSoundCtx, sound::SoundCtx},
Context, Error,
};
#[command("volume")]
#[aliases("vol")]
#[required_permissions(Managed)]
#[group("Settings")]
#[description("Change the bot's volume in this server")]
#[arg(
name = "volume",
description = "New volume for the bot to use",
kind = "Integer",
required = false
)]
#[example("`/volume` - check the volume on the current server")]
#[example("`/volume 100` - reset the volume on the current server")]
#[example("`/volume 10` - set the volume on the current server to 10%")]
/// Change the bot's volume in this server
#[poise::command(slash_command, rename = "volume")]
pub async fn change_volume(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not get SQLPool from data");
let guild_data_opt = ctx.guild_data(invoke.guild_id().unwrap()).await;
ctx: Context<'_>,
#[description = "New volume as a percentage"] volume: Option<usize>,
) -> Result<(), Error> {
let guild_data_opt = ctx.guild_data(ctx.guild_id().unwrap()).await;
let guild_data = guild_data_opt.unwrap();
if let Some(volume) = args.named("volume").map(|i| i.parse::<u8>().ok()).flatten() {
guild_data.write().await.volume = volume;
if let Some(volume) = volume {
guild_data.write().await.volume = volume as u8;
guild_data.read().await.commit(pool).await?;
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(format!("Volume changed to {}%", volume)),
)
guild_data
.read()
.await
.commit(ctx.data().database.clone())
.await?;
ctx.say(format!("Volume changed to {}%", volume)).await?;
} else {
let read = guild_data.read().await;
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(format!(
"Current server volume: {vol}%. Change the volume with `/volume <new volume>`",
vol = read.volume
)),
)
.await?;
}
Ok(())
}
#[command("prefix")]
#[required_permissions(Restricted)]
#[kind(Text)]
#[group("Settings")]
#[description("Change the prefix of the bot for using non-slash commands")]
#[arg(
name = "prefix",
kind = "String",
description = "The new prefix to use for the bot",
required = true
)]
pub async fn change_prefix(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not get SQLPool from data");
let guild_data;
{
let guild_data_opt = ctx.guild_data(invoke.guild_id().unwrap()).await;
guild_data = guild_data_opt.unwrap();
}
if let Some(prefix) = args.named("prefix") {
if prefix.len() <= 5 && !prefix.is_empty() {
let reply = format!("Prefix changed to `{}`", prefix);
{
guild_data.write().await.prefix = prefix.to_string();
}
{
let read = guild_data.read().await;
read.commit(pool).await?;
}
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(reply),
)
.await?;
} else {
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new()
.content("Prefix must be less than 5 characters long"),
)
.await?;
}
} else {
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(format!(
"Usage: `{prefix}prefix <new prefix>`",
prefix = guild_data.read().await.prefix
)),
)
.await?;
}
Ok(())
}
#[command("roles")]
#[required_permissions(Restricted)]
#[group("Settings")]
#[description("Change the role allowed to use the bot")]
#[arg(
name = "role",
kind = "Role",
description = "A role to allow to use the bot. Use @everyone to allow all server members",
required = true
)]
#[example("`/roles @everyone` - allow all server members to use the bot")]
#[example("`/roles @DJ` - allow only server members with the 'DJ' role to use the bot")]
pub async fn set_allowed_roles(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not get SQLPool from data");
let role_id = args.named("role").unwrap().parse::<u64>().unwrap();
let guild_data = ctx.guild_data(invoke.guild_id().unwrap()).await.unwrap();
guild_data.write().await.allowed_role = Some(role_id);
guild_data.read().await.commit(pool).await?;
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(format!("Allowed role set to <@&{}>", role_id)),
)
ctx.say(format!(
"Current server volume: {vol}%. Change the volume with `/volume <new volume>`",
vol = read.volume
))
.await?;
}
Ok(())
}
#[command("greet")]
#[group("Settings")]
#[description("Set a join sound")]
#[arg(
name = "query",
kind = "String",
description = "Name or ID of sound to set as your greet sound",
required = false
)]
#[example("`/greet` - remove your join sound")]
#[example("`/greet 1523` - set your join sound to sound with ID 1523")]
/// Manage greet sounds on this server
#[poise::command(slash_command, rename = "greet")]
pub async fn greet_sound(_ctx: Context<'_>) -> Result<(), Error> {
Ok(())
}
/// Set a join sound
#[poise::command(slash_command, rename = "set")]
pub async fn set_greet_sound(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not get SQLPool from data");
let query = args
.named("query")
.map(|s| s.to_owned())
.unwrap_or(String::new());
let user_id = invoke.author_id();
if query.len() == 0 {
ctx.update_join_sound(user_id, None).await;
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content("Your greet sound has been unset."),
)
.await?;
} else {
let sound_vec = Sound::search_for_sound(
&query,
invoke.guild_id().unwrap(),
user_id,
pool.clone(),
true,
)
ctx: Context<'_>,
#[description = "Name or ID of sound to set as your join sound"] name: String,
) -> Result<(), Error> {
let sound_vec = ctx
.data()
.search_for_sound(&name, ctx.guild_id().unwrap(), ctx.author().id, true)
.await?;
match sound_vec.first() {
Some(sound) => {
ctx.update_join_sound(user_id, Some(sound.id)).await;
match sound_vec.first() {
Some(sound) => {
ctx.data()
.update_join_sound(ctx.author().id, Some(sound.id))
.await;
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(format!(
"Greet sound has been set to {} (ID {})",
sound.name, sound.id
)),
)
.await?;
}
ctx.say(format!(
"Greet sound has been set to {} (ID {})",
sound.name, sound.id
))
.await?;
}
None => {
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new()
.content("Could not find a sound by that name."),
)
.await?;
}
None => {
ctx.say("Could not find a sound by that name.").await?;
}
}
Ok(())
}
#[command("allow_greet")]
#[group("Settings")]
#[description("Configure whether users should be able to use join sounds")]
#[required_permissions(Restricted)]
#[example("`/allow_greet` - disable greet sounds in the server")]
#[example("`/allow_greet` - re-enable greet sounds in the server")]
pub async fn allow_greet_sounds(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
_args: Args,
) -> CommandResult {
let pool = ctx
.data
.read()
.await
.get::<MySQL>()
.cloned()
.expect("Could not acquire SQL pool from data");
/// Set a join sound
#[poise::command(slash_command, rename = "unset")]
pub async fn unset_greet_sound(ctx: Context<'_>) -> Result<(), Error> {
ctx.data().update_join_sound(ctx.author().id, None).await;
let guild_data_opt = ctx.guild_data(invoke.guild_id().unwrap()).await;
ctx.say("Greet sound has been unset").await?;
Ok(())
}
/// Disable greet sounds on this server
#[poise::command(slash_command, rename = "disable")]
pub async fn disable_greet_sound(ctx: Context<'_>) -> Result<(), Error> {
let guild_data_opt = ctx.guild_data(ctx.guild_id().unwrap()).await;
if let Ok(guild_data) = guild_data_opt {
let current = guild_data.read().await.allow_greets;
guild_data.write().await.allow_greets = false;
{
guild_data.write().await.allow_greets = !current;
}
guild_data.read().await.commit(pool).await?;
invoke
.respond(
ctx.http.clone(),
CreateGenericResponse::new().content(format!(
"Greet sounds have been {}abled in this server",
if !current { "en" } else { "dis" }
)),
)
guild_data
.read()
.await
.commit(ctx.data().database.clone())
.await?;
}
ctx.say("Greet sounds have been disabled in this server")
.await?;
Ok(())
}
/// Enable greet sounds on this server
#[poise::command(slash_command, rename = "enable")]
pub async fn enable_greet_sound(ctx: Context<'_>) -> Result<(), Error> {
let guild_data_opt = ctx.guild_data(ctx.guild_id().unwrap()).await;
if let Ok(guild_data) = guild_data_opt {
guild_data.write().await.allow_greets = true;
guild_data
.read()
.await
.commit(ctx.data().database.clone())
.await?;
}
ctx.say("Greet sounds have been enable in this server")
.await?;
Ok(())
}

View File

@ -1,22 +1,12 @@
use regex_command_attr::command;
use serenity::{client::Context, framework::standard::CommandResult};
use songbird;
use crate::framework::{Args, CommandInvoke, CreateGenericResponse};
use crate::{Context, Error};
#[command("stop")]
#[required_permissions(Managed)]
#[group("Stop")]
#[description("Stop the bot from playing")]
pub async fn stop_playing(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
_args: Args,
) -> CommandResult {
let guild_id = invoke.guild_id().unwrap();
let songbird = songbird::get(ctx).await.unwrap();
let call_opt = songbird.get(guild_id);
/// Stop the bot from playing
#[poise::command(slash_command, rename = "stop")]
pub async fn stop_playing(ctx: Context<'_>) -> Result<(), Error> {
let songbird = songbird::get(ctx.discord()).await.unwrap();
let call_opt = songbird.get(ctx.guild_id().unwrap());
if let Some(call) = call_opt {
let mut lock = call.lock().await;
@ -24,31 +14,18 @@ pub async fn stop_playing(
lock.stop();
}
invoke
.respond(ctx.http.clone(), CreateGenericResponse::new().content("👍"))
.await?;
ctx.say("👍").await?;
Ok(())
}
#[command]
#[aliases("dc")]
#[required_permissions(Managed)]
#[group("Stop")]
#[description("Disconnect the bot")]
pub async fn disconnect(
ctx: &Context,
invoke: &(dyn CommandInvoke + Sync + Send),
_args: Args,
) -> CommandResult {
let guild_id = invoke.guild_id().unwrap();
/// Disconnect the bot
#[poise::command(slash_command)]
pub async fn disconnect(ctx: Context<'_>) -> Result<(), Error> {
let songbird = songbird::get(ctx.discord()).await.unwrap();
let _ = songbird.leave(ctx.guild_id().unwrap()).await;
let songbird = songbird::get(ctx).await.unwrap();
let _ = songbird.leave(guild_id).await;
invoke
.respond(ctx.http.clone(), CreateGenericResponse::new().content("👍"))
.await?;
ctx.say("👍").await?;
Ok(())
}