fix: let voice/mute/kick/detach take --party

A host of two or more parties was told 'pass a name' by commands that
accepted no name flag, making moderation impossible. Mirrors the
--party flag invite already had.
This commit is contained in:
veg 2026-07-04 09:14:19 +00:00
parent 9117f73423
commit fc366f48fa
2 changed files with 71 additions and 22 deletions

66
party
View file

@ -1034,19 +1034,43 @@ EOF
echo "Invited $user to '$RR_PARTY_NAME'." echo "Invited $user to '$RR_PARTY_NAME'."
} }
# Toggle a user's read/write status. $1 = subcommand label (for usage # Parse the "<user> [--party <name>]" argv shared by voice/mute/kick/
# and the success message), $2 = server-access flag (-w voice, -r mute), # detach. Sets mod_user and mod_party in the calling shell (POSIX sh
# $3 = past-participle for the message, $4 = $user. # has no locals; the mod_ prefix keeps them out of callers' way).
_set_user_access() { # Exits 2 on usage errors.
label="$1" flag="$2" verb="$3" user="$4" _parse_user_party() {
[ -n "$user" ] || { echo "Usage: party $label <user>" >&2; exit 2; } label="$1"; shift
resolve_authoritative_party "" || exit 1 mod_user='' mod_party=''
"$PARTY_TMUX" -S "$RR_SOCKET" server-access "$flag" "$user" while [ $# -gt 0 ]; do
echo "$verb $user." case "$1" in
--party)
[ $# -ge 2 ] || { echo "party $label: --party needs an argument" >&2; exit 2; }
mod_party="$2"; shift 2 ;;
-h|--help)
echo "Usage: party $label <user> [--party <name>]"; exit 0 ;;
-*) echo "party $label: unknown flag '$1'" >&2; exit 2 ;;
*)
if [ -z "$mod_user" ]; then mod_user="$1"; shift
else echo "party $label: unexpected arg '$1'" >&2; exit 2; fi
;;
esac
done
[ -n "$mod_user" ] || { echo "Usage: party $label <user> [--party <name>]" >&2; exit 2; }
} }
cmd_voice() { _set_user_access voice -w Voiced "${1:-}"; } # Toggle a user's read/write status. $1 = subcommand label (for usage
cmd_mute() { _set_user_access mute -r Muted "${1:-}"; } # and the success message), $2 = server-access flag (-w voice, -r mute),
# $3 = past-participle for the message; the rest is the user's argv.
_set_user_access() {
label="$1" flag="$2" verb="$3"; shift 3
_parse_user_party "$label" "$@"
resolve_authoritative_party "$mod_party" || exit 1
"$PARTY_TMUX" -S "$RR_SOCKET" server-access "$flag" "$mod_user"
echo "$verb $mod_user."
}
cmd_voice() { _set_user_access voice -w Voiced "$@"; }
cmd_mute() { _set_user_access mute -r Muted "$@"; }
# Disconnect every client of $user on the resolved party socket and kill # Disconnect every client of $user on the resolved party socket and kill
# their guest session if present. Used by both cmd_kick and cmd_detach. # their guest session if present. Used by both cmd_kick and cmd_detach.
@ -1061,20 +1085,18 @@ _disconnect_user() {
} }
cmd_kick() { cmd_kick() {
user="${1:-}" _parse_user_party kick "$@"
[ -n "$user" ] || { echo "Usage: party kick <user>" >&2; exit 2; } resolve_authoritative_party "$mod_party" || exit 1
resolve_authoritative_party "" || exit 1 "$PARTY_TMUX" -S "$RR_SOCKET" server-access -d "$mod_user" 2>/dev/null || true
"$PARTY_TMUX" -S "$RR_SOCKET" server-access -d "$user" 2>/dev/null || true _disconnect_user "$mod_user"
_disconnect_user "$user" echo "Kicked $mod_user."
echo "Kicked $user."
} }
cmd_detach() { cmd_detach() {
user="${1:-}" _parse_user_party detach "$@"
[ -n "$user" ] || { echo "Usage: party detach <user>" >&2; exit 2; } resolve_authoritative_party "$mod_party" || exit 1
resolve_authoritative_party "" || exit 1 _disconnect_user "$mod_user"
_disconnect_user "$user" echo "Detached $mod_user (still on allowlist)."
echo "Detached $user (still on allowlist)."
} }
cmd_list() { cmd_list() {

View file

@ -810,3 +810,30 @@ STUB
! grep -q "server-access -aw $USER" "$TMUX_LOG" || \ ! grep -q "server-access -aw $USER" "$TMUX_LOG" || \
fail "should not have attempted -aw before capability check" fail "should not have attempted -aw before capability check"
} }
@test "moderation accepts --party to disambiguate multiple hosted parties" {
"$PARTY_BIN" host alpha
"$PARTY_BIN" host bravo
# Without --party: ambiguous, must refuse and say so.
run "$PARTY_BIN" kick nobody
[ "$status" -ne 0 ]
[[ "$output" == *"multiple parties"* ]]
# With --party: resolves, and the server-access -d lands on bravo's
# socket specifically.
: > "$TMUX_LOG"
run "$PARTY_BIN" kick nobody --party bravo
[ "$status" -eq 0 ]
grep "server-access -d nobody" "$TMUX_LOG" | grep -q "party-$USER:bravo.d/sock"
: > "$TMUX_LOG"
run "$PARTY_BIN" voice nobody --party alpha
[ "$status" -eq 0 ]
grep "server-access -w nobody" "$TMUX_LOG" | grep -q "party-$USER:alpha.d/sock"
run "$PARTY_BIN" mute nobody --party alpha
[ "$status" -eq 0 ]
run "$PARTY_BIN" detach nobody --party alpha
[ "$status" -eq 0 ]
}