Skip to content

Commit

Permalink
perf: 可选是否缓存游戏中文名
Browse files Browse the repository at this point in the history
  • Loading branch information
XasYer committed Jan 9, 2025
1 parent 6112538 commit f385840
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 6 deletions.
1 change: 1 addition & 0 deletions components/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class Config {
* time: number,
* defaultPush: boolean,
* randomBot: boolean,
* cacheName: boolean,
* statusFilterGroup: boolean,
* blackBotList: string[],
* whiteBotList: string[],
Expand Down
4 changes: 4 additions & 0 deletions config/default_config/push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ defaultPush: true
# 是否随机Bot进行推送, 有多个Bot在同一群群时随机选择一个在线的Bot推送状态 (仅限TRSS)
randomBot: false

# 是否缓存游戏的中文名
# 需要单独请求一个接口获取游戏的中文名并缓存在数据库中
cacheName: true

# 群统计是否过滤掉黑名单群和白名单群
# 如果关闭则每次会获取忽略黑白名单的所有群 但是不会推送 仅统计
statusFilterGroup: true
Expand Down
71 changes: 71 additions & 0 deletions models/db/game.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { sequelize, DataTypes, Op } from './base.js'

/**
* @typedef {Object} GameColumns
* @property {string} appid appid
* @property {string} name 游戏名称
* @property {string} community 社区icon
* @property {string} header header图片
*/

const GameTable = sequelize.define('game', {
id: {
type: DataTypes.BIGINT,
primaryKey: true,
autoIncrement: true
},
appid: {
type: DataTypes.STRING,
allowNull: false
},
name: {
type: DataTypes.STRING,
allowNull: false
},
community: {
type: DataTypes.STRING,
defaultValue: false
},
header: {
type: DataTypes.STRING,
defaultValue: false
}
}, {
freezeTableName: true
})

await GameTable.sync()

/**
* 添加游戏信息
* @param {GameColumns[]} games
*/
export async function GameTableAddGame (games) {
if (!Array.isArray(games)) {
if (typeof games === 'object') {
games = Object.values(games)
} else {
games = [games]
}
}
return (await GameTable.bulkCreate(games.map(i => ({ ...i, appid: String(i.appid) })))).map(i => i.dataValues)
}

/**
* 查询游戏信息
* @param {string[]} appids
* @returns {Promise<{[appid: string]: GameColumns}>}
*/
export async function GameTableGetGameByAppids (appids) {
if (!Array.isArray(appids)) appids = [appids]
return await GameTable.findAll({
where: {
appid: {
[Op.in]: appids.map(String)
}
}
}).then(res => res.map(i => i.dataValues)).then(i => i.reduce((acc, cur) => {
acc[cur.appid] = cur
return acc
}, {}))
}
1 change: 1 addition & 0 deletions models/db/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './user.js'
export * from './push.js'
export * from './game.js'
export * from './stats.js'
export * from './token.js'
export * from './history.js'
7 changes: 7 additions & 0 deletions models/setting/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ export const cfgSchema = {
def: false,
desc: '有多个Bot在同一群群时随机选择一个在线的Bot推送状态 (仅限TRSS)'
},
cacheName: {
title: '缓存中文游戏名',
key: '缓存游戏名',
type: 'boolean',
def: true,
desc: '是否缓存游戏的中文名, 通过接口获取存储在数据库'
},
statusFilterGroup: {
title: '统计过滤黑白名单',
key: '统计过滤群',
Expand Down
82 changes: 76 additions & 6 deletions models/utils/steam.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,18 @@ export async function getUserSummaries (steamIds) {
throw err
})
if (data !== false) {
return data
if (Config.push.cacheName) {
const names = await getGameName(data.map(i => i.gameid))
return data.map(i => {
const info = names[i.gameid]
if (info) {
i.gameextrainfo = info.name
}
return i
})
} else {
return data
}
}
}
type = 2
Expand All @@ -205,15 +216,36 @@ export async function getUserSummaries (steamIds) {
throw err
})
if (data !== false) {
return data
if (Config.push.cacheName) {
const names = await getGameName(data.map(i => i.gameid))
return data.map(i => {
const info = names[i.gameid]
if (info) {
i.gameextrainfo = info.name
}
return i
})
} else {
return data
}
}
}
return await api.IPlayerService.GetPlayerLinkDetails(steamIds).then(async res => {
const appids = res.map(i => i.private_data.game_id).filter(Boolean)
const appInfo = appids.length ? await api.IStoreBrowseService.GetItems(appids, { include_assets: true }) : {}
const appInfo = {}
if (appids.length) {
if (Config.push.cacheName) {
Object.assign(appInfo, await getGameName(appids))
} else {
const info = await api.IStoreBrowseService.GetItems(appids, { include_assets: true })
Object.assign(appInfo, info)
}
}
return res.map(i => {
const avatarhash = Buffer.from(i.public_data.sha_digest_avatar, 'base64').toString('hex')
const gameid = i.private_data.game_id
const info = appInfo[gameid] || {}
const gameextrainfo = info.name
return {
steamid: i.public_data.steamid,
communityvisibilitystate: i.public_data.visibility_state,
Expand All @@ -226,9 +258,10 @@ export async function getUserSummaries (steamIds) {
personastate: i.private_data.persona_state ?? 0,
timecreated: i.private_data.time_created,
gameid,
gameextrainfo: appInfo[gameid]?.name,
lastlogoff: i.private_data.last_logoff_time,
community_icon: appInfo[gameid]?.assets?.community_icon
gameextrainfo,
lastlogoff: i.private_data.last_logoff_time
// TODO: 展示在好友列表的小图标
// community_icon: appInfo[gameid]?.assets?.community_icon
}
})
})
Expand All @@ -249,3 +282,40 @@ export function getStateColor (state) {
return '#8fbc8b'
}
}

/**
* 从数据库中获取游戏中文名
* @param {string[]} appids
* @returns {Promise<{[appid: string]: import('models/db/game').GameColumns}>}
*/
export async function getGameName (appids) {
appids = appids.filter(Boolean).map(String)
if (!appids.length) {
return {}
}
try {
// 先从数据库中找出对应的游戏名
const appInfo = await db.GameTableGetGameByAppids(appids)
const cacheAppids = Object.keys(appInfo)
// 找到没有被缓存的appid
const noCacheAppids = _.difference(appids, cacheAppids)
if (noCacheAppids.length) {
// 获取游戏名
const info = await api.IStoreBrowseService.GetItems(noCacheAppids, { include_assets: true })
const cache = noCacheAppids.map(i => info[i]
? ({
appid: i,
name: info[i].name,
community: info[i].assets?.community_icon,
header: info[i].assets?.header
})
: null).filter(Boolean)
// 缓存游戏名
await db.GameTableAddGame(cache)
Object.assign(appInfo, _.keyBy(cache, 'appid'))
}
return appInfo
} catch (error) {
return {}
}
}

0 comments on commit f385840

Please sign in to comment.