릴리스: v0.1.17 티어표 삭제와 미사용 이미지 정리 추가
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
const fs = require('fs/promises')
|
||||
const path = require('path')
|
||||
const express = require('express')
|
||||
const multer = require('multer')
|
||||
@@ -13,6 +14,9 @@ const {
|
||||
deleteGameItem,
|
||||
deleteGame,
|
||||
listCustomItems,
|
||||
findUnusedCustomItems,
|
||||
findCustomItemsByIds,
|
||||
deleteCustomItems,
|
||||
listUsers,
|
||||
adminUpdateUser,
|
||||
adminUpdateUserPassword,
|
||||
@@ -89,6 +93,11 @@ router.get('/custom-items', requireAdmin, async (req, res) => {
|
||||
q: z.string().trim().max(120).optional().default(''),
|
||||
page: z.coerce.number().int().min(1).optional().default(1),
|
||||
limit: z.coerce.number().int().min(1).max(200).optional().default(50),
|
||||
orphanOnly: z
|
||||
.union([z.literal('true'), z.literal('false'), z.boolean()])
|
||||
.optional()
|
||||
.default('false')
|
||||
.transform((value) => value === true || value === 'true'),
|
||||
})
|
||||
const parsed = schema.safeParse(req.query)
|
||||
if (!parsed.success) return res.status(400).json({ error: 'bad_request' })
|
||||
@@ -97,10 +106,51 @@ router.get('/custom-items', requireAdmin, async (req, res) => {
|
||||
queryText: parsed.data.q,
|
||||
page: parsed.data.page,
|
||||
limit: parsed.data.limit,
|
||||
orphanOnly: parsed.data.orphanOnly,
|
||||
})
|
||||
res.json(result)
|
||||
})
|
||||
|
||||
async function removeCustomItemFiles(items) {
|
||||
await Promise.all(
|
||||
items.map(async (item) => {
|
||||
if (!item?.src || !item.src.startsWith('/uploads/custom/')) return
|
||||
const absolutePath = path.join(__dirname, '..', '..', item.src.replace(/^\//, ''))
|
||||
try {
|
||||
await fs.unlink(absolutePath)
|
||||
} catch (e) {
|
||||
if (e?.code !== 'ENOENT') throw e
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
if (!target) return res.status(404).json({ error: 'not_found' })
|
||||
if (target.usageCount > 0) return res.status(409).json({ error: 'item_in_use' })
|
||||
|
||||
const items = await findCustomItemsByIds([target.id])
|
||||
await deleteCustomItems([target.id])
|
||||
await removeCustomItemFiles(items)
|
||||
res.json({ ok: true })
|
||||
})
|
||||
|
||||
router.delete('/custom-items', requireAdmin, async (req, res) => {
|
||||
const schema = z.object({
|
||||
q: z.string().trim().max(120).optional().default(''),
|
||||
})
|
||||
const parsed = schema.safeParse(req.query)
|
||||
if (!parsed.success) return res.status(400).json({ error: 'bad_request' })
|
||||
|
||||
const items = await findUnusedCustomItems({ queryText: parsed.data.q })
|
||||
const ids = items.map((item) => item.id)
|
||||
await deleteCustomItems(ids)
|
||||
await removeCustomItemFiles(items)
|
||||
res.json({ ok: true, deletedCount: ids.length })
|
||||
})
|
||||
|
||||
router.get('/users', requireAdmin, async (req, res) => {
|
||||
const users = await listUsers()
|
||||
res.json({ users })
|
||||
|
||||
Reference in New Issue
Block a user