fix(events): fix Ticketmaster URL encoding + add error logging
Colons in startDateTime were being percent-encoded which Ticketmaster may reject. Also log errors/status so backend logs reveal the cause when no events appear. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
2c9d3a9dde
commit
7fe755379b
1 file changed
+14
-9
@@ -317,20 +317,24 @@ app.get('/api/itunes/:endpoint', (req, res) => {
|
|||||||
|
|
||||||
app.get('/api/events/:artist', (req, res) => {
|
app.get('/api/events/:artist', (req, res) => {
|
||||||
const key = CONFIG.ticketmasterKey;
|
const key = CONFIG.ticketmasterKey;
|
||||||
if (!key) return res.json([]);
|
if (!key) { console.warn('[events] TICKETMASTER_API_KEY not set'); return res.json([]); }
|
||||||
const artist = req.params.artist;
|
const artist = req.params.artist;
|
||||||
const now = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
const now = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z'); // 2024-06-08T12:00:00Z
|
||||||
const url = `https://app.ticketmaster.com/discovery/v2/events.json` +
|
const url = `https://app.ticketmaster.com/discovery/v2/events.json` +
|
||||||
`?keyword=${encodeURIComponent(artist)}&classificationName=music` +
|
`?keyword=${encodeURIComponent(artist)}&classificationName=music` +
|
||||||
`&startDateTime=${encodeURIComponent(now)}&size=20&sort=date%2Casc` +
|
`&startDateTime=${now}&size=20&sort=date,asc` +
|
||||||
`&apikey=${encodeURIComponent(key)}`;
|
`&apikey=${key}`;
|
||||||
https.get(url, { headers: { 'Accept': 'application/json' } }, upstream => {
|
https.get(url, { headers: { 'Accept': 'application/json' } }, upstream => {
|
||||||
let body = '';
|
let body = '';
|
||||||
upstream.on('data', d => body += d);
|
upstream.on('data', d => body += d);
|
||||||
upstream.on('end', () => {
|
upstream.on('end', () => {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(body);
|
const data = JSON.parse(body);
|
||||||
const raw = data?._embedded?.events || [];
|
if (upstream.statusCode !== 200 || data.fault || data.errors) {
|
||||||
|
console.error('[events] Ticketmaster error:', upstream.statusCode, JSON.stringify(data).slice(0, 200));
|
||||||
|
return res.json([]);
|
||||||
|
}
|
||||||
|
const raw = data?._embedded?.events || [];
|
||||||
const events = raw.map(e => {
|
const events = raw.map(e => {
|
||||||
const venue = e._embedded?.venues?.[0] || {};
|
const venue = e._embedded?.venues?.[0] || {};
|
||||||
const start = e.dates?.start || {};
|
const start = e.dates?.start || {};
|
||||||
@@ -342,17 +346,18 @@ app.get('/api/events/:artist', (req, res) => {
|
|||||||
return {
|
return {
|
||||||
datetime: dt,
|
datetime: dt,
|
||||||
venue: {
|
venue: {
|
||||||
name: venue.name || '',
|
name: venue.name || '',
|
||||||
city: venue.city?.name || '',
|
city: venue.city?.name || '',
|
||||||
country: venue.country?.name || '',
|
country: venue.country?.name || '',
|
||||||
},
|
},
|
||||||
offers: e.url ? [{ url: e.url, status: soldOut ? 'unavailable' : 'available' }] : [],
|
offers: e.url ? [{ url: e.url, status: soldOut ? 'unavailable' : 'available' }] : [],
|
||||||
};
|
};
|
||||||
}).filter(e => e.datetime);
|
}).filter(e => e.datetime);
|
||||||
|
console.log(`[events] ${artist}: ${events.length} events`);
|
||||||
res.json(events);
|
res.json(events);
|
||||||
} catch { res.json([]); }
|
} catch(err) { console.error('[events] parse error:', err); res.json([]); }
|
||||||
});
|
});
|
||||||
}).on('error', () => res.json([]));
|
}).on('error', e => { console.error('[events] request error:', e.message); res.json([]); });
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/api/health', (req, res) => {
|
app.get('/api/health', (req, res) => {
|
||||||
|
|||||||
Reference in new issue
Block a user