move og image to backend
Some checks failed
Deploy Backend / deploy (push) Has been cancelled
Deploy Website / deploy (push) Failing after 2m39s

This commit is contained in:
Lee 2024-10-15 19:26:04 +01:00
parent ef634194b8
commit 6f88ab8f30
7 changed files with 41 additions and 24 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -14,12 +14,14 @@
"@ssr/common": "workspace:common",
"@tqman/nice-logger": "^1.0.1",
"@typegoose/typegoose": "^12.8.0",
"@vercel/og": "^0.6.3",
"elysia": "latest",
"elysia-autoroutes": "^0.5.0",
"elysia-decorators": "^1.0.2",
"elysia-helmet": "^2.0.0",
"elysia-rate-limit": "^4.1.0",
"mongoose": "^8.7.0"
"mongoose": "^8.7.0",
"react": "^18.3.1"
},
"devDependencies": {
"bun-types": "latest"

View File

@ -1,19 +1,10 @@
import { ImageResponse } from "next/og";
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
import { NextRequest } from "next/server";
import { formatNumberWithCommas, formatPp } from "@/common/number-utils";
import { config } from "../../../../../../config";
export async function GET(request: NextRequest) {
const playerId = request.nextUrl.searchParams.get("id");
if (!playerId) {
return new Response(null, { status: 400 });
}
const player = await scoresaberService.lookupPlayer(playerId);
if (!player) {
return new Response(null, { status: 404 });
}
import { ImageResponse } from "@vercel/og";
import { formatNumberWithCommas, formatPp } from "website/src/common/number-utils";
import { config } from "website/config";
import React from "react";
import ScoreSaberPlayerToken from "@ssr/common/types/token/scoresaber/score-saber-player-token";
export function generatePlayerOgImage(player: ScoreSaberPlayerToken) {
return new ImageResponse(
(
<div tw="w-full h-full flex flex-col text-white bg-black text-3xl p-3 justify-center items-center">
@ -42,7 +33,12 @@ export async function GET(request: NextRequest) {
<p tw="m-0">#{formatNumberWithCommas(player.rank)}</p>
</div>
<div tw="flex items-center px-2 justify-center items-center">
<img src={`${config.siteUrl}/assets/flags/${player.country}.png`} height={20} alt="Player's Country" />
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={`${config.siteUrl}/assets/flags/${player.country.toLowerCase()}.png`}
height={20}
alt="Player's Country"
/>
<p tw="pl-1 m-0">#{formatNumberWithCommas(player.countryRank)}</p>
</div>
</div>

View File

@ -51,4 +51,14 @@ export default class PlayerController {
};
}
}
@Get("/og/:id", {
config: {},
params: t.Object({
id: t.String({ required: true }),
}),
})
public async getOpenGraphImage({ params: { id } }: { params: { id: string } }) {
return await PlayerService.generateOpenGraphImage(id);
}
}

View File

@ -5,6 +5,7 @@ import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
import ScoreSaberPlayerToken from "@ssr/common/types/token/scoresaber/score-saber-player-token";
import { InternalServerError } from "../error/internal-server-error";
import ScoreSaberPlayerScoreToken from "@ssr/common/types/token/scoresaber/score-saber-player-score-token";
import { generatePlayerOgImage } from "../common/open-graph";
export class PlayerService {
/**
@ -155,4 +156,17 @@ export class PlayerService {
`Updated scores set statistic for "${playerName}"(${playerId}), scores today: ${scores.rankedScores} ranked, ${scores.unrankedScores} unranked`
);
}
/**
* Generates the OpenGraph image for the player
*
* @param id the player's id
*/
public static async generateOpenGraphImage(id: string) {
const player = await scoresaberService.lookupPlayer(id);
if (player == undefined) {
return undefined;
}
return generatePlayerOgImage(player);
}
}

View File

@ -10,5 +10,6 @@
"skipLibCheck": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"jsx": "react"
}
}

View File

@ -95,15 +95,9 @@ export async function generateMetadata(props: Props): Promise<Metadata> {
title: `${player.name}`,
openGraph: {
title: `ScoreSaber Reloaded - ${player.name}`,
// description: `
// PP: ${formatPp(player.pp)}pp
// Rank: #${formatNumberWithCommas(player.rank)} (#${formatNumberWithCommas(player.countryRank)} ${player.country})
// Joined ScoreSaber: ${format(player.joinedDate, { date: "medium", time: "short" })}
//
// View the scores for ${player.name}!`,
images: [
{
url: `${config.siteUrl}/api/og/player/?id=${player.id}`,
url: `${config.siteApi}/player/og/${player.id}`,
},
],
},