mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-21 18:04:10 -05:00
Show Splatoon 3 Splatfest team image in presence embed
This commit is contained in:
parent
597d3ba554
commit
b5d86bf2d6
|
|
@ -702,6 +702,8 @@ curl http://[::1]:12345/api/presence/0123456789abcdef/embed?transparent=1 > embe
|
|||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed?width=800 > embed.svg
|
||||
# ... with Splatoon 3 presence
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed?include-splatoon3=1 > embed.svg
|
||||
# ... with Splatoon 3 Splatfest team
|
||||
curl 'http://[::1]:12345/api/presence/0123456789abcdef/embed?include-splatoon3=1&show-splatoon3-fest-team=1' > embed.svg
|
||||
```
|
||||
|
||||
Example EventStream use:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { FestVoteState } from 'splatnet3-types/splatnet3';
|
||||
import type { Arguments as ParentArguments } from '../util.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
|
|
@ -26,6 +27,10 @@ export function builder(yargs: Argv<ParentArguments>) {
|
|||
}).option('friend-code', {
|
||||
describe: 'Friend code',
|
||||
type: 'string',
|
||||
}).option('show-splatoon3-fest-team', {
|
||||
describe: 'Show Splatoon 3 Splatfest team',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
}).option('scale', {
|
||||
describe: 'Image scale',
|
||||
type: 'number',
|
||||
|
|
@ -64,6 +69,7 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
const image_urls = [result.friend.imageUri];
|
||||
|
||||
if ('imageUri' in result.friend.presence.game) image_urls.push(result.friend.presence.game.imageUri);
|
||||
if (argv.showSplatoon3FestTeam && result.splatoon3_fest_team?.myVoteState === FestVoteState.VOTED) image_urls.push(result.splatoon3_fest_team.image.url);
|
||||
|
||||
const url_map: Record<string, readonly [name: string, data: Uint8Array, type: string]> = {};
|
||||
|
||||
|
|
@ -77,7 +83,9 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
url_map[url] = [url, data, 'image/jpeg'];
|
||||
}));
|
||||
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, argv.friendCode, argv.scale, argv.transparent, width);
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, argv.friendCode, {
|
||||
show_splatoon3_fest_team: argv.showSplatoon3FestTeam,
|
||||
}, argv.scale, argv.transparent, width);
|
||||
const [image, type] = await renderUserEmbedImage(svg, format);
|
||||
|
||||
console.warn('output type', type);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import * as os from 'node:os';
|
|||
import * as net from 'node:net';
|
||||
import express, { Request, Response } from 'express';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { FestVoteState } from 'splatnet3-types/splatnet3';
|
||||
import type { Arguments as ParentArguments } from '../util.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
|
|
@ -100,7 +101,7 @@ class Server extends HttpServer {
|
|||
const [presence, user, data] = await getPresenceFromUrl(this.base_url + '/' + presence_user_nsaid + qs);
|
||||
const result = data as PresenceResponse;
|
||||
|
||||
const {theme, friend_code, transparent, width} = getUserEmbedOptionsFromRequest(req);
|
||||
const {theme, friend_code, transparent, width, options} = getUserEmbedOptionsFromRequest(req);
|
||||
|
||||
const etag = createHash('sha256').update(JSON.stringify({
|
||||
data,
|
||||
|
|
@ -109,6 +110,7 @@ class Server extends HttpServer {
|
|||
friend_code,
|
||||
transparent,
|
||||
width,
|
||||
options,
|
||||
v: version + '-' + git?.revision,
|
||||
})).digest('base64url');
|
||||
|
||||
|
|
@ -121,6 +123,7 @@ class Server extends HttpServer {
|
|||
const image_urls = [result.friend.imageUri];
|
||||
|
||||
if ('imageUri' in result.friend.presence.game) image_urls.push(result.friend.presence.game.imageUri);
|
||||
if (options.show_splatoon3_fest_team && result.splatoon3_fest_team?.image.url) image_urls.push(result.splatoon3_fest_team.image.url);
|
||||
|
||||
const url_map: Record<string, readonly [name: string, data: Uint8Array, type: string]> = {};
|
||||
|
||||
|
|
@ -132,7 +135,7 @@ class Server extends HttpServer {
|
|||
url_map[url] = [url, data, 'image/jpeg'];
|
||||
}));
|
||||
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, friend_code, 1, transparent, width);
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, friend_code, options, 1, transparent, width);
|
||||
const [image, type] = await renderUserEmbedImage(svg, format);
|
||||
|
||||
res.setHeader('Content-Type', type);
|
||||
|
|
@ -159,6 +162,7 @@ class Server extends HttpServer {
|
|||
const image_urls = [result.friend.imageUri];
|
||||
|
||||
if ('imageUri' in result.friend.presence.game) image_urls.push(result.friend.presence.game.imageUri);
|
||||
if (result.splatoon3_fest_team?.myVoteState === FestVoteState.VOTED) image_urls.push(result.splatoon3_fest_team.image.url);
|
||||
|
||||
const url_map: Record<string, readonly [name: string, data: Uint8Array, type: string]> = {};
|
||||
|
||||
|
|
@ -170,7 +174,9 @@ class Server extends HttpServer {
|
|||
url_map[url] = [url, data, 'image/jpeg'];
|
||||
}));
|
||||
|
||||
const svg = renderUserEmbedSvg(result, url_map, PresenceEmbedTheme.LIGHT, undefined, 1, true, 800);
|
||||
const svg = renderUserEmbedSvg(result, url_map, PresenceEmbedTheme.LIGHT, undefined, {
|
||||
show_splatoon3_fest_team: true,
|
||||
}, 2, true, 800);
|
||||
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.write(`<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width,initial-scale=1"/><style>body{margin:0;min-height:100vh;width:100vw;min-width:fit-content;display:flex;align-items:center;justify-content:center}</style></head>`);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import * as fs from 'node:fs/promises';
|
|||
import * as path from 'node:path';
|
||||
import { Request } from 'express';
|
||||
import sharp from 'sharp';
|
||||
import { CoopRule, FriendOnlineState, StageScheduleResult } from 'splatnet3-types/splatnet3';
|
||||
import { CoopRule, FestVoteState, FriendOnlineState, StageScheduleResult } from 'splatnet3-types/splatnet3';
|
||||
import { dir } from '../../util/product.js';
|
||||
import createDebug from '../../util/debug.js';
|
||||
import { Game, PresenceState } from '../../api/coral-types.js';
|
||||
|
|
@ -50,11 +50,16 @@ const embed_themes: Record<PresenceEmbedTheme, PresenceEmbedThemeColours> = {
|
|||
},
|
||||
};
|
||||
|
||||
interface UserEmbedOptions {
|
||||
show_splatoon3_fest_team?: boolean;
|
||||
}
|
||||
|
||||
const embed_titles: Partial<Record<string, (
|
||||
result: PresenceResponse,
|
||||
url_map: Record<string, string | readonly [url: string, data: Uint8Array, type: string]>,
|
||||
image: (url: string) => string | undefined,
|
||||
theme?: PresenceEmbedTheme,
|
||||
options?: UserEmbedOptions,
|
||||
) => readonly [svg: string, height: number, override_description: string | null]>> = {
|
||||
'0100c2500fc20000': renderUserSplatoon3EmbedPartialSvg,
|
||||
};
|
||||
|
|
@ -65,7 +70,7 @@ export function getUserEmbedOptionsFromRequest(req: Request) {
|
|||
const theme = url.searchParams.get('theme') === 'dark' ? PresenceEmbedTheme.DARK : PresenceEmbedTheme.LIGHT;
|
||||
const friend_code = url.searchParams.getAll('friend-code').find(c => c.match(/^\d{4}-\d{4}-\d{4}$/));
|
||||
const transparent = url.searchParams.get('transparent') === '1';
|
||||
|
||||
|
||||
let width = url.searchParams.getAll('width')
|
||||
.map(w => parseInt(w))
|
||||
.map(w => transparent ? w + 60 : w)
|
||||
|
|
@ -74,7 +79,11 @@ export function getUserEmbedOptionsFromRequest(req: Request) {
|
|||
if (!width) width = 500;
|
||||
if (width > 1500) width = 1500;
|
||||
|
||||
return {theme, friend_code, transparent, width};
|
||||
const options: UserEmbedOptions = {
|
||||
show_splatoon3_fest_team: url.searchParams.get('show-splatoon3-fest-team') === '1',
|
||||
};
|
||||
|
||||
return {theme, friend_code, transparent, width, options};
|
||||
}
|
||||
|
||||
export async function renderUserEmbedImage(
|
||||
|
|
@ -112,6 +121,7 @@ export function renderUserEmbedSvg(
|
|||
url_map: Record<string, string | readonly [url: string, data: Uint8Array, type: string]>,
|
||||
theme = PresenceEmbedTheme.LIGHT,
|
||||
friend_code?: string,
|
||||
options?: UserEmbedOptions,
|
||||
scale = 1,
|
||||
transparent = false,
|
||||
width = 500,
|
||||
|
|
@ -132,7 +142,7 @@ export function renderUserEmbedSvg(
|
|||
Buffer.from(url_map[url][1]).toString('base64') :
|
||||
url_map[url] as string | undefined;
|
||||
|
||||
const title_extra = result.title ? embed_titles[result.title.id]?.call(null, result, url_map, image, theme) : null;
|
||||
const title_extra = result.title ? embed_titles[result.title.id]?.call(null, result, url_map, image, theme, options) : null;
|
||||
if (title_extra) height += title_extra[1];
|
||||
|
||||
return htmlentities`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
|
@ -181,6 +191,11 @@ export function renderUserEmbedSvg(
|
|||
<text x="30" y="186" fill="${colours.text}" font-size="14" font-family="${font_family}" font-weight="400">Friend code: SW-${friend_code}</text>
|
||||
` : ''}}
|
||||
|
||||
${{[RawValueSymbol]: options?.show_splatoon3_fest_team && result.splatoon3_fest_team?.myVoteState === FestVoteState.VOTED ? htmlentities`
|
||||
<image x="${width - 60}" y="33" width="30" height="30"
|
||||
href="${image(result.splatoon3_fest_team.image.url) ?? result.splatoon3_fest_team.image.url}" />
|
||||
` : ''}}
|
||||
|
||||
${{[RawValueSymbol]: title_extra?.[0] ?? ''}}
|
||||
</svg>
|
||||
`;
|
||||
|
|
@ -212,6 +227,7 @@ function renderUserSplatoon3EmbedPartialSvg(
|
|||
url_map: Record<string, string | readonly [url: string, data: Uint8Array, type: string]>,
|
||||
image: (url: string) => string | undefined,
|
||||
theme = PresenceEmbedTheme.LIGHT,
|
||||
options?: UserEmbedOptions,
|
||||
) {
|
||||
if (result.splatoon3?.vsMode && (
|
||||
result.splatoon3.onlineState === FriendOnlineState.VS_MODE_FIGHTING ||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user