harness-base: matrix-avatar-sync oneshot mirroring forge avatar (#548 phase 2.5)
This commit is contained in:
parent
666c32ae65
commit
7e041e6079
1 changed files with 96 additions and 0 deletions
|
|
@ -745,6 +745,102 @@
|
|||
'';
|
||||
};
|
||||
|
||||
# One-shot: upload the agent's configured icon to its matrix profile
|
||||
# avatar so the icon shows up next to messages in matrix rooms (#548
|
||||
# phase 2.5). Mirrors the forge-avatar-sync flow above, only differs
|
||||
# in protocol: matrix avatars are a two-step `media upload` → `set
|
||||
# avatar_url` dance, both authenticated by the access_token written
|
||||
# by hive-c0re's `matrix::ensure_user_for`. No-op when the icon
|
||||
# isn't configured, the matrix token isn't present, or the
|
||||
# homeserver isn't reachable. *Always* exits 0.
|
||||
systemd.services.matrix-avatar-sync = {
|
||||
description = "sync agent icon to matrix profile avatar (best-effort)";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
# No `after = [ "tea-login.service" ]` — matrix has no
|
||||
# equivalent prerequisite; we just need the homeserver up.
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
path = [
|
||||
pkgs.curl
|
||||
pkgs.coreutils
|
||||
pkgs.jq
|
||||
pkgs.librsvg
|
||||
];
|
||||
script = ''
|
||||
ICON=/etc/hyperhive/icon.svg
|
||||
if [ ! -f "$ICON" ]; then
|
||||
echo "matrix-avatar-sync: no icon configured; skipping"
|
||||
exit 0
|
||||
fi
|
||||
# Token written by `hive-c0re::matrix::ensure_user_for` to the
|
||||
# agent's bind-mounted state dir. Either appears at the legacy
|
||||
# `/state/` (manager) or per-agent `/agents/<name>/state/` path.
|
||||
TOKEN_FILE=""
|
||||
for f in /state/matrix-token /agents/*/state/matrix-token; do
|
||||
if [ -f "$f" ]; then
|
||||
TOKEN_FILE="$f"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$TOKEN_FILE" ]; then
|
||||
echo "matrix-avatar-sync: no matrix-token found; skipping"
|
||||
exit 0
|
||||
fi
|
||||
TOKEN=$(cat "$TOKEN_FILE")
|
||||
# Local tuwunel reachable on shared host netns at the
|
||||
# default matrix-spec port. Override via the future
|
||||
# `hyperhive.matrix.url` if the operator ever runs the
|
||||
# homeserver elsewhere (deferred to #548 phase 4).
|
||||
MATRIX_URL=http://localhost:8008
|
||||
# whoami → user_id. Needed to scope the avatar set call.
|
||||
# Tolerant of the homeserver being unreachable (`-f` makes
|
||||
# curl fail on 4xx/5xx; `|| true` swallows the exit).
|
||||
USER_ID=$(curl -sf --max-time 5 \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
"$MATRIX_URL/_matrix/client/v3/account/whoami" 2>/dev/null \
|
||||
| jq -r '.user_id // empty' || true)
|
||||
if [ -z "$USER_ID" ]; then
|
||||
echo "matrix-avatar-sync: whoami failed or homeserver unreachable; skipping"
|
||||
exit 0
|
||||
fi
|
||||
# Rasterize SVG → PNG (matrix media accepts any image type
|
||||
# but we already standardise on PNG for the forge sync).
|
||||
PNG=$(mktemp --suffix=.png)
|
||||
if ! rsvg-convert -f png -w 512 -h 512 "$ICON" -o "$PNG" 2>/dev/null; then
|
||||
echo "matrix-avatar-sync: rsvg-convert failed; skipping"
|
||||
rm -f "$PNG"
|
||||
exit 0
|
||||
fi
|
||||
# Step 1: upload bytes → mxc:// URI.
|
||||
MXC=$(curl -sf --max-time 10 \
|
||||
-X POST "$MATRIX_URL/_matrix/media/v3/upload" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: image/png" \
|
||||
--data-binary "@$PNG" 2>/dev/null \
|
||||
| jq -r '.content_uri // empty' || true)
|
||||
rm -f "$PNG"
|
||||
if [ -z "$MXC" ]; then
|
||||
echo "matrix-avatar-sync: media upload failed; skipping"
|
||||
exit 0
|
||||
fi
|
||||
# Step 2: set avatar_url on the profile.
|
||||
PAYLOAD=$(jq -n --arg url "$MXC" '{avatar_url:$url}')
|
||||
CODE=$(curl -s --max-time 10 \
|
||||
-X PUT "$MATRIX_URL/_matrix/client/v3/profile/$USER_ID/avatar_url" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD" \
|
||||
-o /dev/null -w "%{http_code}" 2>/dev/null || true)
|
||||
if [ "$CODE" = "200" ]; then
|
||||
echo "matrix-avatar-sync: avatar set on $USER_ID"
|
||||
else
|
||||
echo "matrix-avatar-sync: avatar PUT returned HTTP $CODE — skipping (non-fatal)"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Write declared dashboardLinks to the state dir so hive-c0re can read
|
||||
# them without accessing the container's /etc/ from the host.
|
||||
# Runs every boot; idempotent (overwrite). Always exits 0.
|
||||
|
|
|
|||
Loading…
Reference in a new issue