mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-07-18 01:09:52 -05:00
Update documentation, add width option
This commit is contained in:
parent
01fdfb1fec
commit
b7afcfb175
35
docs/cli.md
35
docs/cli.md
|
|
@ -664,9 +664,44 @@ curl http://[::1]:12345/api/presence/0123456789abcdef
|
|||
# Fetch presence data for a specific user including Splatoon 3 presence using curl
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef?include-splatoon3=1
|
||||
|
||||
# Fetch Splatoon 3 fest voting history for a specific user using curl
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/splatoon3-fest-votes
|
||||
# Fetch Splatoon 3 fest voting history including all prevotes for a specific user using curl
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/splatoon3-fest-votes?include-all=1
|
||||
|
||||
# Watch for presence events
|
||||
curl --no-buffer http://[::1]:12345/api/presence/0123456789abcdef/events
|
||||
curl --no-buffer http://[::1]:12345/api/presence/0123456789abcdef/events?include-splatoon3=1
|
||||
|
||||
# Save a user's current picture
|
||||
curl -L http://[::1]:12345/api/presence/0123456789abcdef/image > image.jpeg
|
||||
|
||||
# Show the Nintendo eShop page for a user's current title
|
||||
# http://[::1]:12345/api/presence/0123456789abcdef/title/redirect
|
||||
# Redirect to a friend code URL if not playing
|
||||
# http://[::1]:12345/api/presence/0123456789abcdef/title/redirect?friend-code=0000-0000-0000&friend-code-hash=0000000000
|
||||
# Redirect to another URL if not playing
|
||||
# http://[::1]:12345/api/presence/0123456789abcdef/title/redirect?fallback-url=https://example.com
|
||||
# Signal to the browser to cancel navigation if not playing
|
||||
# http://[::1]:12345/api/presence/0123456789abcdef/title/redirect?fallback-prevent-navigation=1
|
||||
|
||||
# Generate an SVG showing a user's presence
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed > embed.svg
|
||||
# Generate a PNG/JPEG/WEBP showing a user's presence
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed.png > embed.png
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed.jpeg > embed.jpeg
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed.webp > embed.webp
|
||||
# ... using a specific theme
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed?theme=light > embed.svg
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed?theme=dark > embed.svg
|
||||
# ... including a friend code
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed?friend-code=0000-0000-0000 > embed.svg
|
||||
# ... without a background and border
|
||||
curl http://[::1]:12345/api/presence/0123456789abcdef/embed?transparent=1 > embed.svg
|
||||
# ... with a custom width (500 to 1500, or 440 to 1440 with transparency)
|
||||
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
|
||||
```
|
||||
|
||||
Example EventStream use:
|
||||
|
|
|
|||
|
|
@ -1189,13 +1189,14 @@ class Server extends HttpServer {
|
|||
|
||||
const result = await this.handlePresenceRequest(req, null, presence_user_nsaid);
|
||||
|
||||
const {theme, friend_code, transparent} = getUserEmbedOptionsFromRequest(req);
|
||||
const {theme, friend_code, transparent, width} = getUserEmbedOptionsFromRequest(req);
|
||||
|
||||
const etag = createHash('sha256').update(JSON.stringify({
|
||||
result,
|
||||
theme,
|
||||
friend_code,
|
||||
transparent,
|
||||
width,
|
||||
v: version + '-' + git?.revision,
|
||||
})).digest('base64url');
|
||||
|
||||
|
|
@ -1207,10 +1208,11 @@ class Server extends HttpServer {
|
|||
|
||||
const url_map = await this.downloadImages(result, this.getResourceBaseUrls(req));
|
||||
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, friend_code);
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, friend_code, 1, transparent, width);
|
||||
const [image, type] = await renderUserEmbedImage(svg, format);
|
||||
|
||||
res.setHeader('Content-Type', type);
|
||||
res.setHeader('Cache-Control', 'public, no-cache'); // no-cache means store but revalidate
|
||||
res.setHeader('Etag', '"' + etag + '"');
|
||||
res.end(image);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ export function builder(yargs: Argv<ParentArguments>) {
|
|||
describe: 'Remove border and use transparent background',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
}).option('width', {
|
||||
describe: 'Image width',
|
||||
type: 'number',
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -51,6 +54,10 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
throw new TypeError('Invalid friend code');
|
||||
}
|
||||
|
||||
const width = argv.width ?
|
||||
argv.transparent ? argv.width + 60 : argv.width :
|
||||
500;
|
||||
|
||||
const [presence, user, data] = await getPresenceFromUrl(argv.url);
|
||||
const result = data as PresenceResponse;
|
||||
|
||||
|
|
@ -70,7 +77,7 @@ 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);
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, argv.friendCode, argv.scale, argv.transparent, width);
|
||||
const [image, type] = await renderUserEmbedImage(svg, format);
|
||||
|
||||
console.warn('output type', type);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,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} = getUserEmbedOptionsFromRequest(req);
|
||||
const {theme, friend_code, transparent, width} = getUserEmbedOptionsFromRequest(req);
|
||||
|
||||
const etag = createHash('sha256').update(JSON.stringify({
|
||||
data,
|
||||
|
|
@ -108,6 +108,7 @@ class Server extends HttpServer {
|
|||
theme,
|
||||
friend_code,
|
||||
transparent,
|
||||
width,
|
||||
v: version + '-' + git?.revision,
|
||||
})).digest('base64url');
|
||||
|
||||
|
|
@ -131,10 +132,11 @@ class Server extends HttpServer {
|
|||
url_map[url] = [url, data, 'image/jpeg'];
|
||||
}));
|
||||
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, friend_code, 1, transparent);
|
||||
const svg = renderUserEmbedSvg(result, url_map, theme, friend_code, 1, transparent, width);
|
||||
const [image, type] = await renderUserEmbedImage(svg, format);
|
||||
|
||||
res.setHeader('Content-Type', type);
|
||||
res.setHeader('Cache-Control', 'public, no-cache'); // no-cache means store but revalidate
|
||||
res.setHeader('Etag', '"' + etag + '"');
|
||||
res.end(image);
|
||||
}
|
||||
|
|
@ -168,7 +170,7 @@ class Server extends HttpServer {
|
|||
url_map[url] = [url, data, 'image/jpeg'];
|
||||
}));
|
||||
|
||||
const svg = renderUserEmbedSvg(result, url_map, PresenceEmbedTheme.LIGHT, undefined, 1, true);
|
||||
const svg = renderUserEmbedSvg(result, url_map, PresenceEmbedTheme.LIGHT, undefined, 1, 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>`);
|
||||
|
|
|
|||
|
|
@ -65,8 +65,16 @@ 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)
|
||||
.find(w => !isNaN(w) && w >= 500);
|
||||
|
||||
return {theme, friend_code, transparent};
|
||||
if (!width) width = 500;
|
||||
if (width > 1500) width = 1500;
|
||||
|
||||
return {theme, friend_code, transparent, width};
|
||||
}
|
||||
|
||||
export async function renderUserEmbedImage(
|
||||
|
|
@ -106,8 +114,9 @@ export function renderUserEmbedSvg(
|
|||
friend_code?: string,
|
||||
scale = 1,
|
||||
transparent = false,
|
||||
width = 500,
|
||||
) {
|
||||
let width = 500;
|
||||
if (width < 500) width = 500;
|
||||
let height = 180;
|
||||
if (friend_code) height += 40;
|
||||
|
||||
|
|
@ -155,9 +164,9 @@ export function renderUserEmbedSvg(
|
|||
|
||||
<image x="30" y="30" width="120" height="120"
|
||||
href="${image(result.friend.imageUri) ?? result.friend.imageUri}" />
|
||||
<text x="180" y="57" fill="${colours.text}" font-size="26" font-family="${font_family}" font-weight="500">${result.friend.name}</text>
|
||||
<text x="180" y="57" fill="${colours.text}" font-size="26" font-family="${font_family}" font-weight="500" mask="url(#mask-out)">${result.friend.name}</text>
|
||||
|
||||
<line x1="180" y1="73" x2="470" y2="73" stroke="${colours.separator}" />
|
||||
<line x1="180" y1="73" x2="${width - 30}" y2="73" stroke="${colours.separator}" />
|
||||
|
||||
${{[RawValueSymbol]: game && (state === PresenceState.ONLINE || state === PresenceState.PLAYING) ? htmlentities`
|
||||
<image x="180" y="87" width="60" height="60"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user