Show NSFW-node posts to authenticated local members in Curated and Swarm feeds

Hop-State: A_06FP9V8EJ8CX3VM4D7DDZJR
Hop-Proposal: R_06FP9V7H6GNGX6CFBQN8HER
Hop-Task: T_06FP9TA4HBBMJPF6SDEMEC0
Hop-Attempt: AT_06FP9TA4HBQJXX3KT14FYN0
This commit is contained in:
2026-07-15 01:38:05 -07:00
committed by Hop
parent 7f8a97ffe2
commit e1a7f5018f
5 changed files with 80 additions and 22 deletions
+9 -12
View File
@@ -1,11 +1,13 @@
import { NextResponse } from 'next/server';
import { db, posts, users, media, follows, mutes, blocks, likes, remoteFollows, remotePosts, userSwarmReposts, notifications } from '@/db';
import { requireAuth } from '@/lib/auth';
import { getSession, requireAuth } from '@/lib/auth';
import { requireSignedAction, type SignedAction } from '@/lib/auth/verify-signature';
import { eq, desc, and, inArray, isNull, isNotNull, or, lt, sql } from 'drizzle-orm';
import { z } from 'zod';
import { buildNotificationTarget } from '@/lib/notifications';
import { serializeLinkPreviewMedia, parseLinkPreviewMediaJson } from '@/lib/media/linkPreview';
import { shouldIncludeNsfwFeed } from '@/lib/nsfw/feed-access';
import { isLocalNodeNsfw } from '@/lib/node/local-node';
const POST_MAX_LENGTH = 600;
const CURATION_WINDOW_HOURS = 72;
@@ -705,17 +707,12 @@ export async function GET(request: Request) {
});
} else if (type === 'curated') {
// Curated feed - swarm posts only
let viewer = null;
let includeNsfw = false;
try {
const { getSession } = await import('@/lib/auth');
const session = await getSession();
viewer = session?.user || null;
includeNsfw = session?.user?.nsfwEnabled ?? false;
} catch {
viewer = null;
includeNsfw = false;
}
const session = await getSession().catch(() => null);
const viewer = session?.user ?? null;
const includeNsfw = shouldIncludeNsfwFeed({
viewer,
localNodeIsNsfw: await isLocalNodeNsfw(),
});
// Fetch swarm posts with user's NSFW preference
const { fetchSwarmTimeline } = await import('@/lib/swarm/timeline');
+8 -10
View File
@@ -9,6 +9,8 @@ import { fetchSwarmTimeline } from '@/lib/swarm/timeline';
import { getSession } from '@/lib/auth';
import { getViewerSwarmLikedPostIds } from '@/lib/swarm/likes';
import { getViewerSwarmRepostedPostIds } from '@/lib/swarm/reposts';
import { shouldIncludeNsfwFeed } from '@/lib/nsfw/feed-access';
import { isLocalNodeNsfw } from '@/lib/node/local-node';
type SwarmFeedPost = {
id: string;
@@ -65,20 +67,16 @@ export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const cursor = searchParams.get('cursor') || undefined;
// Check user's NSFW preference
let includeNsfw = false;
try {
const session = await getSession();
includeNsfw = session?.user?.nsfwEnabled ?? false;
} catch {
includeNsfw = false;
}
const session = await getSession().catch(() => null);
const viewer = session?.user ?? null;
const includeNsfw = shouldIncludeNsfwFeed({
viewer,
localNodeIsNsfw: await isLocalNodeNsfw(),
});
// Fetch swarm timeline (no caching - user preferences vary)
const timeline = await fetchSwarmTimeline(10, 15, { includeNsfw, cursor });
const session = await getSession().catch(() => null);
const viewer = session?.user;
const nodeDomain = process.env.NEXT_PUBLIC_NODE_DOMAIN || 'localhost:43821';
const allTimelinePosts = collectNestedSwarmPosts(timeline.posts as SwarmFeedPost[]);
const likedPostIds = viewer