Changeset b7d4458 in Klonkt for src/routes


Ignore:
Timestamp:
06/27/2026 08:10:43 AM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
c21197a
Parents:
92f6976
Message:

feat(nsfw): custom content-warning text + blur in the Cirkel

  • Per-post content-warning text (like Mastodon): editor field; used as the on-site veil/banner label and the fediverse Note summary (falls back to 'Gevoelige inhoud').
  • Cirkel feed now blurs remote sensitive posts: ap_timeline gets nsfw+cw (captured from the incoming Note's sensitive/summary), getCirkelPosts returns them, circle.js maps them so post-card/tile show the veil.
Location:
src/routes
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/routes/activitypub.js

    r92f6976 rb7d4458  
    6767  if (!site) return res.status(404).end();
    6868  const posts = db.prepare(
    69     `SELECT id, slug, title, content, cover_image_url, nsfw, published_at, created_at
     69    `SELECT id, slug, title, content, cover_image_url, nsfw, content_warning, published_at, created_at
    7070     FROM posts WHERE site_id = ? AND status = 'published' AND (fan_only IS NULL OR fan_only = 0)
    7171     ORDER BY COALESCE(published_at, created_at) DESC LIMIT 20`
     
    9090  // rank 1 last) → Mastodon flips it back to pin-rank ascending on the profile.
    9191  const posts = db.prepare(
    92     `SELECT id, slug, title, content, cover_image_url, nsfw, published_at, created_at
     92    `SELECT id, slug, title, content, cover_image_url, nsfw, content_warning, published_at, created_at
    9393     FROM posts WHERE site_id = ? AND status = 'published' AND (fan_only IS NULL OR fan_only = 0)
    9494       AND pinned IS NOT NULL AND pinned > 0
  • src/routes/circle.js

    r92f6976 rb7d4458  
    5353      pinned: 0,
    5454      isBoost: !!r.boosted, // a post YOU boosted → render in the pinned style with a Boost badge
     55      nsfw: r.nsfw ? 1 : 0, // remote sensitive post → blur in the Cirkel (post-card/tile)
     56      content_warning: r.cw || '',
    5557      status: 'published',
    5658      source_name: name,
  • src/routes/posts.js

    r92f6976 rb7d4458  
    177177  const fanOnly = req.body.fan_only ? 1 : 0;
    178178  const nsfw = req.body.nsfw ? 1 : 0;
     179  const cw = (req.body.content_warning || '').trim().slice(0, 200);
    179180
    180181  // Content arrives as user-authored HTML from the WYSIWYG editor — sanitize
     
    214215    INSERT INTO posts (
    215216      id, site_id, slug, author_id, title, content, excerpt,
    216       status, cover_image_url, pinned, tags, type, noindex, fan_only, nsfw, publish_at,
     217      status, cover_image_url, pinned, tags, type, noindex, fan_only, nsfw, content_warning, publish_at,
    217218      created_at, updated_at, published_at
    218     ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
     219    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    219220  `).run(
    220221    postId, site.id, finalSlug, req.session.user.id,
     
    222223    finalStatus, cover_image_url || null, parsePinnedRank(pinned),
    223224    JSON.stringify((tags || '').split(',').map(t => t.trim()).filter(Boolean)),
    224     finalType, noindex ? 1 : 0, fanOnly, nsfw, publishAt,
     225    finalType, noindex ? 1 : 0, fanOnly, nsfw, cw, publishAt,
    225226    now, now, publishedAt
    226227  );
     
    239240        id: postId, slug: finalSlug, title: title || finalSlug,
    240241        content: cleanContent, cover_image_url: cover_image_url || null,
    241         published_at: publishedAt, created_at: now, fan_only: fanOnly, nsfw,
     242        published_at: publishedAt, created_at: now, fan_only: fanOnly, nsfw, content_warning: cw,
    242243      }).catch(() => { /* best-effort */ });
    243244    }
     
    298299  const fanOnly = req.body.fan_only ? 1 : 0;
    299300  const nsfw = req.body.nsfw ? 1 : 0;
     301  const cw = (req.body.content_warning || '').trim().slice(0, 200);
    300302  const newSlug = req.body.slug;
    301303  const action = req.body.action || 'save';
     
    336338      title = ?, content = ?, excerpt = ?, status = ?,
    337339      cover_image_url = ?, pinned = ?, tags = ?,
    338       type = ?, noindex = ?, fan_only = ?, nsfw = ?, publish_at = ?,
     340      type = ?, noindex = ?, fan_only = ?, nsfw = ?, content_warning = ?, publish_at = ?,
    339341      slug = ?, published_at = ?, updated_at = ?
    340342    WHERE id = ?
     
    343345    cover_image_url || null, parsePinnedRank(pinned),
    344346    JSON.stringify((tags || '').split(',').map(t => t.trim()).filter(Boolean)),
    345     finalType, noindex ? 1 : 0, fanOnly, nsfw, publishAt,
     347    finalType, noindex ? 1 : 0, fanOnly, nsfw, cw, publishAt,
    346348    finalSlug, publishedAt, now, post.id
    347349  );
     
    364366      id: post.id, slug: finalSlug, title: title || finalSlug,
    365367      content: cleanContent, cover_image_url: cover_image_url || null,
    366       published_at: publishedAt, created_at: post.created_at, fan_only: fanOnly, nsfw,
     368      published_at: publishedAt, created_at: post.created_at, fan_only: fanOnly, nsfw, content_warning: cw,
    367369    };
    368370    if (post.status !== 'published') ActivityPubService.deliverCreate(site, apPost).catch(() => { /* best-effort */ });
Note: See TracChangeset for help on using the changeset viewer.