add :emote and :list to chat
This commit is contained in:
parent
1ca300098f
commit
bd28e201a2
7 changed files with 741 additions and 22 deletions
|
|
@ -1695,3 +1695,30 @@ pub struct JoinChannelResponse {
|
|||
pub member: ChannelMemberInfo,
|
||||
pub members: Vec<ChannelMemberWithAvatar>,
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Emotion Availability
|
||||
// =============================================================================
|
||||
|
||||
/// Emotion availability data for the emote command UI.
|
||||
///
|
||||
/// Indicates which of the 12 emotions have assets configured for the user's avatar,
|
||||
/// and provides preview paths (position 4/center) for rendering in the emotion picker.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct EmotionAvailability {
|
||||
/// Which emotions have at least one non-null asset slot (positions 0-8).
|
||||
/// Index corresponds to emotion: 0=neutral, 1=happy, 2=sad, etc.
|
||||
pub available: [bool; 12],
|
||||
/// Center position (4) asset path for each emotion, used for preview rendering.
|
||||
/// None if that emotion has no center asset.
|
||||
pub preview_paths: [Option<String>; 12],
|
||||
}
|
||||
|
||||
impl Default for EmotionAvailability {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
available: [false; 12],
|
||||
preview_paths: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use sqlx::PgExecutor;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::models::{ActiveAvatar, AvatarRenderData};
|
||||
use crate::models::{ActiveAvatar, AvatarRenderData, EmotionAvailability};
|
||||
use chattyness_error::AppError;
|
||||
|
||||
/// Get the active avatar for a user in a realm.
|
||||
|
|
@ -35,8 +35,8 @@ pub async fn set_emotion<'e>(
|
|||
realm_id: Uuid,
|
||||
emotion: i16,
|
||||
) -> Result<[Option<String>; 9], AppError> {
|
||||
if emotion < 0 || emotion > 9 {
|
||||
return Err(AppError::Validation("Emotion must be 0-9".to_string()));
|
||||
if emotion < 0 || emotion > 11 {
|
||||
return Err(AppError::Validation("Emotion must be 0-11".to_string()));
|
||||
}
|
||||
|
||||
// Map emotion index to column prefix
|
||||
|
|
@ -51,7 +51,9 @@ pub async fn set_emotion<'e>(
|
|||
7 => "e_crying",
|
||||
8 => "e_love",
|
||||
9 => "e_confused",
|
||||
_ => return Err(AppError::Validation("Emotion must be 0-9".to_string())),
|
||||
10 => "e_sleeping",
|
||||
11 => "e_wink",
|
||||
_ => return Err(AppError::Validation("Emotion must be 0-11".to_string())),
|
||||
};
|
||||
|
||||
// Build dynamic query for the specific emotion's 9 positions
|
||||
|
|
@ -199,3 +201,167 @@ impl From<SimplifiedAvatarRow> for AvatarRenderData {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get emotion availability for a user's avatar in a realm.
|
||||
///
|
||||
/// Returns which emotions have assets configured (any of positions 0-8 non-null)
|
||||
/// and the center position (4) preview path for each emotion.
|
||||
pub async fn get_emotion_availability<'e>(
|
||||
executor: impl PgExecutor<'e>,
|
||||
user_id: Uuid,
|
||||
realm_id: Uuid,
|
||||
) -> Result<EmotionAvailability, AppError> {
|
||||
let row = sqlx::query_as::<_, EmotionAvailabilityRow>(
|
||||
r#"
|
||||
SELECT
|
||||
-- Neutral (0): check if any position has asset
|
||||
(a.e_neutral_0 IS NOT NULL OR a.e_neutral_1 IS NOT NULL OR a.e_neutral_2 IS NOT NULL OR
|
||||
a.e_neutral_3 IS NOT NULL OR a.e_neutral_4 IS NOT NULL OR a.e_neutral_5 IS NOT NULL OR
|
||||
a.e_neutral_6 IS NOT NULL OR a.e_neutral_7 IS NOT NULL OR a.e_neutral_8 IS NOT NULL) as avail_0,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_neutral_4) as preview_0,
|
||||
|
||||
-- Happy (1)
|
||||
(a.e_happy_0 IS NOT NULL OR a.e_happy_1 IS NOT NULL OR a.e_happy_2 IS NOT NULL OR
|
||||
a.e_happy_3 IS NOT NULL OR a.e_happy_4 IS NOT NULL OR a.e_happy_5 IS NOT NULL OR
|
||||
a.e_happy_6 IS NOT NULL OR a.e_happy_7 IS NOT NULL OR a.e_happy_8 IS NOT NULL) as avail_1,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_happy_4) as preview_1,
|
||||
|
||||
-- Sad (2)
|
||||
(a.e_sad_0 IS NOT NULL OR a.e_sad_1 IS NOT NULL OR a.e_sad_2 IS NOT NULL OR
|
||||
a.e_sad_3 IS NOT NULL OR a.e_sad_4 IS NOT NULL OR a.e_sad_5 IS NOT NULL OR
|
||||
a.e_sad_6 IS NOT NULL OR a.e_sad_7 IS NOT NULL OR a.e_sad_8 IS NOT NULL) as avail_2,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_sad_4) as preview_2,
|
||||
|
||||
-- Angry (3)
|
||||
(a.e_angry_0 IS NOT NULL OR a.e_angry_1 IS NOT NULL OR a.e_angry_2 IS NOT NULL OR
|
||||
a.e_angry_3 IS NOT NULL OR a.e_angry_4 IS NOT NULL OR a.e_angry_5 IS NOT NULL OR
|
||||
a.e_angry_6 IS NOT NULL OR a.e_angry_7 IS NOT NULL OR a.e_angry_8 IS NOT NULL) as avail_3,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_angry_4) as preview_3,
|
||||
|
||||
-- Surprised (4)
|
||||
(a.e_surprised_0 IS NOT NULL OR a.e_surprised_1 IS NOT NULL OR a.e_surprised_2 IS NOT NULL OR
|
||||
a.e_surprised_3 IS NOT NULL OR a.e_surprised_4 IS NOT NULL OR a.e_surprised_5 IS NOT NULL OR
|
||||
a.e_surprised_6 IS NOT NULL OR a.e_surprised_7 IS NOT NULL OR a.e_surprised_8 IS NOT NULL) as avail_4,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_surprised_4) as preview_4,
|
||||
|
||||
-- Thinking (5)
|
||||
(a.e_thinking_0 IS NOT NULL OR a.e_thinking_1 IS NOT NULL OR a.e_thinking_2 IS NOT NULL OR
|
||||
a.e_thinking_3 IS NOT NULL OR a.e_thinking_4 IS NOT NULL OR a.e_thinking_5 IS NOT NULL OR
|
||||
a.e_thinking_6 IS NOT NULL OR a.e_thinking_7 IS NOT NULL OR a.e_thinking_8 IS NOT NULL) as avail_5,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_thinking_4) as preview_5,
|
||||
|
||||
-- Laughing (6)
|
||||
(a.e_laughing_0 IS NOT NULL OR a.e_laughing_1 IS NOT NULL OR a.e_laughing_2 IS NOT NULL OR
|
||||
a.e_laughing_3 IS NOT NULL OR a.e_laughing_4 IS NOT NULL OR a.e_laughing_5 IS NOT NULL OR
|
||||
a.e_laughing_6 IS NOT NULL OR a.e_laughing_7 IS NOT NULL OR a.e_laughing_8 IS NOT NULL) as avail_6,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_laughing_4) as preview_6,
|
||||
|
||||
-- Crying (7)
|
||||
(a.e_crying_0 IS NOT NULL OR a.e_crying_1 IS NOT NULL OR a.e_crying_2 IS NOT NULL OR
|
||||
a.e_crying_3 IS NOT NULL OR a.e_crying_4 IS NOT NULL OR a.e_crying_5 IS NOT NULL OR
|
||||
a.e_crying_6 IS NOT NULL OR a.e_crying_7 IS NOT NULL OR a.e_crying_8 IS NOT NULL) as avail_7,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_crying_4) as preview_7,
|
||||
|
||||
-- Love (8)
|
||||
(a.e_love_0 IS NOT NULL OR a.e_love_1 IS NOT NULL OR a.e_love_2 IS NOT NULL OR
|
||||
a.e_love_3 IS NOT NULL OR a.e_love_4 IS NOT NULL OR a.e_love_5 IS NOT NULL OR
|
||||
a.e_love_6 IS NOT NULL OR a.e_love_7 IS NOT NULL OR a.e_love_8 IS NOT NULL) as avail_8,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_love_4) as preview_8,
|
||||
|
||||
-- Confused (9)
|
||||
(a.e_confused_0 IS NOT NULL OR a.e_confused_1 IS NOT NULL OR a.e_confused_2 IS NOT NULL OR
|
||||
a.e_confused_3 IS NOT NULL OR a.e_confused_4 IS NOT NULL OR a.e_confused_5 IS NOT NULL OR
|
||||
a.e_confused_6 IS NOT NULL OR a.e_confused_7 IS NOT NULL OR a.e_confused_8 IS NOT NULL) as avail_9,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_confused_4) as preview_9,
|
||||
|
||||
-- Sleeping (10)
|
||||
(a.e_sleeping_0 IS NOT NULL OR a.e_sleeping_1 IS NOT NULL OR a.e_sleeping_2 IS NOT NULL OR
|
||||
a.e_sleeping_3 IS NOT NULL OR a.e_sleeping_4 IS NOT NULL OR a.e_sleeping_5 IS NOT NULL OR
|
||||
a.e_sleeping_6 IS NOT NULL OR a.e_sleeping_7 IS NOT NULL OR a.e_sleeping_8 IS NOT NULL) as avail_10,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_sleeping_4) as preview_10,
|
||||
|
||||
-- Wink (11)
|
||||
(a.e_wink_0 IS NOT NULL OR a.e_wink_1 IS NOT NULL OR a.e_wink_2 IS NOT NULL OR
|
||||
a.e_wink_3 IS NOT NULL OR a.e_wink_4 IS NOT NULL OR a.e_wink_5 IS NOT NULL OR
|
||||
a.e_wink_6 IS NOT NULL OR a.e_wink_7 IS NOT NULL OR a.e_wink_8 IS NOT NULL) as avail_11,
|
||||
(SELECT prop_asset_path FROM props.inventory WHERE id = a.e_wink_4) as preview_11
|
||||
|
||||
FROM props.active_avatars aa
|
||||
JOIN props.avatars a ON aa.avatar_id = a.id
|
||||
WHERE aa.user_id = $1 AND aa.realm_id = $2
|
||||
"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(realm_id)
|
||||
.fetch_optional(executor)
|
||||
.await?;
|
||||
|
||||
match row {
|
||||
Some(r) => Ok(r.into()),
|
||||
None => Ok(EmotionAvailability::default()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Row type for emotion availability query.
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
struct EmotionAvailabilityRow {
|
||||
avail_0: Option<bool>,
|
||||
preview_0: Option<String>,
|
||||
avail_1: Option<bool>,
|
||||
preview_1: Option<String>,
|
||||
avail_2: Option<bool>,
|
||||
preview_2: Option<String>,
|
||||
avail_3: Option<bool>,
|
||||
preview_3: Option<String>,
|
||||
avail_4: Option<bool>,
|
||||
preview_4: Option<String>,
|
||||
avail_5: Option<bool>,
|
||||
preview_5: Option<String>,
|
||||
avail_6: Option<bool>,
|
||||
preview_6: Option<String>,
|
||||
avail_7: Option<bool>,
|
||||
preview_7: Option<String>,
|
||||
avail_8: Option<bool>,
|
||||
preview_8: Option<String>,
|
||||
avail_9: Option<bool>,
|
||||
preview_9: Option<String>,
|
||||
avail_10: Option<bool>,
|
||||
preview_10: Option<String>,
|
||||
avail_11: Option<bool>,
|
||||
preview_11: Option<String>,
|
||||
}
|
||||
|
||||
impl From<EmotionAvailabilityRow> for EmotionAvailability {
|
||||
fn from(row: EmotionAvailabilityRow) -> Self {
|
||||
Self {
|
||||
available: [
|
||||
row.avail_0.unwrap_or(false),
|
||||
row.avail_1.unwrap_or(false),
|
||||
row.avail_2.unwrap_or(false),
|
||||
row.avail_3.unwrap_or(false),
|
||||
row.avail_4.unwrap_or(false),
|
||||
row.avail_5.unwrap_or(false),
|
||||
row.avail_6.unwrap_or(false),
|
||||
row.avail_7.unwrap_or(false),
|
||||
row.avail_8.unwrap_or(false),
|
||||
row.avail_9.unwrap_or(false),
|
||||
row.avail_10.unwrap_or(false),
|
||||
row.avail_11.unwrap_or(false),
|
||||
],
|
||||
preview_paths: [
|
||||
row.preview_0,
|
||||
row.preview_1,
|
||||
row.preview_2,
|
||||
row.preview_3,
|
||||
row.preview_4,
|
||||
row.preview_5,
|
||||
row.preview_6,
|
||||
row.preview_7,
|
||||
row.preview_8,
|
||||
row.preview_9,
|
||||
row.preview_10,
|
||||
row.preview_11,
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue