Changeset 3d7312a in Klonkt for src/routes/posts.js


Ignore:
Timestamp:
06/24/2026 12:44:21 PM (3 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
594cc50
Parents:
82079ad
Message:

feat(activitypub): remote interaction — reply to any fediverse post from your own server

Standard 'reply from your own server' flow: every post page has a 'Reply via the
fediverse' button that bounces the visitor to their home server's
/authorize_interaction?uri=. Klonkt implements that endpoint: the site owner
composes a reply that's resolved (resolveRemoteNote) + federated back to the
remote post as the site actor. Works Klonkt<->Klonkt and with Mastodon.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/posts.js

    r82079ad r3d7312a  
    8686  'tag', 'type', 'user', 'users', 'artiesten', 'leden', 'favorieten', 'feed.xml', 'atom.xml', 'sitemap.xml',
    8787  'manifest.webmanifest', 'sw.js', 'favicon.ico', 'favicon.svg', 'assets',
     88  'authorize_interaction',
    8889]);
    8990
     
    509510  return { newerPost, olderPost };
    510511}
     512
     513// ==================== REMOTE INTERACTION (reply to a fediverse post as your site) ====================
     514// Standard fediverse "reply from your own server" landing endpoint. A post page
     515// elsewhere bounces the visitor here with ?uri=<remote post>; the site owner
     516// composes a reply that federates back to that post.
     517router.get('/authorize_interaction', requireSiteManager, async (req, res) => {
     518  const site = res.locals.site;
     519  const uri = (req.query.uri || '').toString();
     520  let target = null;
     521  try { target = await ActivityPubService.resolveRemoteNote(uri); } catch { /* ignore */ }
     522  renderPage(req, res, 'pages/authorize-interaction', {
     523    pageTitle: 'Reageer via de fediverse',
     524    bodyClass: 'on-special',
     525    uri,
     526    target,
     527    siteTitle: site ? site.title : '',
     528  });
     529});
     530
     531router.post('/authorize_interaction', requireSiteManager, async (req, res) => {
     532  const site = res.locals.site;
     533  const uri = (req.body.uri || '').toString();
     534  const text = (req.body.text || '').toString();
     535  if (site && uri && text.trim()) {
     536    try {
     537      const parent = await ActivityPubService.resolveRemoteNote(uri);
     538      if (parent) await ActivityPubService.deliverReply(site, { postId: '', postSlug: null, parent, text });
     539    } catch (e) { console.warn('[AP] remote reply failed:', e.message); }
     540  }
     541  // Send them to the post they replied to so they can see the thread.
     542  res.redirect(uri && /^https?:\/\//i.test(uri) ? uri : (res.locals.siteUrlBase || '/'));
     543});
    511544
    512545// ==================== VIEW POST (last route — catches /:slug) ====================
Note: See TracChangeset for help on using the changeset viewer.