feat: improve mii metadata images
This commit is contained in:
parent
69cf02e018
commit
a09b3cb56d
6 changed files with 48 additions and 36 deletions
|
|
@ -44,13 +44,6 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
|
||||||
where: {
|
where: {
|
||||||
id: miiId,
|
id: miiId,
|
||||||
},
|
},
|
||||||
include: {
|
|
||||||
user: {
|
|
||||||
select: {
|
|
||||||
username: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!mii) return rateLimit.sendResponse({ error: "Mii not found" }, 404);
|
if (!mii) return rateLimit.sendResponse({ error: "Mii not found" }, 404);
|
||||||
|
|
@ -102,11 +95,18 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
|
||||||
if (images.length > 0) updateData.imageCount = images.length;
|
if (images.length > 0) updateData.imageCount = images.length;
|
||||||
|
|
||||||
if (Object.keys(updateData).length == 0) return rateLimit.sendResponse({ error: "Nothing was changed" }, 400);
|
if (Object.keys(updateData).length == 0) return rateLimit.sendResponse({ error: "Nothing was changed" }, 400);
|
||||||
await prisma.mii.update({
|
const updatedMii = await prisma.mii.update({
|
||||||
where: {
|
where: {
|
||||||
id: miiId,
|
id: miiId,
|
||||||
},
|
},
|
||||||
data: updateData,
|
data: updateData,
|
||||||
|
include: {
|
||||||
|
user: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Only touch files if new images were uploaded
|
// Only touch files if new images were uploaded
|
||||||
|
|
@ -136,7 +136,7 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
|
||||||
}
|
}
|
||||||
} else if (description === undefined) {
|
} else if (description === undefined) {
|
||||||
// If images or description were not changed, regenerate the metadata image
|
// If images or description were not changed, regenerate the metadata image
|
||||||
await generateMetadataImage(mii, mii.user.username!);
|
await generateMetadataImage(updatedMii, updatedMii.user.name!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rateLimit.sendResponse({ success: true });
|
return rateLimit.sendResponse({ success: true });
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ReportReason, ReportType } from "@prisma/client";
|
import { Prisma, ReportReason, ReportType } from "@prisma/client";
|
||||||
|
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { RateLimit } from "@/lib/rate-limit";
|
import { RateLimit } from "@/lib/rate-limit";
|
||||||
import { MiiWithUsername } from "@/types";
|
|
||||||
|
|
||||||
const reportSchema = z.object({
|
const reportSchema = z.object({
|
||||||
id: z.coerce.number({ error: "ID must be a number" }).int({ error: "ID must be an integer" }).positive({ error: "ID must be valid" }),
|
id: z.coerce.number({ error: "ID must be a number" }).int({ error: "ID must be an integer" }).positive({ error: "ID must be valid" }),
|
||||||
|
|
@ -30,7 +29,15 @@ export async function POST(request: NextRequest) {
|
||||||
if (!parsed.success) return rateLimit.sendResponse({ error: parsed.error.issues[0].message }, 400);
|
if (!parsed.success) return rateLimit.sendResponse({ error: parsed.error.issues[0].message }, 400);
|
||||||
const { id, type, reason, notes } = parsed.data;
|
const { id, type, reason, notes } = parsed.data;
|
||||||
|
|
||||||
let mii: MiiWithUsername | null = null;
|
let mii: Prisma.MiiGetPayload<{
|
||||||
|
include: {
|
||||||
|
user: {
|
||||||
|
select: {
|
||||||
|
username: true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}> | null = null;
|
||||||
|
|
||||||
// Check if the Mii or User exists
|
// Check if the Mii or User exists
|
||||||
if (type === "mii") {
|
if (type === "mii") {
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ export async function POST(request: NextRequest) {
|
||||||
const codeFileLocation = path.join(miiUploadsDirectory, "qr-code.webp");
|
const codeFileLocation = path.join(miiUploadsDirectory, "qr-code.webp");
|
||||||
|
|
||||||
await fs.writeFile(codeFileLocation, codeWebpBuffer);
|
await fs.writeFile(codeFileLocation, codeWebpBuffer);
|
||||||
await generateMetadataImage(miiRecord, session.user.username!);
|
await generateMetadataImage(miiRecord, session.user.name!);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Clean up if something went wrong
|
// Clean up if something went wrong
|
||||||
await prisma.mii.delete({ where: { id: miiRecord.id } });
|
await prisma.mii.delete({ where: { id: miiRecord.id } });
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { NextRequest } from "next/server";
|
import { NextRequest } from "next/server";
|
||||||
|
import { Prisma } from "@prisma/client";
|
||||||
|
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
@ -8,7 +9,6 @@ import { idSchema } from "@/lib/schemas";
|
||||||
import { RateLimit } from "@/lib/rate-limit";
|
import { RateLimit } from "@/lib/rate-limit";
|
||||||
import { generateMetadataImage } from "@/lib/images";
|
import { generateMetadataImage } from "@/lib/images";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { MiiWithUsername } from "@/types";
|
|
||||||
|
|
||||||
const searchParamsSchema = z.object({
|
const searchParamsSchema = z.object({
|
||||||
type: z
|
type: z
|
||||||
|
|
@ -37,7 +37,15 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
||||||
|
|
||||||
let buffer: Buffer | undefined;
|
let buffer: Buffer | undefined;
|
||||||
// Only find Mii if image type is 'metadata'
|
// Only find Mii if image type is 'metadata'
|
||||||
let mii: MiiWithUsername | null = null;
|
let mii: Prisma.MiiGetPayload<{
|
||||||
|
include: {
|
||||||
|
user: {
|
||||||
|
select: {
|
||||||
|
name: true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}> | null = null;
|
||||||
|
|
||||||
if (imageType === "metadata") {
|
if (imageType === "metadata") {
|
||||||
mii = await prisma.mii.findUnique({
|
mii = await prisma.mii.findUnique({
|
||||||
|
|
@ -47,7 +55,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
||||||
include: {
|
include: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
username: true,
|
name: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -66,7 +74,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
||||||
if (imageType === "metadata" && mii) {
|
if (imageType === "metadata" && mii) {
|
||||||
// Metadata images were added after 1274 Miis were submitted, so we generate it on-the-fly
|
// Metadata images were added after 1274 Miis were submitted, so we generate it on-the-fly
|
||||||
console.log(`Metadata image not found for mii ID ${miiId}, generating metadata image...`);
|
console.log(`Metadata image not found for mii ID ${miiId}, generating metadata image...`);
|
||||||
const { buffer: metadataBuffer, error, status } = await generateMetadataImage(mii, mii.user.username!);
|
const { buffer: metadataBuffer, error, status } = await generateMetadataImage(mii, mii.user.name!);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return rateLimit.sendResponse({ error }, status);
|
return rateLimit.sendResponse({ error }, status);
|
||||||
|
|
|
||||||
|
|
@ -162,22 +162,29 @@ export async function generateMetadataImage(mii: Mii, author: string): Promise<{
|
||||||
{mii.name}
|
{mii.name}
|
||||||
</span>
|
</span>
|
||||||
{/* Tags */}
|
{/* Tags */}
|
||||||
<div id="tags" tw="flex flex-wrap mt-1 w-full">
|
<div id="tags" tw="relative flex mt-1 w-full overflow-hidden">
|
||||||
|
<div tw="flex">
|
||||||
{mii.tags.map((tag) => (
|
{mii.tags.map((tag) => (
|
||||||
<span key={tag} tw="mr-1 px-2 py-1 bg-orange-300 rounded-full text-sm">
|
<span key={tag} tw="mr-1 px-2 py-1 bg-orange-300 rounded-full text-sm shrink-0">
|
||||||
{tag}
|
{tag}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div tw="absolute inset-0" style={{ position: "absolute", backgroundImage: "linear-gradient(to right, #fffbeb00 70%, #fffbeb);" }}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Author */}
|
{/* Author */}
|
||||||
<div tw="flex text-sm mt-2">
|
<div tw="flex mt-2 text-sm w-1/2">
|
||||||
By: <span tw="ml-1.5 font-semibold">@{author}</span>
|
By{" "}
|
||||||
|
<span tw="ml-1.5 font-semibold overflow-hidden" style={{ textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||||
|
{author}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Watermark */}
|
{/* Watermark */}
|
||||||
<div tw="absolute bottom-0 right-0 flex items-center">
|
<div tw="absolute bottom-0 right-0 flex items-center">
|
||||||
<img src={`${process.env.NEXT_PUBLIC_BASE_URL}/logo.svg`} height={34} />
|
<img src={`${process.env.NEXT_PUBLIC_BASE_URL}/logo.svg`} height={32} />
|
||||||
{/* I tried using text-orange-400 but it wasn't correct..? */}
|
{/* I tried using text-orange-400 but it wasn't correct..? */}
|
||||||
<span tw="ml-2 font-black text-xl" style={{ color: "#FF8904" }}>
|
<span tw="ml-2 font-black text-xl" style={{ color: "#FF8904" }}>
|
||||||
TomodachiShare
|
TomodachiShare
|
||||||
|
|
|
||||||
10
src/types.d.ts
vendored
10
src/types.d.ts
vendored
|
|
@ -12,13 +12,3 @@ declare module "next-auth" {
|
||||||
username?: string;
|
username?: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type MiiWithUsername = Prisma.MiiGetPayload<{
|
|
||||||
include: {
|
|
||||||
user: {
|
|
||||||
select: {
|
|
||||||
username: true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue