feat: merge upstream v3.7.1–v3.7.5 into svemagie/main

All five 3.7.x releases published 2026-03-21 in one pass.

Changes from upstream:

- lib/lookup-helpers.js: lookupWithSecurity → async with signed→unsigned
  fallback (handles servers like tags.pub that return 400 on signed GETs)

- lib/mastodon/helpers/account-cache.js: add reverse lookup map
  (hashId → actorUrl) populated by cacheAccountStats(); export
  getActorUrlFromId() for follow/unfollow resolution

- lib/mastodon/helpers/enrich-accounts.js: NEW — enrichAccountStats()
  enriches embedded account objects in serialized statuses with real
  follower/following/post counts; Phanpy never calls /accounts/:id so
  counts were always 0 without this

- lib/mastodon/routes/timelines.js: call enrichAccountStats() after
  serialising home, public, and hashtag timelines

- lib/mastodon/routes/statuses.js: processStatusContent() linkifies bare
  URLs and converts @user@domain mentions to <a> links; extractMentions()
  builds mention list; date lookup now tries both .000Z and bare Z suffixes

- lib/mastodon/routes/stubs.js: /api/v1/domain_blocks now returns real
  blocked-server hostnames from ap_blocked_servers instead of []

- lib/mastodon/routes/accounts.js: /accounts/relationships computes
  domain_blocking using ap_blocked_servers; resolveActorUrl() falls back
  to getActorUrlFromId() cache for timeline-author resolution

- lib/controllers/federation-mgmt.js: fetch blocked servers, blocked
  accounts, and muted accounts in parallel; pass to template

- views/activitypub-federation-mgmt.njk: add Moderation section showing
  blocked servers, blocked accounts, and muted accounts

- package.json: bump version 3.6.8 → 3.7.5

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
svemagie
2026-03-21 20:22:04 +01:00
parent f029c3128e
commit 97a902bda1
10 changed files with 324 additions and 15 deletions

View File

@@ -116,6 +116,53 @@
{% endif %}
</section>
{# --- Moderation Overview --- #}
<section class="ap-federation__section">
<h2>Moderation</h2>
{% if blockedServers.length > 0 %}
<h3>Blocked servers ({{ blockedServers.length }})</h3>
<div class="ap-federation__stats-grid">
{% for server in blockedServers %}
<div class="ap-federation__stat-card">
<span class="ap-federation__stat-label">🚫 {{ server.hostname }}</span>
{% if server.blockedAt %}
<span class="ap-federation__stat-count" style="font-size: 0.75rem; opacity: 0.7">{{ server.blockedAt | date("PPp") }}</span>
{% endif %}
</div>
{% endfor %}
</div>
{% else %}
{{ prose({ text: "No servers blocked." }) }}
{% endif %}
{% if blockedAccounts.length > 0 %}
<h3>Blocked accounts ({{ blockedAccounts.length }})</h3>
<div class="ap-federation__stats-grid">
{% for account in blockedAccounts %}
<div class="ap-federation__stat-card">
<span class="ap-federation__stat-label">🚫 {{ account.url or account.handle or "Unknown" }}</span>
{% if account.blockedAt %}
<span class="ap-federation__stat-count" style="font-size: 0.75rem; opacity: 0.7">{{ account.blockedAt | date("PPp") }}</span>
{% endif %}
</div>
{% endfor %}
</div>
{% else %}
{{ prose({ text: "No accounts blocked." }) }}
{% endif %}
{% if mutedAccounts.length > 0 %}
<h3>Muted ({{ mutedAccounts.length }})</h3>
<div class="ap-federation__stats-grid">
{% for muted in mutedAccounts %}
<div class="ap-federation__stat-card">
<span class="ap-federation__stat-label">🔇 {{ muted.url or muted.keyword or "Unknown" }}</span>
</div>
{% endfor %}
</div>
{% endif %}
</section>
{# --- JSON Modal --- #}
<div class="ap-federation__modal-overlay" x-show="jsonModalOpen" x-cloak
@click.self="jsonModalOpen = false" @keydown.escape.window="jsonModalOpen = false">