Migrate download count updater to server action

This commit is contained in:
Jared Schoeny 2025-12-12 01:25:54 -10:00
parent ce2e29ac7a
commit e71f138933
3 changed files with 21 additions and 43 deletions

View File

@ -1,31 +0,0 @@
import { NextRequest } from "next/server";
import { createClient } from "@/utils/supabase/server";
export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
const { deviceId } = await req.json().catch(() => ({ deviceId: undefined }));
if (!deviceId || typeof deviceId !== "string") {
return new Response("Missing deviceId", { status: 400 });
}
const supabase = await createClient();
const patchId = Number(id);
if (!Number.isFinite(patchId)) {
return new Response("Bad id", { status: 400 });
}
// Try insert; if unique constraint violation, treat as success (already counted)
const { error } = await supabase
.from("patch_downloads")
.insert({ patch: patchId, device_id: deviceId });
if (error) {
// PostgREST unique violation codes commonly surface as 409 or PGRST specific; best-effort accept duplicates
if ((error as any).code === "23505" || /duplicate|unique/i.test(error.message)) {
return new Response(null, { status: 200 });
}
return new Response(error.message || "Failed", { status: 500 });
}
return new Response(null, { status: 201 });
}

View File

@ -71,6 +71,20 @@ export async function getSignedPatchUrl(slug: string): Promise<{ ok: true; url:
}
}
export async function updatePatchDownloadCount(patchId: number, deviceId: string): Promise<{ ok: true; didIncrease: boolean } | { ok: false; error: string }> {
const supabase = await createClient();
const { error: updateError } = await supabase
.from("patch_downloads")
.insert({ patch: patchId, device_id: deviceId });
if (updateError) {
if ('code' in updateError && (updateError.code === '23505' || /duplicate|unique/i.test(updateError.message))) {
return { ok: true, didIncrease: false };
}
return { ok: false, error: updateError.message };
}
return { ok: true, didIncrease: true };
}
export async function submitHackReport(data: {
slug: string;
reportType: "hateful" | "harassment" | "misleading" | "stolen";

View File

@ -7,7 +7,7 @@ import { baseRoms } from "@/data/baseRoms";
import BinFile from "rom-patcher-js/rom-patcher-js/modules/BinFile.js";
import BPS from "rom-patcher-js/rom-patcher-js/modules/RomPatcher.format.bps.js";
import type { DownloadEventDetail } from "@/types/util";
import { getSignedPatchUrl } from "@/app/hack/[slug]/actions";
import { getSignedPatchUrl, updatePatchDownloadCount } from "@/app/hack/[slug]/actions";
interface HackActionsProps {
title: string;
@ -221,17 +221,12 @@ const HackActions: React.FC<HackActionsProps> = ({
deviceId = crypto.randomUUID();
localStorage.setItem(key, deviceId);
}
await fetch(`/api/patches/${patchId}/applied`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ deviceId }),
})
.then((res) => {
if (res.status === 201) {
window.dispatchEvent(new CustomEvent<DownloadEventDetail>("hack:patch-applied", { detail: { slug: hackSlug } }));
}
})
.catch(() => {});
const result = await updatePatchDownloadCount(patchId, deviceId);
if (!result.ok) {
console.error(result.error);
} else if (result.didIncrease) {
window.dispatchEvent(new CustomEvent<DownloadEventDetail>("hack:patch-applied", { detail: { slug: hackSlug } }));
}
}
} catch {}
} catch (e: any) {