import { getOverrideHandler, getOverridePreHandler } from '../config.js' import { toSymboUUID, uuidToNoSymboUUID } from '../generator.js' import { getPlayerSerialization, Player, PlayerSeriliazationSchema } from '../models/player.js' import { Token } from '../models/token.js' /* Key: string Username Value: { accessToken: string, serverId: string, ip: string } */ const joinServerRequest = new Map() export const join = { method: 'POST', url: '/sessionserver/session/minecraft/join', schema: { summary: "加入服务器", description: "详情请见 authlib-injector 文档。", tags: [ "Sessionserver" ], body: { "accessToken": { "type": "string" }, "selectedProfile": { "type": "string" }, "serverId": { "type": "string" }, }, response: { 204: { type: "null" } } }, preHandler: getOverridePreHandler('/sessionserver/session/minecraft/join'), handler: getOverrideHandler('/sessionserver/session/minecraft/join') ?? async function (req, rep) { const { accessToken, selectedProfile, serverId } = req.body const user = await await Player.findOne({ uuid: toSymboUUID(selectedProfile) }) if (!user) { return await rep.code(400).send({ error: "IllegalArgumentException", errorMessage: "请求内容不正确", cause: "用户不存在" }) } const session = await Token.findOne({ token: accessToken }) if (!session) { return await rep.code(401).send({ error: "IllegalArgumentException", errorMessage: "无效会话", cause: "无效会话" }) } if (Date.now() > session.expireDate) { return await rep.code(401).send({ error: "IllegalArgumentException", errorMessage: "无效会话", cause: "会话已过期" }) } joinServerRequest.set(session.uuid, { accessToken: accessToken, serverId: serverId, ip: req.headers['x-forwarded-for'] || req.ip }) await rep.code(204).send() } } export const hasJoined = { method: 'GET', url: '/sessionserver/session/minecraft/hasJoined', schema: { summary: "查询是否已加入服务器", description: "详情请见 authlib-injector 文档。", tags: [ "Sessionserver" ], query: { "username": { "type": "string" }, "serverId": { "type": "string" }, "ip": { "type": "string" } }, response: { 200: PlayerSeriliazationSchema, 204: { type: "null" } } }, preHandler: getOverridePreHandler('/sessionserver/session/minecraft/hasJoined'), handler: getOverrideHandler('/sessionserver/session/minecraft/hasJoined') ?? async function (req, rep) { const { username, serverId, ip } = req.query const player = await Player.findOne({ username }) if (!player) { return await rep.code(400).send({ error: "IllegalArgumentException", errorMessage: "请求内容不正确", cause: "用户不存在" }) } const request = joinServerRequest.get(player.uuid) this.log.info(request) if(ip) { if(ip !== request.ip) { return await rep.code(401).send({ error: "IllegalArgumentException", errorMessage: "无效会话", cause: "IP 不匹配" }) } } if(serverId !== request.serverId) { return await rep.code(401).send({ error: "IllegalArgumentException", errorMessage: "无效会话", cause: "服务器 ID 不匹配" }) } await rep.code(200).send(await getPlayerSerialization(player)) } } export const profile = { method: 'GET', url: '/sessionserver/session/minecraft/profile/:uuid', schema: { summary: "获取玩家 Profile", description: "详情请见 authlib-injector 文档。", tags: [ "Sessionserver" ], params: { "uuid": { "type": "string" }, unsigned: { anyOf: [ { "type": "boolean" }, { type: 'null' } ] }, }, response: { 200: PlayerSeriliazationSchema, 204: { type: "null" } } }, preHandler: getOverridePreHandler('/sessionserver/session/minecraft/profile/:uuid'), handler: getOverrideHandler('/sessionserver/session/minecraft/profile/:uuid') ?? async function (req, rep) { const { uuid } = req.params const player = await Player.findOne({ uuid: toSymboUUID(uuid) }) if (!player) { return await rep.code(204).send() } await rep.code(200).send(await getPlayerSerialization(player)) } } export const profiles = { method: 'POST', url: '/api/profiles/minecraft', schema: { summary: "获取玩家信息", description: "获取玩家信息。详情请见 authlib-injector 文档。", tags: [ "api" ], body: { type: 'array', items: { type: 'string' } }, response: { 200: { type: 'array', items: { type: 'object', properties: { id: { type: 'string' }, name: { type: 'string' } } } } } }, preHandler: getOverridePreHandler('/api/profiles/minecraft') ?? async function(req, rep) { if(req.body.length >= 3) { await rep.code(400).send({ error: "IllegalArgumentException", errorMessage: "请求内容过长, 最大请求玩家数: 2", cause: "请求内容过长, 最大请求玩家数: 2" }) } }, handler: getOverrideHandler('/api/profiles/minecraft') ?? async function (req, rep) { const { body } = req const profiles = await Player.find({ username: { $in: body } }) return await rep.code(200).send(profiles.map(profile => ({ id: uuidToNoSymboUUID(profile.uuid), name: profile.username }))) } }