diff --git a/service/migrations/000010_create_guilds/up.sql b/service/migrations/000010_create_guilds/up.sql index d2dd580..6fef802 100644 --- a/service/migrations/000010_create_guilds/up.sql +++ b/service/migrations/000010_create_guilds/up.sql @@ -1,5 +1,5 @@ CREATE TABLE IF NOT EXISTS guilds ( id BIGINT PRIMARY KEY NOT NULL, bot_id BIGINT NOT NULL, - volume DOUBLE PRECISION NOT NULL + volume INTEGER NOT NULL ); \ No newline at end of file diff --git a/service/src/bot/api/routes.rs b/service/src/bot/api/routes.rs index 1b87fb0..4579e40 100644 --- a/service/src/bot/api/routes.rs +++ b/service/src/bot/api/routes.rs @@ -291,16 +291,17 @@ async fn set_volume(path: web::Path, volume: web::Json::, dat } }; - let bound_volume = volume.volume.parse::().unwrap_or(0.0); - - let _ = InsertGuild::update_audio(guild_id as i64, bound_volume as f64); - - if let Some(handler_lock) = data.songbird.get(guild_id) { - let handler = handler_lock.lock().await; - for (_, track_handle) in handler.queue().current_queue().iter().enumerate() { - let _ = track_handle.set_volume(bound_volume); + let volume = volume.volume.parse::().unwrap_or(0); + let manager = Arc::clone(&data.songbird); + let http = Arc::clone(&data.http); + let guild = match http.get_guild(guild_id).await { + Ok(guild) => guild, + Err(err) => { + warn!("Could not get guild: {:?}", err); + return ResponseError::error_response(&ServiceError { status: 422, message: err.to_string() }) } - } + }; + crate::bot::commands::audio::volume::set_volume(manager, guild.id, volume).await; HttpResponse::Ok().finish() } diff --git a/service/src/bot/commands/audio/volume.rs b/service/src/bot/commands/audio/volume.rs index 51fa174..9a3ece3 100644 --- a/service/src/bot/commands/audio/volume.rs +++ b/service/src/bot/commands/audio/volume.rs @@ -1,8 +1,11 @@ +use std::sync::Arc; + use log::{error, warn}; -use serenity::prelude::*; +use serenity::{prelude::*, model::prelude::GuildId}; use serenity::builder::CreateApplicationCommand; use serenity::model::application::interaction::application_command::ApplicationCommandInteraction; +use songbird::Songbird; use crate::db::guilds::InsertGuild; @@ -13,7 +16,7 @@ pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { let volume = match command.data.options.get(0) { Some(t) => match &t.value { Some(v) => match v.as_i64() { - Some(p) => std::cmp::min(100, std::cmp::max(0, p)), + Some(p) => p as i32, None => { warn!("Unable to get volume option as a string"); if let Err(why) = create_response(&ctx, &command, format!("Volume option is missing")).await { @@ -39,9 +42,6 @@ pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { } }; - // Format volume to f32 bound between 0.0 and 1.0 - let bound_volume = volume as f32 / 100.0; - // Create the initial response if let Err(why) = create_response(&ctx, &command, "Processing command...".to_string()).await { error!("Failed to create response message: {}", why); @@ -57,17 +57,25 @@ pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) { return; } }; - let _ = InsertGuild::update_audio(guild_id.0 as i64, bound_volume as f64); let manager = get_songbird(ctx).await; + set_volume(manager, guild_id, volume).await; + if let Err(why) = edit_response(&ctx, &command, format!("Setting the volume to {}", volume)).await { + error!("Failed to set the volume: {}", why); + } +} + +pub async fn set_volume(manager: Arc, guild_id: GuildId, volume: i32) { + // Format volume to f32 bound between 0.0 and 1.0 + let volume = std::cmp::min(100, std::cmp::max(0, volume)); + let bound_volume = volume as f32 / 100.0; + let _ = InsertGuild::update_audio(guild_id.0 as i64, volume); + if let Some(handler_lock) = manager.get(guild_id) { let handler = handler_lock.lock().await; for (_, track_handle) in handler.queue().current_queue().iter().enumerate() { let _ = track_handle.set_volume(bound_volume); } } - if let Err(why) = edit_response(&ctx, &command, format!("Setting the volume to {}", volume)).await { - error!("Failed to set the volume: {}", why); - } } pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { diff --git a/service/src/bot/handler.rs b/service/src/bot/handler.rs index de09fee..f45d3d1 100644 --- a/service/src/bot/handler.rs +++ b/service/src/bot/handler.rs @@ -77,7 +77,7 @@ impl EventHandler for Handler { let _ = InsertGuild::insert(InsertGuild { id: (guild.id.0 as i64), bot_id: ctx.cache.current_user().id.0 as i64, - volume: 100.0 + volume: 100 }); let commands = guild.id.set_application_commands(&ctx.http, |commands| { commands.create_application_command(|command: &mut serenity::builder::CreateApplicationCommand| { commands::ping::register(command) }) diff --git a/service/src/db/guilds/model.rs b/service/src/db/guilds/model.rs index 2c3039f..ababc25 100644 --- a/service/src/db/guilds/model.rs +++ b/service/src/db/guilds/model.rs @@ -9,7 +9,7 @@ use crate::db::{schema::guilds, connection}; pub struct QueryGuild { pub id: i64, pub bot_id: i64, - pub volume: f64 + pub volume: i32 } impl QueryGuild { @@ -25,7 +25,7 @@ impl QueryGuild { pub struct InsertGuild { pub id: i64, pub bot_id: i64, - pub volume: f64 + pub volume: i32 } impl InsertGuild { @@ -35,7 +35,7 @@ impl InsertGuild { Ok(guild) } - pub fn update_audio(id: i64, volume: f64) -> Result { + pub fn update_audio(id: i64, volume: i32) -> Result { let mut conn = connection()?; let guild = diesel::update(guilds::table.filter(guilds::id.eq(id))).set(guilds::volume.eq(volume)).get_result(&mut conn)?; Ok(guild) diff --git a/service/src/db/schema.rs b/service/src/db/schema.rs index 64b84e5..5d5e4bf 100644 --- a/service/src/db/schema.rs +++ b/service/src/db/schema.rs @@ -35,6 +35,6 @@ diesel::table! { guilds (id) { id -> BigInt, bot_id -> BigInt, - volume -> Float8, + volume -> Integer, } } \ No newline at end of file diff --git a/service/src/db/spells/model.rs b/service/src/db/spells/model.rs index d8f71f3..a2d460b 100644 --- a/service/src/db/spells/model.rs +++ b/service/src/db/spells/model.rs @@ -6,7 +6,7 @@ use crate::db::{schema::spells::{self}, classes::AbilityType, conditions::Condit use super::{SchoolType, CastingTime, SpellAttackType, SpellDamageType, Range, Area, Components, Duration, Source, Description, DurationType, Effect}; -#[derive(Queryable, QueryableByName, Serialize, Deserialize)] +#[derive(Debug, Queryable, QueryableByName, Serialize, Deserialize)] #[diesel(table_name = spells)] pub struct QuerySpell { pub id: i32, @@ -163,7 +163,7 @@ impl QuerySpell { } } -#[derive(Insertable, AsChangeset)] +#[derive(Debug, Insertable, AsChangeset)] #[diesel(table_name = spells)] pub struct InsertSpell { pub name: String, diff --git a/service/src/db/spells/types.rs b/service/src/db/spells/types.rs index eaeb94e..72492cc 100644 --- a/service/src/db/spells/types.rs +++ b/service/src/db/spells/types.rs @@ -263,7 +263,7 @@ pub struct Description { #[derive(Debug)] pub struct Entry { - pub text: Option>, + pub text: Option, pub list: Option>, pub table: Option } @@ -279,11 +279,18 @@ impl<'de> Deserialize<'de> for Entry { let value = serde_json::Value::deserialize(deserializer)?; match value { serde_json::Value::String(s) => Ok(Entry { - text: Some(vec![s]), + text: Some(s), list: None, table: None, }), serde_json::Value::Object(o) => { + let text = match o.get("text") { + Some(t) => match t.as_str() { + Some(s) => Some(s.to_string()), + None => return Err(serde::de::Error::custom("Invalid entry text")) + }, + None => None + }; let list = match o.get("list") { Some(i) => match i.as_array() { Some(a) => { @@ -352,7 +359,7 @@ impl<'de> Deserialize<'de> for Entry { None => None }; Ok(Entry { - text: None, + text, list, table }) diff --git a/ui/src/api/spells.types.ts b/ui/src/api/spells.types.ts index 81677f4..4af3ee0 100644 --- a/ui/src/api/spells.types.ts +++ b/ui/src/api/spells.types.ts @@ -61,14 +61,21 @@ export interface Source { } export interface Description { - entries: EntryType[]; + // entries: EntryType[]; + entries: Entry[]; } -type EntryType = string | Entry; +// type EntryType = string | Entry; export interface Entry { - type: string; - items: string[]; + text?: string; + list?: string[]; + table?: EntryTable; +} + +export interface EntryTable { + headers: string[]; + rows: string[][]; } export interface GetSpellResponse { diff --git a/ui/src/app/management/page.tsx b/ui/src/app/management/page.tsx index 7b90ebb..3760004 100644 --- a/ui/src/app/management/page.tsx +++ b/ui/src/app/management/page.tsx @@ -4,6 +4,7 @@ import { getGuilds, getTextChannels, getVoiceChannels, + getVolume, pauseTrack, playTrack, resumeTrack, @@ -22,6 +23,7 @@ export default function Page() { const [activeGuild, setActiveGuild] = useState(null); const [textChannels, setTextChannels] = useState([]); const [voiceChannels, setVoiceChannels] = useState([]); + const [guildVolume, setGuildVolume] = useState(50.0); useEffect(() => { getGuilds().then((g) => { @@ -36,6 +38,7 @@ export default function Page() { if (activeGuild) { getTextChannels(activeGuild.id).then((c) => setTextChannels(c)); getVoiceChannels(activeGuild.id).then((c) => setVoiceChannels(c)); + getVolume(activeGuild.id).then((v) => setGuildVolume(v)); } }, [activeGuild]); @@ -117,7 +120,7 @@ export default function Page() { onSubmit={playForm.onSubmit((values) => setVolume(activeGuild!.id, values.volume))} > {spell.description && ( <> - {spell.description.entries.map((e) => - typeof e === 'string' ? ( -

{parseText(e)}

- ) : ( - <> - {e.type == 'list' ? ( -
    - {e.items.map((text) => ( -
  • {parseText(text)}
  • + {spell.description.entries.map((e) => ( + // typeof e === 'string' ? ( + //

    {parseText(e)}

    + // ) : ( + // <> + // {e.list ? ( + //
      + // {e.list.map((text) => ( + //
    • {parseText(text)}
    • + // ))} + //
    + // ) : ( + // <> + // )} + // + // ) + <> + {e.text &&

    {parseText(e.text)}

    } + {e.list && ( +
      + {e.list.map((text) => ( +
    • {parseText(text)}
    • + ))} +
    + )} + {e.table && ( + + + + {e.table.headers.map((label) => ( + + ))} + + + + {e.table.rows.map((row) => ( + + {row.map((cell) => ( + + ))} + ))} - - ) : ( - <> - )} - - ) - )} + +
    {label}
    {parseText(cell)}
    + )} + + ))} )} diff --git a/ui/src/js/spells.ts b/ui/src/js/spells.ts index ec525dd..9e0d8b5 100644 --- a/ui/src/js/spells.ts +++ b/ui/src/js/spells.ts @@ -18,6 +18,5 @@ export function rollDice(dice: string): number[] { for (let i = 0; i < parseInt(count); i++) { rolls.push(Math.floor(Math.random() * parseInt(sides)) + 1); } - console.log(rolls); return rolls; }