manage.sh controllers: identify clients by live session IP, not opaque ID
Confirmed live: the paired-clients list is a wall of meaningless cert-derived numbers with nothing human-readable attached (verified against Wolf's own PairedClient API schema - no name, no IP field exists there at all), so there was no way to tell which entry was the user's actual device. Made worse by Wolf not deduping repeated pairings of the same device (the user's real box showed the same client_id 6 times). Fix: cross-reference against GET /api/v1/sessions, which DOES carry client_ip for every currently-streaming session, and tag each paired entry as "ACTIVE - streaming from <ip>" when it matches one. When exactly one client is actively streaming, it's now auto-selected with no prompt - the practical case for a single-user setup. Falls back to the manual picker when nothing's active or multiple clients are (now showing which IP is which, so the choice is no longer a guess). Verified against the user's real duplicate-heavy client list plus mocked active- session data covering: single active session (auto-select), no active sessions (manual fallback), and two distinct active sessions (manual fallback with both IPs shown). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VLX1yYKJExGSXmgUhxKQG6
This commit is contained in:
+62
-7
@@ -3353,6 +3353,15 @@ COMPEOF
|
||||
echo "Could not reach Wolf's API — is Wolf running? (./manage.sh status)"
|
||||
exit 1
|
||||
fi
|
||||
# A bare client_id list is useless for telling devices apart — it's
|
||||
# an opaque cert-derived number with nothing human-readable attached
|
||||
# (confirmed against Wolf's own PairedClient API schema: no name, no
|
||||
# IP, nothing). GET /api/v1/sessions DOES carry client_ip for every
|
||||
# currently-streaming session though, so cross-referencing the two
|
||||
# lets us tag whichever entry is actually connected right now with
|
||||
# its real IP — the one piece of info a person can actually
|
||||
# recognize ("oh, that's my gaming PC").
|
||||
SESSIONS_JSON=$(sudo curl -fsS --unix-socket "$SOCK" http://localhost/api/v1/sessions 2>/dev/null)
|
||||
|
||||
CLIENT_IDS=()
|
||||
while IFS= read -r cid; do CLIENT_IDS+=("$cid"); done < <(echo "$CLIENTS_JSON" | python3 -c "
|
||||
@@ -3366,15 +3375,48 @@ for c in json.load(sys.stdin)['clients']:
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Paired clients:"
|
||||
echo "Paired clients (ACTIVE = streaming from this IP right now — the"
|
||||
echo "reliable way to tell which entry is yours. If nothing shows"
|
||||
echo "ACTIVE, start streaming from the device you want to configure,"
|
||||
echo "leave it connected, and re-run this in another terminal):"
|
||||
echo "$CLIENTS_JSON" | python3 -c "
|
||||
import json, sys
|
||||
d = json.load(sys.stdin)
|
||||
try:
|
||||
active = {s['client_id']: s['client_ip'] for s in json.loads(sys.argv[1]).get('sessions', []) if s.get('client_id')}
|
||||
except Exception:
|
||||
active = {}
|
||||
for i, c in enumerate(d['clients']):
|
||||
ov = c['settings'].get('controllers_override') or []
|
||||
print(f\" {i+1}) {c['client_id']} (current: {ov if ov else 'none - auto-detect'})\")
|
||||
"
|
||||
if [ "${#CLIENT_IDS[@]}" -eq 1 ]; then
|
||||
cid = c['client_id']
|
||||
tag = 'ACTIVE - streaming from ' + active[cid] if cid in active else 'not currently connected'
|
||||
print(f\" {i+1}) {cid} [{tag}]\")
|
||||
print(f\" current override: {ov if ov else 'none - auto-detect'}\")
|
||||
" "$SESSIONS_JSON"
|
||||
DUP_COUNT=$(printf '%s\n' "${CLIENT_IDS[@]}" | sort | uniq -d | wc -l)
|
||||
if [ "$DUP_COUNT" -gt 0 ]; then
|
||||
echo ""
|
||||
echo "Note: some client_ids above are repeated — the same device was"
|
||||
echo "paired more than once (each pairing gets its own entry, Wolf"
|
||||
echo "doesn't dedupe). Harmless, but if you want a clean list, forget"
|
||||
echo "/ re-pair this PC from Moonlight's own settings on the client."
|
||||
fi
|
||||
|
||||
ACTIVE_CLIENT_ID=$(python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
sessions = json.loads(sys.argv[1]).get('sessions', [])
|
||||
except Exception:
|
||||
sessions = []
|
||||
ids = {s['client_id'] for s in sessions if s.get('client_id')}
|
||||
print(next(iter(ids)) if len(ids) == 1 else '')
|
||||
" "$SESSIONS_JSON")
|
||||
|
||||
if [ -n "$ACTIVE_CLIENT_ID" ]; then
|
||||
CLIENT_ID="$ACTIVE_CLIENT_ID"
|
||||
echo ""
|
||||
echo "Exactly one client is actively streaming right now — using that one."
|
||||
elif [ "${#CLIENT_IDS[@]}" -eq 1 ]; then
|
||||
CLIENT_ID="${CLIENT_IDS[0]}"
|
||||
echo ""
|
||||
echo "Only one paired client — using it."
|
||||
@@ -4052,9 +4094,22 @@ itself runs as root in its container), so the curl calls behind this
|
||||
command need it, the same as every other command here that touches
|
||||
Wolf's own root-owned state.
|
||||
|
||||
Picks your paired Moonlight client (auto-selected if there's only one),
|
||||
then asks how many controllers to configure and what type to force each
|
||||
one to. There are only **3 concrete types** (confirmed against Wolf's own
|
||||
**Identifying which paired client is actually yours:** a bare list of
|
||||
paired clients is a wall of meaningless numbers (Wolf's own API exposes
|
||||
no name/IP for a paired-but-not-currently-streaming client) — so this
|
||||
cross-references Wolf's live sessions list too and tags whichever entry
|
||||
is actively streaming right now with its real IP address, e.g.
|
||||
\`ACTIVE - streaming from 192.168.1.42\`. If exactly one client is active
|
||||
it's used automatically with no prompt. **For the clearest result: start
|
||||
streaming from the device you want to configure, leave it connected, and
|
||||
run this command while it's still connected** — then there's no
|
||||
guessing. It's also normal to see the same client_id listed more than
|
||||
once (Wolf doesn't dedupe repeated pairings of the same device) — every
|
||||
duplicate of an active ID is tagged ACTIVE together, so it doesn't matter
|
||||
which one you'd have picked by hand.
|
||||
|
||||
Then it asks how many controllers to configure and what type to force
|
||||
each one to. There are only **3 concrete types** (confirmed against Wolf's own
|
||||
virtual-pad source, \`inputtino\`) — not one per real controller brand:
|
||||
- \`XBOX\` → an **Xbox One** controller specifically (not Series/360)
|
||||
- \`PS\` → a **PlayStation 5 DualSense** specifically (no separate PS4 option)
|
||||
|
||||
Reference in New Issue
Block a user