fix: sync pending requests from overseer

This commit is contained in:
2026-04-23 09:14:44 -04:00
parent e594b450c6
commit bf57169014
2 changed files with 73 additions and 19 deletions
+63 -13
View File
@@ -13,6 +13,13 @@ const overseerClient = axios.create({
headers: { "X-Api-Key": OVERSEER_API_KEY },
});
const mapOverseerStatus = (status: any) => {
const s = Number(status);
if (s >= 5) return "APPROVED";
if (s === 4) return "DECLINED";
return "PENDING";
};
router.get(
"/costs",
authenticate,
@@ -79,13 +86,11 @@ router.post(
cost += (seasons.length - 1) * (settings?.tvPerSeasonCost || 250);
const dbBalance = user.totalEarned - user.totalSpent;
if (dbBalance < cost)
return res
.status(400)
.json({
error: "Insufficient balance",
required: cost,
current: dbBalance,
});
return res.status(400).json({
error: "Insufficient balance",
required: cost,
current: dbBalance,
});
const overseerRequest = await overseerClient.post("/request", {
mediaType,
mediaId,
@@ -130,6 +135,56 @@ router.post(
});
}),
);
router.post(
"/sync-pending",
authenticate,
asyncHandler(async (req: AuthenticatedRequest, res) => {
const pending = await prisma.contentRequest.findMany({
where: { userId: req.user!.id, status: "PENDING" },
});
const updated: any[] = [];
for (const request of pending) {
try {
const response = await overseerClient.get(
`/request/${request.overseerRequestId}`,
);
const mapped = mapOverseerStatus(response.data?.status);
if (mapped !== "PENDING") {
const result = await prisma.contentRequest.update({
where: { id: request.id },
data: { status: mapped as any },
});
if (mapped === "DECLINED") {
await prisma.transaction.create({
data: {
userId: request.userId,
type: "ADJUSTMENT",
amount: request.creditsCost,
description: `Refunded: ${request.title}`,
contentTitle: request.title,
},
});
await prisma.user.update({
where: { id: request.userId },
data: { totalSpent: { decrement: request.creditsCost } },
});
}
io.to(`user:${request.userId}`).emit("request_updated", {
id: request.id,
status: result.status,
title: request.title,
});
updated.push({
id: request.id,
status: result.status,
title: request.title,
});
}
} catch {}
}
res.json({ success: true, updated });
}),
);
router.post(
"/webhook",
asyncHandler(async (req, res) => {
@@ -139,12 +194,7 @@ router.post(
req.body.requestId ??
req.body.id ??
req.body.overseer_request_id;
const statusRaw = String(req.body.status || "").toUpperCase();
let status = "PENDING";
if (statusRaw === "APPROVED" || statusRaw === "COMPLETED")
status = "APPROVED";
else if (statusRaw === "DECLINED" || statusRaw === "FAILED")
status = "DECLINED";
const status = mapOverseerStatus(req.body.status);
if (!rawId) return res.status(400).json({ error: "Missing fields" });
const request = await prisma.contentRequest.findFirst({
where: { overseerRequestId: Number(rawId) },
+10 -6
View File
@@ -1,8 +1,9 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
@@ -10,7 +11,6 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { api, authApi, overseerApi, userApi } from "@/lib/api";
import { useStore } from "@/lib/store";
@@ -43,6 +43,7 @@ export default function DashboardPage() {
}
loadWalletAndPending();
loadCosts();
syncPending();
}, [isAuthenticated, router]);
const loadWalletAndPending = async () => {
@@ -65,6 +66,12 @@ export default function DashboardPage() {
setRequestCosts(costsRes.data);
} catch {}
};
const syncPending = async () => {
try {
await api.post("/overseer/sync-pending");
await loadWalletAndPending();
} catch {}
};
const handleLogout = async () => {
try {
await authApi.logout();
@@ -72,9 +79,6 @@ export default function DashboardPage() {
logout();
router.push("/login");
};
const handleRefresh = () => {
loadWalletAndPending();
};
if (isLoading) return <div className="p-8">Loading...</div>;
@@ -157,7 +161,7 @@ export default function DashboardPage() {
<WatchHistory />
</TabsContent>
<TabsContent value="requests">
<RequestHistory onRefresh={handleRefresh} />
<RequestHistory onRefresh={syncPending} />
</TabsContent>
<TabsContent value="leaderboard">
<Leaderboard />