Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation. Made-with: Cursor
35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
import { loadBarter } from "@/lib/barterState";
|
|
import { loadExchange } from "@/lib/exchangeState";
|
|
import { loadForum } from "@/lib/forumState";
|
|
|
|
/** Match forum / listings when the user types the same handle (case-insensitive). */
|
|
function matchesHandle(author: string, handles: string[]): boolean {
|
|
const a = author.trim().toLowerCase();
|
|
if (!a) return false;
|
|
const set = new Set(handles.map((h) => h.trim().toLowerCase()).filter(Boolean));
|
|
return set.has(a);
|
|
}
|
|
|
|
export type UserActivityStats = {
|
|
forumThreads: number;
|
|
forumReplies: number;
|
|
exchangeListings: number;
|
|
barterListings: number;
|
|
};
|
|
|
|
export function computeUserActivityStats(username: string, displayName: string): UserActivityStats {
|
|
const handles = [username, displayName];
|
|
const forum = loadForum();
|
|
let forumThreads = 0;
|
|
let forumReplies = 0;
|
|
for (const t of forum) {
|
|
if (matchesHandle(t.author, handles)) forumThreads++;
|
|
for (const r of t.replies) {
|
|
if (matchesHandle(r.author, handles)) forumReplies++;
|
|
}
|
|
}
|
|
const exchangeListings = loadExchange().filter((e) => matchesHandle(e.author, handles)).length;
|
|
const barterListings = loadBarter().filter((b) => matchesHandle(b.author, handles)).length;
|
|
return { forumThreads, forumReplies, exchangeListings, barterListings };
|
|
}
|