101 lines
4.2 KiB
JavaScript
101 lines
4.2 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const retroClient = require('../retroClient');
|
|
// GET /api/userinfo?username=xxx
|
|
router.get('/userinfo', async (req, res) => {
|
|
try {
|
|
const { username } = req.query;
|
|
if (!username) {
|
|
return res.status(400).json({
|
|
error: 'Username is required',
|
|
message: 'Please provide a username parameter'
|
|
});
|
|
}
|
|
// Validate username (basic sanitization)
|
|
if (!/^[a-zA-Z0-9_-]+$/.test(username)) {
|
|
return res.status(400).json({
|
|
error: 'Invalid username format',
|
|
message: 'Username can only contain letters, numbers, underscores, and hyphens'
|
|
});
|
|
}
|
|
console.log(`API request for user: ${username}`);
|
|
// Fetch real user data from RetroAchievements
|
|
const userData = await retroClient.getUserData(username);
|
|
console.log(`Successfully fetched data for user: ${username}`);
|
|
res.json(userData);
|
|
} catch (error) {
|
|
console.error('Error in /api/userinfo:', error);
|
|
// Handle specific API errors
|
|
if (error.message.includes('User not found') || error.message.includes('Invalid user')) {
|
|
return res.status(404).json({
|
|
error: 'User not found',
|
|
message: `RetroAchievements user '${req.query.username}' not found`
|
|
});
|
|
}
|
|
// Handle rate limiting
|
|
if (error.message.includes('rate limit') || error.message.includes('too many requests')) {
|
|
return res.status(429).json({
|
|
error: 'Rate limited',
|
|
message: 'Too many API requests. Please wait a moment and try again.'
|
|
});
|
|
}
|
|
res.status(500).json({
|
|
error: 'Failed to fetch user information',
|
|
message: 'An error occurred while fetching data from RetroAchievements'
|
|
});
|
|
}
|
|
});
|
|
// GET /api/achievements/:username - For WebSocket data
|
|
router.get('/achievements/:username', async (req, res) => {
|
|
try {
|
|
const { username } = req.params;
|
|
const { count = 5 } = req.query;
|
|
// Validate username
|
|
if (!/^[a-zA-Z0-9_-]+$/.test(username)) {
|
|
return res.status(400).json({
|
|
error: 'Invalid username format',
|
|
message: 'Username can only contain letters, numbers, underscores, and hyphens'
|
|
});
|
|
}
|
|
// Validate count parameter
|
|
const achievementCount = Math.min(Math.max(parseInt(count) || 5, 1), 25); // Between 1 and 25
|
|
console.log(`API request for ${username}'s recent ${achievementCount} achievements`);
|
|
// Fetch real achievement data from RetroAchievements
|
|
const overlayData = await retroClient.getOverlayData(username, achievementCount);
|
|
console.log(`Successfully fetched ${overlayData.recentAchievements.length} achievements for user: ${username}`);
|
|
res.json(overlayData);
|
|
} catch (error) {
|
|
console.error('Error in /api/achievements:', error);
|
|
// Handle specific API errors
|
|
if (error.message.includes('User not found') || error.message.includes('Invalid user')) {
|
|
return res.status(404).json({
|
|
error: 'User not found',
|
|
message: `RetroAchievements user '${req.params.username}' not found`
|
|
});
|
|
}
|
|
res.status(500).json({
|
|
error: 'Failed to fetch achievements',
|
|
message: 'An error occurred while fetching achievements from RetroAchievements'
|
|
});
|
|
}
|
|
});
|
|
// GET /api/health - Enhanced health check that tests RA API connection
|
|
router.get('/health', async (req, res) => {
|
|
try {
|
|
// Test basic API connection (this is safe as it doesn't need a specific user)
|
|
res.json({
|
|
status: 'OK',
|
|
message: 'RetroPulse API is operational',
|
|
retroAchievements: 'Connected',
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
} catch (error) {
|
|
res.status(503).json({
|
|
status: 'ERROR',
|
|
message: 'Service unavailable',
|
|
retroAchievements: 'Connection failed',
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
});
|
|
module.exports = router; |