Fetch vrc.tl events via Cloudflare Worker relay
vrc.tl returns 403 for the VPS IP range. Route lookups through a relay Worker (relay/), configured via vrctl.relayUrl/relaySecret in config.json. Also handle events without eventSlots/performers instead of crashing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MrxnVXujrZqNrENxJZfVkU
This commit is contained in:
@@ -6,5 +6,9 @@
|
|||||||
"clientID": "",
|
"clientID": "",
|
||||||
"clientSecret": ""
|
"clientSecret": ""
|
||||||
},
|
},
|
||||||
"lfmKey": ""
|
"lfmKey": "",
|
||||||
|
"vrctl": {
|
||||||
|
"relayUrl": "",
|
||||||
|
"relaySecret": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
const { Events } = require('discord.js');
|
const { Events } = require('discord.js');
|
||||||
const axios = require('axios').default;
|
const axios = require('axios').default;
|
||||||
|
const { vrctl } = require(process.env.CONFIG_FILE ? `../${process.env.CONFIG_FILE}` : '../config.json');
|
||||||
|
|
||||||
const SWARM_EVENTS_CHANNEL_ID = '1536067515115905155';
|
const SWARM_EVENTS_CHANNEL_ID = '1536067515115905155';
|
||||||
const VRC_CROSSPOST_CHANNEL_ID = '1438261670916133055';
|
const VRC_CROSSPOST_CHANNEL_ID = '1438261670916133055';
|
||||||
@@ -19,15 +20,17 @@ module.exports = {
|
|||||||
|
|
||||||
for (const eventId of eventIds) {
|
for (const eventId of eventIds) {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`https://vrc.tl/api/v1/events/${eventId}`);
|
const { data } = await axios.get(`${vrctl.relayUrl}/events/${eventId}`, {
|
||||||
|
headers: { 'x-relay-secret': vrctl.relaySecret },
|
||||||
|
});
|
||||||
const event = data.events?.[0];
|
const event = data.events?.[0];
|
||||||
if (!event) continue;
|
if (!event) continue;
|
||||||
|
|
||||||
const performersById = new Map(data.performers.map(performer => [performer.id, performer.name]));
|
const performersById = new Map((data.performers ?? []).map(performer => [performer.id, performer.name]));
|
||||||
|
|
||||||
const lineup = [...event.eventSlots]
|
const lineup = [...(event.eventSlots ?? [])]
|
||||||
.sort((a, b) => a.start - b.start)
|
.sort((a, b) => a.start - b.start)
|
||||||
.flatMap(slot => [...slot.performers]
|
.flatMap(slot => [...(slot.performers ?? [])]
|
||||||
.sort((a, b) => a.order - b.order)
|
.sort((a, b) => a.order - b.order)
|
||||||
.map(slotPerformer => performersById.get(slotPerformer.performerId)))
|
.map(slotPerformer => performersById.get(slotPerformer.performerId)))
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|||||||
10
relay/README.md
Normal file
10
relay/README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# vrc.tl relay
|
||||||
|
|
||||||
|
Cloudflare Worker that proxies vrc.tl event lookups (vrc.tl blocks the VPS IP range).
|
||||||
|
Only serves `GET /events/<id>` and requires an `x-relay-secret` header.
|
||||||
|
|
||||||
|
cd relay
|
||||||
|
npx wrangler deploy
|
||||||
|
npx wrangler secret put RELAY_SECRET
|
||||||
|
|
||||||
|
Set `vrctl.relayUrl` and `vrctl.relaySecret` in the bot's config.json.
|
||||||
20
relay/src/index.js
Normal file
20
relay/src/index.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Minimal relay for vrc.tl event lookups. Only GET /events/<digits>, requires secret header.
|
||||||
|
export default {
|
||||||
|
async fetch(request, env) {
|
||||||
|
if (request.method !== 'GET') return new Response('Method not allowed', { status: 405 });
|
||||||
|
if (!env.RELAY_SECRET || request.headers.get('x-relay-secret') !== env.RELAY_SECRET) {
|
||||||
|
return new Response('Unauthorized', { status: 401 });
|
||||||
|
}
|
||||||
|
const match = new URL(request.url).pathname.match(/^\/events\/(\d{1,10})$/);
|
||||||
|
if (!match) return new Response('Not found', { status: 404 });
|
||||||
|
|
||||||
|
const upstream = await fetch(`https://vrc.tl/api/v1/events/${match[1]}`, {
|
||||||
|
headers: { accept: 'application/json' },
|
||||||
|
cf: { cacheTtl: 300, cacheEverything: true },
|
||||||
|
});
|
||||||
|
return new Response(upstream.body, {
|
||||||
|
status: upstream.status,
|
||||||
|
headers: { 'content-type': upstream.headers.get('content-type') ?? 'application/json' },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
3
relay/wrangler.toml
Normal file
3
relay/wrangler.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
name = "vrctl-relay"
|
||||||
|
main = "src/index.js"
|
||||||
|
compatibility_date = "2026-09-01"
|
||||||
Reference in New Issue
Block a user