feat: add /mod summon

This commit is contained in:
Evan Carroll 2026-01-20 21:48:04 -06:00
parent 864cfaec54
commit 45a7e44b3a
11 changed files with 598 additions and 5 deletions

View file

@ -18,8 +18,8 @@ use tokio::sync::{broadcast, mpsc};
use uuid::Uuid;
use chattyness_db::{
models::{AvatarRenderData, ChannelMemberWithAvatar, EmotionState, User},
queries::{avatars, channel_members, loose_props, realms, scenes},
models::{ActionType, AvatarRenderData, ChannelMemberWithAvatar, EmotionState, User},
queries::{avatars, channel_members, loose_props, memberships, moderation, realms, scenes},
ws_messages::{close_codes, ClientMessage, DisconnectReason, ServerMessage, WsConfig},
};
use chattyness_error::AppError;
@ -828,6 +828,169 @@ async fn handle_socket(
scene_slug: scene.slug,
}).await;
}
ClientMessage::ModCommand { subcommand, args } => {
// Check if user is a moderator
let is_mod = match memberships::is_moderator(&pool, user_id, realm_id).await {
Ok(result) => result,
Err(e) => {
tracing::error!("[WS] Failed to check moderator status: {:?}", e);
false
}
};
if !is_mod {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: "You do not have moderator permissions".to_string(),
}).await;
continue;
}
// Get moderator's current scene info and display name
let mod_member = match channel_members::get_channel_member(
&mut *recv_conn,
channel_id,
user_id,
realm_id,
).await {
Ok(Some(m)) => m,
Ok(None) | Err(_) => {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: "Failed to get moderator info".to_string(),
}).await;
continue;
}
};
// Get moderator's current scene details
let mod_scene = match scenes::get_scene_by_id(&pool, channel_id).await {
Ok(Some(s)) => s,
Ok(None) | Err(_) => {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: "Failed to get scene info".to_string(),
}).await;
continue;
}
};
match subcommand.as_str() {
"summon" => {
if args.is_empty() {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: "Usage: /mod summon [nick|*]".to_string(),
}).await;
continue;
}
let target = &args[0];
if target == "*" {
// Summon all users in the realm
let mut summoned_count = 0;
let mut target_ids = Vec::new();
// Iterate all connected users in this realm
for entry in ws_state.users.iter() {
let (target_user_id, target_conn) = entry.pair();
if target_conn.realm_id == realm_id && *target_user_id != user_id {
// Send Summoned message to each user
let summon_msg = ServerMessage::Summoned {
scene_id: mod_scene.id,
scene_slug: mod_scene.slug.clone(),
summoned_by: mod_member.display_name.clone(),
};
if target_conn.direct_tx.send(summon_msg).await.is_ok() {
summoned_count += 1;
target_ids.push(*target_user_id);
}
}
}
// Log the action
let metadata = serde_json::json!({
"scene_id": mod_scene.id,
"scene_slug": mod_scene.slug,
"summoned_count": summoned_count,
});
let _ = moderation::log_moderation_action(
&pool,
realm_id,
user_id,
ActionType::SummonAll,
None,
&format!("Summoned {} users to scene {}", summoned_count, mod_scene.name),
metadata,
).await;
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: true,
message: format!("Summoned {} users to {}", summoned_count, mod_scene.name),
}).await;
} else {
// Summon specific user by display name
if let Some((target_user_id, target_conn)) = ws_state
.find_user_by_display_name(realm_id, target)
{
if target_user_id == user_id {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: "You cannot summon yourself".to_string(),
}).await;
continue;
}
// Send Summoned message to target
let summon_msg = ServerMessage::Summoned {
scene_id: mod_scene.id,
scene_slug: mod_scene.slug.clone(),
summoned_by: mod_member.display_name.clone(),
};
if target_conn.direct_tx.send(summon_msg).await.is_ok() {
// Log the action
let metadata = serde_json::json!({
"scene_id": mod_scene.id,
"scene_slug": mod_scene.slug,
"target_display_name": target,
});
let _ = moderation::log_moderation_action(
&pool,
realm_id,
user_id,
ActionType::Summon,
Some(target_user_id),
&format!("Summoned {} to scene {}", target, mod_scene.name),
metadata,
).await;
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: true,
message: format!("Summoned {} to {}", target, mod_scene.name),
}).await;
} else {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: format!("Failed to send summon to {}", target),
}).await;
}
} else {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: format!("User '{}' is not online in this realm", target),
}).await;
}
}
}
_ => {
let _ = direct_tx.send(ServerMessage::ModCommandResult {
success: false,
message: format!("Unknown mod command: {}", subcommand),
}).await;
}
}
}
}
}
Message::Close(close_frame) => {