add redis, game icons and fix readme

This commit is contained in:
creations 2025-04-20 14:39:15 -04:00
parent 245215265a
commit 6d46ef48d0
Signed by: creations
GPG key ID: 8F553AA4320FC711
7 changed files with 153 additions and 21 deletions

View file

@ -0,0 +1,82 @@
import { redisTtl, steamGridDbKey } from "@config/environment";
import { logger } from "@helpers/logger";
import { redis } from "bun";
if (!steamGridDbKey) {
logger.warn("[SteamGridDB] Route disabled: Missing API key");
}
const routeDef: RouteDef = {
method: "GET",
accepts: "*/*",
returns: "application/json",
};
async function fetchSteamGridIcon(gameName: string): Promise<string | null> {
const cacheKey = `steamgrid:icon:${gameName.toLowerCase()}`;
const cached = await redis.get(cacheKey);
if (cached) return cached;
const search = await fetch(`https://www.steamgriddb.com/api/v2/search/autocomplete/${encodeURIComponent(gameName)}`, {
headers: {
Authorization: `Bearer ${steamGridDbKey}`,
},
});
if (!search.ok) return null;
const { data } = await search.json();
if (!data?.length) return null;
const gameId = data[0]?.id;
if (!gameId) return null;
const iconRes = await fetch(`https://www.steamgriddb.com/api/v2/icons/game/${gameId}`, {
headers: {
Authorization: `Bearer ${steamGridDbKey}`,
},
});
if (!iconRes.ok) return null;
const iconData = await iconRes.json();
const icon = iconData?.data?.[0]?.url ?? null;
if (icon) {
await redis.set(cacheKey, icon);
await redis.expire(cacheKey, redisTtl);
}
return icon;
}
async function handler(request: ExtendedRequest): Promise<Response> {
if (!steamGridDbKey) {
return Response.json(
{ status: 503, error: "Route disabled due to missing SteamGridDB key" },
{ status: 503 }
);
}
const { game } = request.params;
if (!game || typeof game !== "string" || game.length < 2) {
return Response.json({ status: 400, error: "Missing or invalid game name" }, { status: 400 });
}
const icon = await fetchSteamGridIcon(game);
if (!icon) {
return Response.json({ status: 404, error: "Icon not found" }, { status: 404 });
}
return Response.json(
{
status: 200,
game,
icon,
},
{ status: 200 }
);
}
export { handler, routeDef };

View file

@ -32,9 +32,9 @@
<meta name="color-scheme" content="dark">
</head>
<%- include("partial/style.ejs") %>
<body>
<%- include("partial/style.ejs") %>
<div class="user-card">
<div class="avatar-status-wrapper">
<div class="avatar-wrapper">
@ -54,10 +54,10 @@
<div class="user-info-inner">
<h1><%= username %></h1>
<% if (user.clan && user.clan.tag) { %>
<div class="clan-badge">
<img src="https://cdn.discordapp.com/clan-badges/<%= user.clan.identity_guild_id %>/<%= user.clan.badge %>" alt="Clan Badge" class="clan-badge">
<span class="clan-name"><%= user.clan.tag %></span>
</div>
<div class="clan-badge">
<img src="https://cdn.discordapp.com/clan-badges/<%= user.clan.identity_guild_id %>/<%= user.clan.badge %>" alt="Clan Badge" class="clan-badge">
<span class="clan-name"><%= user.clan.tag %></span>
</div>
<% } %>
</div>
<% if (activities.length && activities[0].type === 4) {
@ -158,14 +158,10 @@
<% } %>
</div>
<div class="activity-wrapper-inner">
<% if (art) { %>
<div class="activity-image-wrapper">
<img class="activity-image" src="<%= art %>" alt="Art" <%= activity.assets?.large_text ? `title="${activity.assets.large_text}"` : '' %>>
<% if (smallArt) { %>
<img class="activity-image-small" src="<%= smallArt %>" alt="Small Art" <%= activity.assets?.small_text ? `title="${activity.assets.small_text}"` : '' %>>
<% } %>
<div class="activity-image-wrapper <%= art ?? "no-asset" %>">
<img class="activity-image <%= art ? '' : 'no-asset' %>" src="<%= art || '' %>" data-name="<%= activity.name.replace(/"/g, '&quot;') %>" <%= activity.assets?.large_text ? `title="${activity.assets.large_text}"` : '' %>>
<img class="activity-image-small <%= smallArt ?? "no-asset" %>" src="<%= smallArt %>" <%= activity.assets?.small_text ? `title="${activity.assets.small_text}"` : '' %>>
</div>
<% } %>
<div class="activity-content">
<div class="inner-content">
<%