릴리스: v0.1.41 커스텀 아이템 승격 연결 수정

This commit is contained in:
2026-03-26 18:49:31 +09:00
parent 6ddc82b1c7
commit b9aa714501
5 changed files with 66 additions and 0 deletions

View File

@@ -472,6 +472,28 @@ async function createCustomItem({ id, ownerId, src, label }) {
return { id, ownerId, src, label, origin: 'custom', createdAt }
}
async function findCustomItemById(id) {
const rows = await query(
`
SELECT id, owner_id, src, label, created_at
FROM custom_items
WHERE id = ?
LIMIT 1
`,
[id]
)
const row = rows[0]
if (!row) return null
return {
id: row.id,
ownerId: row.owner_id,
src: row.src,
label: row.label,
createdAt: Number(row.created_at),
}
}
async function getCustomItemUsageMap() {
const rows = await query('SELECT groups_json, pool_json FROM tierlists')
const usageMap = new Map()
@@ -778,6 +800,7 @@ module.exports = {
deleteGame,
updateGameDisplayOrder,
createCustomItem,
findCustomItemById,
listCustomItems,
findUnusedCustomItems,
listPublicTierLists,

View File

@@ -17,6 +17,7 @@ const {
deleteGame,
updateGameDisplayOrder,
listCustomItems,
findCustomItemById,
findUnusedCustomItems,
findCustomItemsByIds,
deleteCustomItems,
@@ -174,6 +175,23 @@ async function removeCustomItemFiles(items) {
)
}
async function promoteCustomItemToGameItem({ customItem, gameId }) {
const originalName = path.basename(customItem.src || '')
const nextFilename = buildUploadFilename({ originalname: originalName })
const sourcePath = path.join(__dirname, '..', '..', customItem.src.replace(/^\//, ''))
const targetRelativePath = path.join('uploads', 'games', nextFilename)
const targetPath = path.join(__dirname, '..', '..', targetRelativePath)
await fs.copyFile(sourcePath, targetPath)
return createGameItem({
id: nanoid(),
gameId,
src: `/${targetRelativePath.replace(/\\/g, '/')}`,
label: customItem.label,
})
}
router.delete('/custom-items/:itemId', requireAdmin, async (req, res) => {
const result = await listCustomItems({ page: 1, limit: 200, orphanOnly: false })
const target = result.items.find((item) => item.id === req.params.itemId)
@@ -186,6 +204,23 @@ router.delete('/custom-items/:itemId', requireAdmin, async (req, res) => {
res.json({ ok: true })
})
router.post('/custom-items/:itemId/promote', requireAdmin, async (req, res) => {
const schema = z.object({
gameId: z.string().min(1),
})
const parsed = schema.safeParse(req.body)
if (!parsed.success) return res.status(400).json({ error: 'bad_request' })
const game = await findGameById(parsed.data.gameId)
if (!game) return res.status(404).json({ error: 'game_not_found' })
const customItem = await findCustomItemById(req.params.itemId)
if (!customItem) return res.status(404).json({ error: 'not_found' })
const item = await promoteCustomItemToGameItem({ customItem, gameId: game.id })
res.json({ item })
})
router.delete('/custom-items', requireAdmin, async (req, res) => {
const schema = z.object({
q: z.string().trim().max(120).optional().default(''),