Foreign-Profile-Page rendert User-Posts jetzt via PostCard mit dem gleichen Daten-Shape wie Index. `?userId=<uuid>` filtert auf Posts dieses Users — kombinierbar mit `category=...`, Bot-Kategorie-Mapping wird übersteuert wenn explizite userId mitgegeben. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
137 lines
4.9 KiB
TypeScript
137 lines
4.9 KiB
TypeScript
import { getPosts } from "../../db/community";
|
|
import { getFollowingSet } from "../../db/social";
|
|
|
|
/** GET /api/community/posts?category=all&page=1&limit=20 */
|
|
export default defineEventHandler(async (event) => {
|
|
const config = useRuntimeConfig();
|
|
const lyraBotUserId = config.lyraBotUserId || null;
|
|
const rebreakBotUserId = config.rebreakBotUserId || null;
|
|
const query = getQuery(event);
|
|
const category = (query.category as string) || "all";
|
|
const page = Math.max(1, parseInt((query.page as string) || "1"));
|
|
const limit = Math.min(50, parseInt((query.limit as string) || "20"));
|
|
const userIdParam = (query.userId as string) || null;
|
|
|
|
// Lyra / ReBreak → nach userId filtern; expliziter userIdParam hat Vorrang
|
|
let filterUserId: string | null = userIdParam;
|
|
let dbCategory = category;
|
|
if (userIdParam) {
|
|
// Explizite userId: Bot-Kategorie-Mapping irrelevant, category-Filter weglassen außer echte Kategorien
|
|
if (category === "lyra" || category === "rebreak") {
|
|
dbCategory = "all";
|
|
}
|
|
} else if (category === "lyra") {
|
|
filterUserId = lyraBotUserId;
|
|
dbCategory = "all";
|
|
} else if (category === "rebreak") {
|
|
filterUserId = rebreakBotUserId;
|
|
dbCategory = "all";
|
|
}
|
|
|
|
// Auth-User optional (Gäste können auch lesen)
|
|
let currentUserId: string | null = null;
|
|
try {
|
|
const u = await requireUser(event);
|
|
currentUserId = u.id;
|
|
} catch {}
|
|
|
|
const {
|
|
posts,
|
|
userLikes,
|
|
challengeStatuses,
|
|
domainSubmissions,
|
|
userDomainVotes,
|
|
userScores,
|
|
submissionVoters,
|
|
} = await getPosts(dbCategory, page, limit, currentUserId, filterUserId);
|
|
|
|
// Batch: isFollowing für alle Autoren
|
|
const authorIds = [
|
|
...new Set(posts.map((p) => p.userId).filter((id): id is string => !!id)),
|
|
];
|
|
const followingSet =
|
|
currentUserId && authorIds.length > 0
|
|
? await getFollowingSet(currentUserId, authorIds)
|
|
: new Set<string>();
|
|
|
|
return posts.map((p) => {
|
|
const a = p.author;
|
|
return {
|
|
id: p.id,
|
|
category: p.category,
|
|
content:
|
|
p.category === "game_share"
|
|
? p.content.split("\n").slice(1).join("\n").trim()
|
|
: p.content,
|
|
imageUrl: (p as any).imageUrl ?? null,
|
|
challengeId: (p as any).challengeId ?? null,
|
|
challengeStatus: (p as any).challengeId
|
|
? challengeStatuses[(p as any).challengeId]?.status ?? "OPEN"
|
|
: null,
|
|
gameName: (p as any).challengeId
|
|
? challengeStatuses[(p as any).challengeId]?.gameType ?? null
|
|
: (p as any).gameName ?? (p.category === "game_share"
|
|
? p.content.split("\n")[0] ?? null
|
|
: null),
|
|
opponentName: (p as any).challengeId
|
|
? challengeStatuses[(p as any).challengeId]?.opponentName ?? null
|
|
: null,
|
|
isLive: (p as any).challengeId
|
|
? challengeStatuses[(p as any).challengeId]?.isLive ?? false
|
|
: false,
|
|
likesCount: p.likesCount ?? 0,
|
|
dislikesCount: p.dislikesCount ?? 0,
|
|
commentsCount: p.commentsCount ?? 0,
|
|
repostsCount: (p as any).repostsCount ?? 0,
|
|
isAnonymous: p.isAnonymous,
|
|
createdAt: p.createdAt,
|
|
userLike: userLikes[p.id] ?? null,
|
|
submission: domainSubmissions[p.id]
|
|
? {
|
|
...domainSubmissions[p.id],
|
|
yesVoters: submissionVoters[domainSubmissions[p.id].id]?.yes ?? [],
|
|
noVoters: submissionVoters[domainSubmissions[p.id].id]?.no ?? [],
|
|
}
|
|
: null,
|
|
userVote: userDomainVotes[p.id] ?? null,
|
|
i18nKey: (p as any).i18nKey ?? null,
|
|
repostOfId: (p as any).repostOfId ?? null,
|
|
repostOf: (p as any).repostOf
|
|
? {
|
|
id: (p as any).repostOf.id,
|
|
content: (p as any).repostOf.content,
|
|
imageUrl: (p as any).repostOf.imageUrl ?? null,
|
|
author: {
|
|
id: (p as any).repostOf.userId ?? null,
|
|
nickname:
|
|
(p as any).repostOf.author?.nickname ??
|
|
(p as any).repostOf.author?.username ??
|
|
"Nutzer",
|
|
avatar: (p as any).repostOf.author?.avatar ?? null,
|
|
plan: (p as any).repostOf.author?.plan ?? "free",
|
|
tier: userScores[(p as any).repostOf.userId ?? ""] ?? "beginner",
|
|
},
|
|
}
|
|
: null,
|
|
author: {
|
|
id: p.userId ?? null,
|
|
username: a?.username ?? "Nutzer",
|
|
nickname: a?.nickname ?? a?.username ?? "Nutzer",
|
|
avatar: a?.avatar ?? null,
|
|
plan: (a as any)?.plan ?? "free",
|
|
tier: userScores[p.userId ?? ""] ?? "beginner",
|
|
isFollowing: p.userId ? followingSet.has(p.userId) : false,
|
|
},
|
|
isBot:
|
|
!!(lyraBotUserId && p.userId === lyraBotUserId) ||
|
|
!!(rebreakBotUserId && p.userId === rebreakBotUserId),
|
|
botType:
|
|
lyraBotUserId && p.userId === lyraBotUserId
|
|
? "lyra"
|
|
: rebreakBotUserId && p.userId === rebreakBotUserId
|
|
? "rebreak"
|
|
: undefined,
|
|
};
|
|
});
|
|
});
|