Changeset 2826bb97 in Klonkt


Ignore:
Timestamp:
06/24/2026 12:52:51 PM (3 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
7f46112b
Parents:
594cc50
Message:

feat(activitypub): full post on reply page + strip audio shortcodes from federation

buildNote strips album|playlist shortcodes (they federated raw).
resolveRemoteNote returns the full sanitized content + image attachments; the
authorize_interaction compose page shows the whole post + images + a 'view full
post + comments on the source' link.

Co-Authored-By: Claude <noreply@…>

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/services/ActivityPubService.js

    r594cc50 r2826bb97  
    121121  for (const m of body.matchAll(/<img\b[^>]*\bsrc="([^"]+)"[^>]*>/gi)) urls.push(abs(m[1]));
    122122  body = body.replace(/<img\b[^>]*>/gi, '');
     123  // Strip Klonkt audio shortcodes ([[track:…]] etc.) — they'd federate raw as
     124  // ugly text (audio federation itself is a later phase).
     125  body = body.replace(/\[\[(track|album|playlist):[^\]]+\]\]/gi, '');
    123126  const seen = new Set();
    124127  const attachment = urls.filter(Boolean)
     
    488491  const actor = await fetchActor(actorUri).catch(() => null);
    489492  const ai = actorInfo(actor, actorUri);
     493  const rawHtml = String(note.content || '').replace(/\[\[(track|album|playlist):[^\]]+\]\]/gi, '');
     494  const images = (Array.isArray(note.attachment) ? note.attachment : [])
     495    .filter((a) => a && a.url && (!a.mediaType || /^image\//i.test(a.mediaType)))
     496    .map((a) => a.url);
    490497  return {
    491498    object_uri: note.id,
     
    495502    actor_name: ai.name,
    496503    actor_icon: ai.icon,
     504    url: note.url || url,
     505    content: HtmlSanitizerService.sanitize(rawHtml),       // full, sanitized
     506    images,
    497507    preview: HtmlSanitizerService.toPlainText(note.content || '').slice(0, 240),
    498508  };
  • src/services/i18n.js

    r594cc50 r2826bb97  
    109109    'fedi.heading': 'Vanuit de fediverse', 'fedi.likes': 'sterren', 'fedi.boosts': 'boosts', 'fedi.replies': 'Reacties uit de fediverse',
    110110    'fedi.reply': 'Reageer', 'fedi.reply_ph': 'Je antwoord aan de fediverse…', 'fedi.send': 'Versturen', 'fedi.you': 'Jij',
    111     'fedi.remote_title': 'Reageer via de fediverse', 'fedi.remote_reply': 'Reageer via de fediverse', 'fedi.remote_prompt': 'Je fediverse-adres (bv. @jij@mastodon.social):', 'fedi.remote_notfound': 'Kon die post niet ophalen. Plak de volledige post-URL:', 'fedi.remote_load': 'Ophalen', 'fedi.remote_replying_to': 'Je reageert op', 'fedi.remote_as': 'Wordt verzonden als {site}.',
     111    'fedi.remote_title': 'Reageer via de fediverse', 'fedi.remote_reply': 'Reageer via de fediverse', 'fedi.remote_prompt': 'Je fediverse-adres (bv. @jij@mastodon.social):', 'fedi.remote_notfound': 'Kon die post niet ophalen. Plak de volledige post-URL:', 'fedi.remote_load': 'Ophalen', 'fedi.remote_replying_to': 'Je reageert op', 'fedi.remote_as': 'Wordt verzonden als {site}.', 'fedi.remote_view_original': 'Bekijk de hele post + reacties op de bron →',
    112112    'comments.to_start': 'om de conversatie te starten.',
    113113    'comments.reply': 'Reageer', 'comments.delete': 'Verwijder', 'comments.cancel': 'Annuleren',
     
    11041104    'fedi.heading': 'From the fediverse', 'fedi.likes': 'favourites', 'fedi.boosts': 'boosts', 'fedi.replies': 'Replies from the fediverse',
    11051105    'fedi.reply': 'Reply', 'fedi.reply_ph': 'Your reply to the fediverse…', 'fedi.send': 'Send', 'fedi.you': 'You',
    1106     'fedi.remote_title': 'Reply via the fediverse', 'fedi.remote_reply': 'Reply via the fediverse', 'fedi.remote_prompt': 'Your fediverse address (e.g. @you@mastodon.social):', 'fedi.remote_notfound': 'Could not fetch that post. Paste the full post URL:', 'fedi.remote_load': 'Fetch', 'fedi.remote_replying_to': 'Replying to', 'fedi.remote_as': 'Sent as {site}.',
     1106    'fedi.remote_title': 'Reply via the fediverse', 'fedi.remote_reply': 'Reply via the fediverse', 'fedi.remote_prompt': 'Your fediverse address (e.g. @you@mastodon.social):', 'fedi.remote_notfound': 'Could not fetch that post. Paste the full post URL:', 'fedi.remote_load': 'Fetch', 'fedi.remote_replying_to': 'Replying to', 'fedi.remote_as': 'Sent as {site}.', 'fedi.remote_view_original': 'View the full post + comments on the source →',
    11071107    'comments.to_start': 'to start the conversation.',
    11081108    'comments.reply': 'Reply', 'comments.delete': 'Delete', 'comments.cancel': 'Cancel',
     
    20972097    'fedi.heading': 'Aus dem Fediverse', 'fedi.likes': 'Favoriten', 'fedi.boosts': 'Boosts', 'fedi.replies': 'Antworten aus dem Fediverse',
    20982098    'fedi.reply': 'Antworten', 'fedi.reply_ph': 'Deine Antwort an das Fediverse…', 'fedi.send': 'Senden', 'fedi.you': 'Du',
    2099     'fedi.remote_title': 'Über das Fediverse antworten', 'fedi.remote_reply': 'Über das Fediverse antworten', 'fedi.remote_prompt': 'Deine Fediverse-Adresse (z.B. @du@mastodon.social):', 'fedi.remote_notfound': 'Beitrag konnte nicht geladen werden. Füge die vollständige Beitrags-URL ein:', 'fedi.remote_load': 'Laden', 'fedi.remote_replying_to': 'Antwort an', 'fedi.remote_as': 'Wird als {site} gesendet.',
     2099    'fedi.remote_title': 'Über das Fediverse antworten', 'fedi.remote_reply': 'Über das Fediverse antworten', 'fedi.remote_prompt': 'Deine Fediverse-Adresse (z.B. @du@mastodon.social):', 'fedi.remote_notfound': 'Beitrag konnte nicht geladen werden. Füge die vollständige Beitrags-URL ein:', 'fedi.remote_load': 'Laden', 'fedi.remote_replying_to': 'Antwort an', 'fedi.remote_as': 'Wird als {site} gesendet.', 'fedi.remote_view_original': 'Ganzen Beitrag + Kommentare an der Quelle ansehen →',
    21002100    'comments.to_start': 'um das Gespräch zu starten.',
    21012101    'comments.reply': 'Antworten', 'comments.delete': 'Löschen', 'comments.cancel': 'Abbrechen',
  • src/views/pages/authorize-interaction.ejs

    r594cc50 r2826bb97  
    1414      <span class="fedi-handle"><%= target.actor_handle %></span>
    1515    </p>
    16     <% if (target.preview) { %>
    17       <blockquote class="auth-interact-preview"><%= target.preview %></blockquote>
    18     <% } %>
     16    <blockquote class="auth-interact-preview">
     17      <% if (target.content) { %><div class="auth-interact-content"><%- target.content %></div>
     18      <% } else if (target.preview) { %><%= target.preview %><% } %>
     19      <% (target.images || []).forEach(function(im){ %>
     20        <img class="auth-interact-img" src="<%= im %>" alt="" loading="lazy">
     21      <% }); %>
     22      <% if (target.url || uri) { %>
     23        <p class="auth-interact-orig"><a href="<%= target.url || uri %>" target="_blank" rel="nofollow noopener"><%= t('fedi.remote_view_original') %></a></p>
     24      <% } %>
     25    </blockquote>
    1926    <form method="post" action="/authorize_interaction" class="auth-interact-form">
    2027      <input type="hidden" name="uri" value="<%= uri %>">
     
    4653  .auth-interact-actions { display: flex; gap: .5rem; align-items: center; }
    4754  .auth-interact-note { color: var(--ink-soft, #999); font-size: .85rem; margin-top: 1rem; }
     55  .auth-interact-content { line-height: 1.55; }
     56  .auth-interact-content p { margin: .35rem 0; }
     57  .auth-interact-content p:first-child { margin-top: 0; }
     58  .auth-interact-img { max-width: 100%; height: auto; border-radius: 10px; margin: .5rem 0 0; display: block; }
     59  .auth-interact-orig { margin: .75rem 0 0; font-size: .85rem; }
     60  .auth-interact-orig a { color: var(--accent, #06c); }
    4861</style>
Note: See TracChangeset for help on using the changeset viewer.