Add skin upload and texture management endpoints

Introduces endpoints and logic for uploading Minecraft skins via file or URL, storing textures, and managing player skins. Adds new repository and service methods for texture registration and retrieval, updates authorization handling, and uses process.cwd() for data paths. Also includes static serving of textures and rate limiting for skin uploads.
This commit is contained in:
2025-12-28 07:49:31 +01:00
parent 5dd1de1521
commit 1fe46a03fd
8 changed files with 252 additions and 19 deletions

View File

@@ -314,6 +314,46 @@ async function changeUsername(uuid, newName) {
}
}
async function createTexture(uuid, hash, type, url, alias) {
try {
const sql = `
INSERT INTO textures (uuid, hash, type, url, alias)
VALUES (?, ?, ?, ?, ?)
`
await database.query(sql, [uuid, hash, type, url, alias])
return true
} catch (error) {
if (error.code === 'ER_DUP_ENTRY') {
return false
}
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
throw new DefaultError(500, "Internal Server Error", "Database Error")
}
}
async function getTextureByUuid(textureUuid) {
try {
const sql = "SELECT hash FROM textures WHERE uuid = ?"
const rows = await database.query(sql, [textureUuid])
return rows[0] || null
} catch (error) {
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
throw new DefaultError(500, "Internal Server Error", "Database Error")
}
}
async function getTextureByHash(hash) {
try {
const sql = "SELECT uuid FROM textures WHERE hash = ?"
const rows = await database.query(sql, [hash])
return rows[0]
} catch (error) {
logger.log("Database Error: " + error.toString(), ["MariaDB", "red"])
throw new DefaultError(500, "Internal Server Error", "Database Error")
}
}
async function resetSkin(uuid, hash, variant) {
try {
const insertSql = `
@@ -345,17 +385,6 @@ async function hideCape(uuid) {
}
}
async function getTextureByUuid(textureUuid) {
try {
const sql = "SELECT hash FROM textures WHERE uuid = ?"
const rows = await database.query(sql, [textureUuid])
return rows[0] || null
} catch (error) {
logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"])
throw new DefaultError(500, "Internal Server Error", "Database Error")
}
}
async function showCape(uuid, hash) {
try {
const sql = `
@@ -611,7 +640,24 @@ async function getNameHistory(uuid) {
}
}
async function setSkin(uuid, hash, variant) {
const insertSql = `
INSERT INTO playersSkins (playerUuid, assetHash, variant, isSelected)
VALUES (?, ?, ?, 1)
ON DUPLICATE KEY UPDATE isSelected = 1, variant = ?
`
await database.query(insertSql, [uuid, hash, variant, variant])
const updateSql = `
UPDATE playersSkins
SET isSelected = 0
WHERE playerUuid = ? AND assetHash != ?
`
await database.query(updateSql, [uuid, hash])
return true
}
module.exports = {
setSkin,
banUser,
showCape,
hideCape,
@@ -619,6 +665,7 @@ module.exports = {
isBlocked,
unbanUser,
blockPlayer,
createTexture,
getPlayerBans,
getPlayerMeta,
unblockPlayer,
@@ -628,6 +675,7 @@ module.exports = {
getUsersByNames,
getPlayerActions,
getTextureByUuid,
getTextureByHash,
addProfileAction,
getLastNameChange,
getPlayerProperty,