릴리스: v1.4.20 백엔드 topic 이름층 정리
This commit is contained in:
@@ -737,7 +737,7 @@ async function adminDeleteUser(id) {
|
||||
await query('DELETE FROM users WHERE id = ?', [id])
|
||||
}
|
||||
|
||||
async function listGames(currentUserId = '', options = {}) {
|
||||
async function listTopics(currentUserId = '', options = {}) {
|
||||
const includePrivate = !!options.includePrivate
|
||||
const rows = await query(
|
||||
`
|
||||
@@ -753,23 +753,23 @@ async function listGames(currentUserId = '', options = {}) {
|
||||
`,
|
||||
[FREEFORM_TOPIC_ID]
|
||||
)
|
||||
const games = rows.map(mapGameRow)
|
||||
if (!currentUserId) return games.map((game) => ({ ...game, isFavorited: false }))
|
||||
const topics = rows.map(mapGameRow)
|
||||
if (!currentUserId) return topics.map((topic) => ({ ...topic, isFavorited: false }))
|
||||
|
||||
const favoriteRows = await query('SELECT topic_id FROM favorite_topics WHERE user_id = ?', [currentUserId])
|
||||
const favoriteSet = new Set(favoriteRows.map((row) => row.topic_id))
|
||||
return games.map((game) => ({
|
||||
...game,
|
||||
isFavorited: favoriteSet.has(game.id),
|
||||
return topics.map((topic) => ({
|
||||
...topic,
|
||||
isFavorited: favoriteSet.has(topic.id),
|
||||
}))
|
||||
}
|
||||
|
||||
async function findGameById(id) {
|
||||
async function findTopicById(id) {
|
||||
const rows = await query('SELECT id, name, thumbnail_src, is_public, display_rank, created_at FROM topics WHERE id = ? LIMIT 1', [id])
|
||||
return mapGameRow(rows[0])
|
||||
}
|
||||
|
||||
async function listGameItems(gameId) {
|
||||
async function listTopicItems(topicId) {
|
||||
const rows = await query(
|
||||
`
|
||||
SELECT id, topic_id, src, label, display_order, created_at
|
||||
@@ -781,24 +781,24 @@ async function listGameItems(gameId) {
|
||||
created_at DESC,
|
||||
id DESC
|
||||
`,
|
||||
[gameId]
|
||||
[topicId]
|
||||
)
|
||||
return rows.map(mapGameItemRow)
|
||||
}
|
||||
|
||||
async function findGameItemById(itemId) {
|
||||
async function findTopicItemById(itemId) {
|
||||
const rows = await query('SELECT id, topic_id, src, label, display_order, created_at FROM topic_items WHERE id = ? LIMIT 1', [itemId])
|
||||
return mapGameItemRow(rows[0])
|
||||
}
|
||||
|
||||
async function getGameDetail(gameId) {
|
||||
const game = await findGameById(gameId)
|
||||
if (!game) return null
|
||||
const items = await listGameItems(gameId)
|
||||
return { game, items }
|
||||
async function getTopicDetail(topicId) {
|
||||
const topic = await findTopicById(topicId)
|
||||
if (!topic) return null
|
||||
const items = await listTopicItems(topicId)
|
||||
return { topic, game: topic, items }
|
||||
}
|
||||
|
||||
async function createGame({ id, name, isPublic = true }) {
|
||||
async function createTopic({ id, name, isPublic = true }) {
|
||||
await query('INSERT INTO topics (id, name, thumbnail_src, is_public, display_rank, created_at) VALUES (?, ?, ?, ?, ?, ?)', [
|
||||
id,
|
||||
name,
|
||||
@@ -807,17 +807,17 @@ async function createGame({ id, name, isPublic = true }) {
|
||||
null,
|
||||
now(),
|
||||
])
|
||||
return findGameById(id)
|
||||
return findTopicById(id)
|
||||
}
|
||||
|
||||
async function updateGameThumbnail(gameId, thumbnailSrc) {
|
||||
await query('UPDATE topics SET thumbnail_src = ? WHERE id = ?', [thumbnailSrc, gameId])
|
||||
return findGameById(gameId)
|
||||
async function updateTopicThumbnail(topicId, thumbnailSrc) {
|
||||
await query('UPDATE topics SET thumbnail_src = ? WHERE id = ?', [thumbnailSrc, topicId])
|
||||
return findTopicById(topicId)
|
||||
}
|
||||
|
||||
async function updateGameVisibility(gameId, isPublic) {
|
||||
await query('UPDATE topics SET is_public = ? WHERE id = ?', [isPublic ? 1 : 0, gameId])
|
||||
return findGameById(gameId)
|
||||
async function updateTopicVisibility(topicId, isPublic) {
|
||||
await query('UPDATE topics SET is_public = ? WHERE id = ?', [isPublic ? 1 : 0, topicId])
|
||||
return findTopicById(topicId)
|
||||
}
|
||||
|
||||
async function findImageAssetByHash(contentHash) {
|
||||
@@ -1347,14 +1347,15 @@ async function clearImageOptimizationJobs({ month } = {}) {
|
||||
const result = await query('DELETE FROM image_optimization_jobs')
|
||||
return Number(result.affectedRows || 0)
|
||||
}
|
||||
async function createGameItem({ id, gameId, src, label }) {
|
||||
async function createTopicItem({ id, topicId, gameId = topicId, src, label }) {
|
||||
const createdAt = now()
|
||||
const minOrderRows = await query('SELECT MIN(display_order) AS min_display_order FROM topic_items WHERE topic_id = ?', [gameId])
|
||||
const resolvedTopicId = topicId || gameId
|
||||
const minOrderRows = await query('SELECT MIN(display_order) AS min_display_order FROM topic_items WHERE topic_id = ?', [resolvedTopicId])
|
||||
const nextDisplayOrder =
|
||||
minOrderRows[0]?.min_display_order == null ? 0 : Number(minOrderRows[0].min_display_order) - 1
|
||||
await query('INSERT INTO topic_items (id, topic_id, src, label, display_order, created_at) VALUES (?, ?, ?, ?, ?, ?)', [
|
||||
id,
|
||||
gameId,
|
||||
resolvedTopicId,
|
||||
src,
|
||||
label,
|
||||
nextDisplayOrder,
|
||||
@@ -1364,25 +1365,25 @@ async function createGameItem({ id, gameId, src, label }) {
|
||||
return mapGameItemRow(rows[0])
|
||||
}
|
||||
|
||||
async function updateGameItemLabel(itemId, label) {
|
||||
async function updateTopicItemLabel(itemId, label) {
|
||||
await query('UPDATE topic_items SET label = ? WHERE id = ?', [label, itemId])
|
||||
const rows = await query('SELECT id, topic_id, src, label, display_order, created_at FROM topic_items WHERE id = ? LIMIT 1', [itemId])
|
||||
return mapGameItemRow(rows[0])
|
||||
}
|
||||
|
||||
async function updateGameItemDisplayOrder(gameId, itemIds) {
|
||||
async function updateTopicItemDisplayOrder(topicId, itemIds) {
|
||||
const normalizedIds = Array.from(new Set((itemIds || []).filter(Boolean)))
|
||||
const existingItems = await listGameItems(gameId)
|
||||
const existingItems = await listTopicItems(topicId)
|
||||
const existingIdSet = new Set(existingItems.map((item) => item.id))
|
||||
const orderedIds = normalizedIds.filter((id) => existingIdSet.has(id))
|
||||
const remainingIds = existingItems.map((item) => item.id).filter((id) => !orderedIds.includes(id))
|
||||
const finalIds = [...orderedIds, ...remainingIds]
|
||||
|
||||
await Promise.all(
|
||||
finalIds.map((itemId, index) => query('UPDATE topic_items SET display_order = ? WHERE id = ? AND topic_id = ?', [index + 1, itemId, gameId]))
|
||||
finalIds.map((itemId, index) => query('UPDATE topic_items SET display_order = ? WHERE id = ? AND topic_id = ?', [index + 1, itemId, topicId]))
|
||||
)
|
||||
|
||||
return listGameItems(gameId)
|
||||
return listTopicItems(topicId)
|
||||
}
|
||||
|
||||
async function updateCustomItemLabel(itemId, label) {
|
||||
@@ -1413,7 +1414,7 @@ async function updateImageAssetLabel(assetId, label) {
|
||||
return mapImageAssetRow(rows[0])
|
||||
}
|
||||
|
||||
async function countTierListsUsingGameItem(itemId) {
|
||||
async function countTierListsUsingTopicItem(itemId) {
|
||||
if (!itemId) return { totalCount: 0, publicCount: 0, privateCount: 0 }
|
||||
|
||||
const rows = await query(
|
||||
@@ -1441,16 +1442,16 @@ async function countTierListsUsingGameItem(itemId) {
|
||||
return { totalCount, publicCount, privateCount }
|
||||
}
|
||||
|
||||
async function deleteGameItem(itemId) {
|
||||
async function deleteTopicItem(itemId) {
|
||||
await query('DELETE FROM topic_items WHERE id = ?', [itemId])
|
||||
}
|
||||
|
||||
async function deleteGame(gameId) {
|
||||
await query('DELETE FROM topics WHERE id = ?', [gameId])
|
||||
async function deleteTopic(topicId) {
|
||||
await query('DELETE FROM topics WHERE id = ?', [topicId])
|
||||
}
|
||||
|
||||
async function updateGameDisplayOrder(gameIds) {
|
||||
const normalizedIds = Array.from(new Set((gameIds || []).filter((id) => id && id !== FREEFORM_TOPIC_ID))).slice(0, 50)
|
||||
async function updateTopicDisplayOrder(topicIds) {
|
||||
const normalizedIds = Array.from(new Set((topicIds || []).filter((id) => id && id !== FREEFORM_TOPIC_ID))).slice(0, 50)
|
||||
|
||||
await query('UPDATE topics SET display_rank = NULL WHERE id <> ?', [FREEFORM_TOPIC_ID])
|
||||
|
||||
@@ -1460,7 +1461,7 @@ async function updateGameDisplayOrder(gameIds) {
|
||||
)
|
||||
)
|
||||
|
||||
return listGames()
|
||||
return listTopics()
|
||||
}
|
||||
|
||||
async function createCustomItem({ id, ownerId, src, label }) {
|
||||
@@ -1475,6 +1476,22 @@ async function createCustomItem({ id, ownerId, src, label }) {
|
||||
return { id, ownerId, src, label, origin: 'custom', createdAt }
|
||||
}
|
||||
|
||||
const listGames = listTopics
|
||||
const findGameById = findTopicById
|
||||
const listGameItems = listTopicItems
|
||||
const findGameItemById = findTopicItemById
|
||||
const getGameDetail = getTopicDetail
|
||||
const createGame = createTopic
|
||||
const updateGameThumbnail = updateTopicThumbnail
|
||||
const updateGameVisibility = updateTopicVisibility
|
||||
const createGameItem = createTopicItem
|
||||
const updateGameItemLabel = updateTopicItemLabel
|
||||
const updateGameItemDisplayOrder = updateTopicItemDisplayOrder
|
||||
const countTierListsUsingGameItem = countTierListsUsingTopicItem
|
||||
const deleteGameItem = deleteTopicItem
|
||||
const deleteGame = deleteTopic
|
||||
const updateGameDisplayOrder = updateTopicDisplayOrder
|
||||
|
||||
async function syncOwnedCustomItemLabels({ ownerId, items }) {
|
||||
const customItems = Array.from(
|
||||
new Map(
|
||||
@@ -2511,14 +2528,19 @@ async function unfavoriteTierList({ userId, tierListId }) {
|
||||
await query('DELETE FROM favorite_tierlists WHERE user_id = ? AND tierlist_id = ?', [userId, tierListId])
|
||||
}
|
||||
|
||||
async function favoriteGame({ userId, gameId }) {
|
||||
await query('INSERT IGNORE INTO favorite_topics (user_id, topic_id, created_at) VALUES (?, ?, ?)', [userId, gameId, now()])
|
||||
async function favoriteTopic({ userId, topicId, gameId = topicId }) {
|
||||
const resolvedTopicId = topicId || gameId
|
||||
await query('INSERT IGNORE INTO favorite_topics (user_id, topic_id, created_at) VALUES (?, ?, ?)', [userId, resolvedTopicId, now()])
|
||||
}
|
||||
|
||||
async function unfavoriteGame({ userId, gameId }) {
|
||||
await query('DELETE FROM favorite_topics WHERE user_id = ? AND topic_id = ?', [userId, gameId])
|
||||
async function unfavoriteTopic({ userId, topicId, gameId = topicId }) {
|
||||
const resolvedTopicId = topicId || gameId
|
||||
await query('DELETE FROM favorite_topics WHERE user_id = ? AND topic_id = ?', [userId, resolvedTopicId])
|
||||
}
|
||||
|
||||
const favoriteGame = favoriteTopic
|
||||
const unfavoriteGame = unfavoriteTopic
|
||||
|
||||
module.exports = {
|
||||
DB_NAME,
|
||||
ensureData,
|
||||
@@ -2533,6 +2555,14 @@ module.exports = {
|
||||
adminUpdateUser,
|
||||
adminUpdateUserPassword,
|
||||
adminDeleteUser,
|
||||
listTopics,
|
||||
findTopicById,
|
||||
listTopicItems,
|
||||
findTopicItemById,
|
||||
getTopicDetail,
|
||||
createTopic,
|
||||
updateTopicThumbnail,
|
||||
updateTopicVisibility,
|
||||
listGames,
|
||||
findGameById,
|
||||
listGameItems,
|
||||
@@ -2557,6 +2587,13 @@ module.exports = {
|
||||
clearImageOptimizationJobs,
|
||||
getImageAssetStats,
|
||||
cleanupMissingUploadReferences,
|
||||
createTopicItem,
|
||||
updateTopicItemLabel,
|
||||
updateTopicItemDisplayOrder,
|
||||
countTierListsUsingTopicItem,
|
||||
deleteTopicItem,
|
||||
deleteTopic,
|
||||
updateTopicDisplayOrder,
|
||||
createGameItem,
|
||||
updateGameItemLabel,
|
||||
updateGameItemDisplayOrder,
|
||||
@@ -2577,6 +2614,8 @@ module.exports = {
|
||||
summarizeAdminTierLists,
|
||||
findTierListById,
|
||||
updateAdminTierListMeta,
|
||||
favoriteTopic,
|
||||
unfavoriteTopic,
|
||||
favoriteTierList,
|
||||
unfavoriteTierList,
|
||||
favoriteGame,
|
||||
|
||||
Reference in New Issue
Block a user