Skip to content

Commit aadffd7

Browse files
committed
add servers/:ip/:port endpoint
1 parent bf943b0 commit aadffd7

1 file changed

Lines changed: 136 additions & 0 deletions

File tree

src/api/servers.js

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,140 @@ router.get("/:ip", async (req, res) => {
363363
}
364364
});
365365

366+
/**
367+
* @swagger
368+
* /servers/{ip}/{port}:
369+
* get:
370+
* summary: Get server by IP and port
371+
* description: Returns detailed information for a specific server by IP address and port
372+
* tags: [Servers]
373+
* parameters:
374+
* - in: path
375+
* name: ip
376+
* required: true
377+
* schema:
378+
* type: string
379+
* description: Server IP address
380+
* example: "185.107.96.59"
381+
* - in: path
382+
* name: port
383+
* required: true
384+
* schema:
385+
* type: integer
386+
* description: Server port
387+
* example: 27015
388+
* responses:
389+
* 200:
390+
* description: Successful response with server details
391+
* content:
392+
* application/json:
393+
* schema:
394+
* $ref: '#/components/schemas/Server'
395+
* 400:
396+
* description: Invalid IP address or port format
397+
* content:
398+
* application/json:
399+
* schema:
400+
* type: object
401+
* properties:
402+
* error:
403+
* type: string
404+
* example: "Invalid IP address format"
405+
* 404:
406+
* description: Server not found
407+
* content:
408+
* application/json:
409+
* schema:
410+
* type: object
411+
* properties:
412+
* error:
413+
* type: string
414+
* example: "Server not found"
415+
* 500:
416+
* description: Server error
417+
* content:
418+
* application/json:
419+
* schema:
420+
* type: object
421+
* properties:
422+
* error:
423+
* type: string
424+
* example: "Server fetch error"
425+
*/
426+
router.get("/:ip/:port", async (req, res) => {
427+
try {
428+
const { ip, port } = req.params;
429+
430+
if (!isValidIP(ip)) {
431+
return res.status(400).json({ error: "Invalid IP address format" });
432+
}
433+
434+
const portNum = parseInt(port, 10);
435+
if (isNaN(portNum) || portNum < 1 || portNum > 65535) {
436+
return res.status(400).json({ error: "Invalid port number" });
437+
}
438+
439+
const [rows] = await pool.query(
440+
"SELECT * FROM servers WHERE ip = ? AND port = ?",
441+
[ip, portNum]
442+
);
443+
444+
if (rows.length === 0) {
445+
return res.status(404).json({ error: "Server not found" });
446+
}
447+
448+
const server = rows[0];
449+
let playersList = [];
450+
451+
if (server.players_list) {
452+
try {
453+
playersList =
454+
typeof server.players_list === "string"
455+
? JSON.parse(server.players_list)
456+
: server.players_list;
457+
458+
// Remove IP addresses from player data for privacy
459+
playersList = playersList.map((player) => {
460+
const { ip, ...playerWithoutIp } = player;
461+
return playerWithoutIp;
462+
});
463+
} catch (e) {
464+
logger.error(
465+
`Failed to parse players_list for ${server.ip}:${server.port}`,
466+
{ error: e.message },
467+
);
468+
playersList = [];
469+
}
470+
}
471+
472+
const response = {
473+
ip: server.ip,
474+
port: server.port,
475+
game: server.game,
476+
hostname: server.hostname,
477+
version: server.version,
478+
os: server.os,
479+
secure: server.secure,
480+
status: server.status,
481+
map: server.map,
482+
player_count: server.player_count,
483+
maxplayers: server.maxplayers,
484+
bot_count: server.bot_count,
485+
players_list: playersList,
486+
region: server.region,
487+
domain: server.domain,
488+
api_id: server.api_id,
489+
kzt_id: server.kzt_id,
490+
tickrate: server.tickrate,
491+
last_update: server.last_update,
492+
created_at: server.created_at,
493+
};
494+
495+
res.json(response);
496+
} catch (e) {
497+
logger.error(`Server fetch error for ${req.params.ip}:${req.params.port}: ${e.message}`);
498+
res.status(500).json({ error: "Server fetch error" });
499+
}
500+
});
501+
366502
module.exports = router;

0 commit comments

Comments
 (0)