diff --git a/projects/backend/src/controller/image.controller.ts b/projects/backend/src/controller/image.controller.ts new file mode 100644 index 0000000..79b0c30 --- /dev/null +++ b/projects/backend/src/controller/image.controller.ts @@ -0,0 +1,19 @@ +import { Controller, Get } from "elysia-decorators"; +import { PlayerService } from "../service/player.service"; +import { t } from "elysia"; +import { PlayerHistory } from "@ssr/common/types/player/player-history"; +import { PlayerTrackedSince } from "@ssr/common/types/player/player-tracked-since"; +import { ImageService } from "../service/image.service"; + +@Controller("/image") +export default class ImageController { + @Get("/player/:id", { + config: {}, + params: t.Object({ + id: t.String({ required: true }), + }), + }) + public async getOpenGraphImage({ params: { id } }: { params: { id: string } }) { + return await ImageService.generateOpenGraphImage(id); + } +} diff --git a/projects/backend/src/index.ts b/projects/backend/src/index.ts index c02cc09..503199d 100644 --- a/projects/backend/src/index.ts +++ b/projects/backend/src/index.ts @@ -19,6 +19,7 @@ import { PlayerDocument, PlayerModel } from "./model/player"; import { scoresaberService } from "@ssr/common/service/impl/scoresaber"; import { delay } from "@ssr/common/utils/utils"; import { connectScoreSaberWebSocket } from "@ssr/common/websocket/scoresaber-websocket"; +import ImageController from "./controller/image.controller"; // Load .env file dotenv.config({ @@ -151,7 +152,7 @@ app.use( */ app.use( decorators({ - controllers: [AppController, PlayerController], + controllers: [AppController, PlayerController, ImageController], }) ); diff --git a/projects/backend/src/service/image.service.tsx b/projects/backend/src/service/image.service.tsx new file mode 100644 index 0000000..7d9daa3 --- /dev/null +++ b/projects/backend/src/service/image.service.tsx @@ -0,0 +1,64 @@ +import { ImageResponse } from "@vercel/og"; +import { scoresaberService } from "@ssr/common/service/impl/scoresaber"; +import { formatNumberWithCommas, formatPp } from "website/src/common/number-utils"; +import React from "react"; + +export class ImageService { + /** + * 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 new ImageResponse( + ( +
{player.name}
+{formatPp(player.pp)}pp
+#{formatNumberWithCommas(player.rank)}
+#{formatNumberWithCommas(player.countryRank)}
+{player.name}
-{formatPp(player.pp)}pp
-#{formatNumberWithCommas(player.rank)}
-#{formatNumberWithCommas(player.countryRank)}
-