From a6965d622b0474be5a8906ac7ccf852c118e794f Mon Sep 17 00:00:00 2001 From: Petr Vecera Date: Thu, 12 Dec 2024 11:48:01 +0100 Subject: [PATCH] Swap online players API --- .../pages/api/onlineSteamPlayers.test.ts | 61 ------------------- components/online-players.tsx | 19 ++++-- pages/api/onlineSteamPlayers.ts | 26 -------- src/apis/steam-api.ts | 6 +- 4 files changed, 19 insertions(+), 93 deletions(-) delete mode 100644 __tests__/pages/api/onlineSteamPlayers.test.ts delete mode 100644 pages/api/onlineSteamPlayers.ts diff --git a/__tests__/pages/api/onlineSteamPlayers.test.ts b/__tests__/pages/api/onlineSteamPlayers.test.ts deleted file mode 100644 index f2b6b193..00000000 --- a/__tests__/pages/api/onlineSteamPlayers.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @jest-environment node - */ - -import handler from "../../../pages/api/onlineSteamPlayers"; -import { NextApiRequest, NextApiResponse } from "next"; - -describe("onlineSteamApiPlayersHandler", () => { - let req: NextApiRequest; - let res: NextApiResponse; - - // Mock the fetch function - const fakeData = { response: { player_count: 5 } }; - const setupFetchStub = (data: any) => () => - Promise.resolve({ json: () => Promise.resolve(data) }); - - beforeAll(() => { - // @ts-ignore - jest.spyOn(global, "fetch").mockImplementation(setupFetchStub(fakeData)); - - req = { - method: "GET", - } as NextApiRequest; - - res = { - setHeader: jest.fn().mockReturnThis(), - status: jest.fn().mockReturnThis(), - json: jest.fn(), - } as unknown as NextApiResponse; - - jest.spyOn(console, "log").mockImplementation(() => {}); - jest.spyOn(console, "error").mockImplementation(() => {}); - }); - - afterAll(() => { - jest.clearAllMocks(); - }); - - test("should return 200 status code and player count and timestamp in response", async () => { - await handler(req, res); - - expect(res.setHeader).toHaveBeenCalledWith( - "Cache-Control", - "public, max-age=300, s-maxage=180, stale-while-revalidate=1200", - ); - expect(res.status).toHaveBeenCalledWith(200); - expect(res.json).toHaveBeenCalledWith({ - playerCount: 5, - timeStampMs: expect.any(Number), - }); - }); - - test("should return 500 status code when fetch throws an error", async () => { - jest.spyOn(global, "fetch").mockRejectedValue(new Error("Fake error")); - - await handler(req, res); - - expect(res.status).toHaveBeenCalledWith(500); - expect(res.json).toHaveBeenCalledWith({}); - }); -}); diff --git a/components/online-players.tsx b/components/online-players.tsx index e6576d47..82573668 100644 --- a/components/online-players.tsx +++ b/components/online-players.tsx @@ -1,5 +1,6 @@ import { Badge, Flex, Tooltip } from "@mantine/core"; import React, { useEffect, useState } from "react"; +import { getNumberOfOnlinePlayersSteamUrl } from "../src/apis/steam-api"; export const OnlinePlayers: React.FC = () => { const [onlinePlayersData, setOnlinePlayersData] = useState { onlinePlayersData.timeStampMs < new Date().getTime() - 1000 * 60 * 4) || !onlinePlayersData ) { - const fetchData = await fetch("/api/onlineSteamPlayers"); - setOnlinePlayersData(await fetchData.json()); + const fetchData = await fetch(getNumberOfOnlinePlayersSteamUrl()); + // reader header last-modified: + const data = await fetchData.json(); + setOnlinePlayersData({ + playerCount: data.response.player_count, + timeStampMs: new Date(fetchData.headers.get("last-modified") || "").getTime(), + }); } // Update the data every 5 minutes @@ -28,10 +34,13 @@ export const OnlinePlayers: React.FC = () => { onlinePlayersData.timeStampMs < new Date().getTime() - 1000 * 60 * 4) || !onlinePlayersData ) { - const fetchData = await fetch("/api/onlineSteamPlayers"); + const fetchData = await fetch(getNumberOfOnlinePlayersSteamUrl()); const data = await fetchData.json(); - if (data && data.playerCount > 0) { - setOnlinePlayersData(data); + if (data && data.player_count > 0) { + setOnlinePlayersData({ + playerCount: data.response.player_count, + timeStampMs: new Date(fetchData.headers.get("last-modified") || "").getTime(), + }); } } } catch (e) { diff --git a/pages/api/onlineSteamPlayers.ts b/pages/api/onlineSteamPlayers.ts deleted file mode 100644 index 0503d293..00000000 --- a/pages/api/onlineSteamPlayers.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * This is unique API component, we won't be using this much. - * The reason we have this here is, so we can cache it. - */ - -import { getNumberOfOnlinePlayersSteamUrl } from "../../src/apis/steam-api"; -import { logger } from "../../src/logger"; -import { NextApiRequest, NextApiResponse } from "next"; - -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - try { - const fetchResponse = await fetch(getNumberOfOnlinePlayersSteamUrl()); - const { response } = await fetchResponse.json(); - - res - .setHeader( - "Cache-Control", - "public, max-age=300, s-maxage=180, stale-while-revalidate=1200", - ) - .status(200) - .json({ playerCount: response.player_count, timeStampMs: new Date().valueOf() }); - } catch (e) { - logger.error(e); - res.status(500).json({}); - } -} diff --git a/src/apis/steam-api.ts b/src/apis/steam-api.ts index 3c9989fa..109ebbf1 100644 --- a/src/apis/steam-api.ts +++ b/src/apis/steam-api.ts @@ -1,6 +1,8 @@ import { logger } from "../logger"; const baseUrl = "https://api.steampowered.com/"; +const baseUrlProxied = "https://steam.coh3stats.com/"; + const COH3_STEAM_APP_ID = 1677280; const steamImagesBaseUrl = "https://clan.cloudflare.steamstatic.com/images"; @@ -21,7 +23,9 @@ export type COH3SteamNewsType = { }; const getNumberOfOnlinePlayersSteamUrl = (appId: number | string = COH3_STEAM_APP_ID) => { - return encodeURI(`${baseUrl}ISteamUserStats/GetNumberOfCurrentPlayers/v1/?appid=${appId}`); + return encodeURI( + `${baseUrlProxied}ISteamUserStats/GetNumberOfCurrentPlayers/v1/?appid=${appId}`, + ); }; const getCOH3SteamNewsUrl = (count: number = 20) => {