feat: add /mod teleport
This commit is contained in:
parent
45a7e44b3a
commit
3da420fe59
3 changed files with 113 additions and 13 deletions
|
|
@ -227,6 +227,7 @@ pub enum ActionType {
|
||||||
MessageDeletion,
|
MessageDeletion,
|
||||||
Summon,
|
Summon,
|
||||||
SummonAll,
|
SummonAll,
|
||||||
|
Teleport,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for ActionType {
|
impl std::fmt::Display for ActionType {
|
||||||
|
|
@ -241,6 +242,7 @@ impl std::fmt::Display for ActionType {
|
||||||
ActionType::MessageDeletion => write!(f, "message_deletion"),
|
ActionType::MessageDeletion => write!(f, "message_deletion"),
|
||||||
ActionType::Summon => write!(f, "summon"),
|
ActionType::Summon => write!(f, "summon"),
|
||||||
ActionType::SummonAll => write!(f, "summon_all"),
|
ActionType::SummonAll => write!(f, "summon_all"),
|
||||||
|
ActionType::Teleport => write!(f, "teleport"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -983,6 +983,89 @@ async fn handle_socket(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"teleport" => {
|
||||||
|
if args.len() < 2 {
|
||||||
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
|
success: false,
|
||||||
|
message: "Usage: /mod teleport [nick] [slug]".to_string(),
|
||||||
|
}).await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let target_nick = &args[0];
|
||||||
|
let target_slug = &args[1];
|
||||||
|
|
||||||
|
// Look up the target scene by slug
|
||||||
|
let target_scene = match scenes::get_scene_by_slug(&pool, realm_id, target_slug).await {
|
||||||
|
Ok(Some(s)) => s,
|
||||||
|
Ok(None) => {
|
||||||
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
|
success: false,
|
||||||
|
message: format!("Scene '{}' not found", target_slug),
|
||||||
|
}).await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
|
success: false,
|
||||||
|
message: "Failed to look up scene".to_string(),
|
||||||
|
}).await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find target user by display name
|
||||||
|
if let Some((target_user_id, target_conn)) = ws_state
|
||||||
|
.find_user_by_display_name(realm_id, target_nick)
|
||||||
|
{
|
||||||
|
if target_user_id == user_id {
|
||||||
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
|
success: false,
|
||||||
|
message: "You cannot teleport yourself".to_string(),
|
||||||
|
}).await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send Summoned message to target user with the specified scene
|
||||||
|
let teleport_msg = ServerMessage::Summoned {
|
||||||
|
scene_id: target_scene.id,
|
||||||
|
scene_slug: target_scene.slug.clone(),
|
||||||
|
summoned_by: mod_member.display_name.clone(),
|
||||||
|
};
|
||||||
|
if target_conn.direct_tx.send(teleport_msg).await.is_ok() {
|
||||||
|
// Log the action
|
||||||
|
let metadata = serde_json::json!({
|
||||||
|
"scene_id": target_scene.id,
|
||||||
|
"scene_slug": target_scene.slug,
|
||||||
|
"target_display_name": target_nick,
|
||||||
|
});
|
||||||
|
let _ = moderation::log_moderation_action(
|
||||||
|
&pool,
|
||||||
|
realm_id,
|
||||||
|
user_id,
|
||||||
|
ActionType::Teleport,
|
||||||
|
Some(target_user_id),
|
||||||
|
&format!("Teleported {} to scene {}", target_nick, target_scene.name),
|
||||||
|
metadata,
|
||||||
|
).await;
|
||||||
|
|
||||||
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
|
success: true,
|
||||||
|
message: format!("Teleported {} to {}", target_nick, target_scene.name),
|
||||||
|
}).await;
|
||||||
|
} else {
|
||||||
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
|
success: false,
|
||||||
|
message: format!("Failed to send teleport to {}", target_nick),
|
||||||
|
}).await;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
|
success: false,
|
||||||
|
message: format!("User '{}' is not online in this realm", target_nick),
|
||||||
|
}).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
let _ = direct_tx.send(ServerMessage::ModCommandResult {
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@ enum CommandMode {
|
||||||
None,
|
None,
|
||||||
/// Showing command hint for colon commands (`:e[mote], :l[ist]`).
|
/// Showing command hint for colon commands (`:e[mote], :l[ist]`).
|
||||||
ShowingColonHint,
|
ShowingColonHint,
|
||||||
/// Showing command hint for slash commands (`/setting`).
|
/// Showing command hint for slash commands (`/setting`, `/mod` for mods).
|
||||||
ShowingSlashHint,
|
ShowingSlashHint,
|
||||||
/// Showing mod command hint (`/mod summon [nick|*]`).
|
/// Showing mod command hints only (`/mod summon [nick|*]`).
|
||||||
ShowingModHint,
|
ShowingModHint,
|
||||||
/// Showing emotion list popup.
|
/// Showing emotion list popup.
|
||||||
ShowingList,
|
ShowingList,
|
||||||
|
|
@ -361,15 +361,21 @@ pub fn ChatInput(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if mod command (only for moderators)
|
// Check if typing mod command (only for moderators)
|
||||||
let is_mod_command = is_moderator.get_untracked()
|
// Show mod hint when typing "/mod" or "/mod ..."
|
||||||
&& (cmd.starts_with("mod") || "mod".starts_with(&cmd));
|
let is_typing_mod = is_moderator.get_untracked()
|
||||||
|
&& (cmd == "mod" || cmd.starts_with("mod "));
|
||||||
|
// Show /mod in slash hints when just starting to type it
|
||||||
|
let is_partial_mod = is_moderator.get_untracked()
|
||||||
|
&& !cmd.is_empty()
|
||||||
|
&& "mod".starts_with(&cmd)
|
||||||
|
&& cmd != "mod";
|
||||||
|
|
||||||
if is_complete_whisper || is_complete_teleport {
|
if is_complete_whisper || is_complete_teleport {
|
||||||
// User is typing the argument part, no hint needed
|
// User is typing the argument part, no hint needed
|
||||||
set_command_mode.set(CommandMode::None);
|
set_command_mode.set(CommandMode::None);
|
||||||
} else if is_mod_command {
|
} else if is_typing_mod {
|
||||||
// Show mod command hint
|
// Show mod-specific hint bar
|
||||||
set_command_mode.set(CommandMode::ShowingModHint);
|
set_command_mode.set(CommandMode::ShowingModHint);
|
||||||
} else if cmd.is_empty()
|
} else if cmd.is_empty()
|
||||||
|| "setting".starts_with(&cmd)
|
|| "setting".starts_with(&cmd)
|
||||||
|
|
@ -385,6 +391,7 @@ pub fn ChatInput(
|
||||||
|| cmd.starts_with("whisper ")
|
|| cmd.starts_with("whisper ")
|
||||||
|| cmd.starts_with("t ")
|
|| cmd.starts_with("t ")
|
||||||
|| cmd.starts_with("teleport ")
|
|| cmd.starts_with("teleport ")
|
||||||
|
|| is_partial_mod
|
||||||
{
|
{
|
||||||
set_command_mode.set(CommandMode::ShowingSlashHint);
|
set_command_mode.set(CommandMode::ShowingSlashHint);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -826,17 +833,25 @@ pub fn ChatInput(
|
||||||
<span class="text-blue-400">"t"</span>
|
<span class="text-blue-400">"t"</span>
|
||||||
<span class="text-gray-500">"[eleport]"</span>
|
<span class="text-gray-500">"[eleport]"</span>
|
||||||
</Show>
|
</Show>
|
||||||
|
// Show /mod hint for moderators (details shown when typing /mod)
|
||||||
|
<Show when=move || is_moderator.get()>
|
||||||
|
<span class="text-gray-600 mx-2">"|"</span>
|
||||||
|
<span class="text-purple-400">"/"</span>
|
||||||
|
<span class="text-purple-400">"mod"</span>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
// Mod command hint bar (/mod summon [nick|*])
|
// Mod command hint bar (shown when typing /mod)
|
||||||
<Show when=move || command_mode.get() == CommandMode::ShowingModHint>
|
<Show when=move || command_mode.get() == CommandMode::ShowingModHint>
|
||||||
<div class="absolute bottom-full left-0 mb-1 px-3 py-1 bg-purple-800/90 backdrop-blur-sm rounded text-sm">
|
<div class="absolute bottom-full left-0 mb-1 px-3 py-1 bg-purple-900/90 backdrop-blur-sm rounded text-sm">
|
||||||
<span class="text-purple-300 font-medium">"[MOD] "</span>
|
<span class="text-purple-400">"/"</span>
|
||||||
<span class="text-gray-400">"/"</span>
|
|
||||||
<span class="text-purple-400">"mod"</span>
|
<span class="text-purple-400">"mod"</span>
|
||||||
<span class="text-gray-300">" summon"</span>
|
<span class="text-purple-300">" summon"</span>
|
||||||
<span class="text-gray-500">" [nick|*]"</span>
|
<span class="text-purple-500">" [nick|*]"</span>
|
||||||
|
<span class="text-purple-600">" | "</span>
|
||||||
|
<span class="text-purple-300">"teleport"</span>
|
||||||
|
<span class="text-purple-500">" [nick] [slug]"</span>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue