UNPKG

keli-sign

Version:

keli 的积分签到插件,提供积分签到功能,支持分群、自定义积分名等

320 lines (247 loc) 7.71 kB
const { parseUin, uploadFileToDir, Plugin, randomInt, segment } = require('keli') const path = require('node:path') const { name, version } = require('./package.json') const plugin = new Plugin(name, version) const config = { group: 0, unit: '积分', range: [3, 10], max: 6, enableGroups: [], cmds: { sign: '签到', rank: '积分排行', mine: '我的积分' } } const DefaultUserData = { coins: 0, days: 0, last: 0 } const data = {} const dataPath = path.join(plugin.dataDir, 'data.json') plugin.onMounted(() => { // 载入配置文件 plugin.saveConfig(Object.assign(config, plugin.loadConfig())) // 载入数据文件 plugin.saveConfig(Object.assign(data, plugin.loadConfig(dataPath)), dataPath) // 处理管理员命令 plugin.onAdminCmd('/sign', (e, params) => handleAdminCmd(e, params, plugin)) // 处理群员命令 plugin.onGroupMessage(e => { // 过滤未开启的群聊 if (!config.enableGroups.includes(e.group_id)) { return } // 处理各个积分命令 if (e.raw_message === config.cmds.sign) { handleSign(e, plugin) } else if (e.raw_message === config.cmds.rank) { handleRank(e, plugin) } else if (e.raw_message === config.cmds.mine) { handleMine(e, plugin) } }) }) function ensureData(gid, qq) { if (!data[gid]) { data[gid] = {} } if (qq && !data[gid][qq]) { data[gid][qq] = { ...DefaultUserData } } } function today() { const oneHourMs = 60 * 60 * 1000 return Math.floor((Date.now() + 8 * oneHourMs) / (24 * oneHourMs)) } async function handleAdminCmd(e, params, plugin) { const [cmd, v1, v2] = params const menus = [ `/sign on/off`, `/sign group <备份群号>`, `/sign inc/dec <qq> <${config.unit}数>`, `/sign stat`, `/sign backup` ] const cmds = ['on', 'off', 'group', 'inc', 'dec', 'backup', 'stat'] if (cmds.includes(cmd)) { if (cmd === 'group' && v1) { const group = Number(v1) if (group) { config.group = group plugin.saveConfig(config) return e.reply('备份群号设置成功', true) } } if (cmd === 'inc' && v1 && v2) { const qq = parseUin(v1) const count = Number(v2) if (qq && count > 0) { if (e.message_type !== 'group') { return e.reply('请在群聊中使用此命令', true) } else { ensureData(e.group_id, qq) data[e.group_id][qq].coins += count plugin.saveConfig(data, dataPath) return e.reply(`已给目标追加 ${count} ${config.unit}`, true) } } } if (cmd === 'dec' && v1 && v2) { const qq = parseUin(v1) const count = Number(v2) if (qq && count > 0) { if (e.message_type !== 'group') { return e.reply('请在群聊中使用此命令', true) } else { ensureData(e.group_id, qq) data[e.group_id][qq].coins -= count plugin.saveConfig(data, dataPath) return e.reply(`已扣除目标 ${count} ${config.unit}`, true) } } } if (cmd === 'backup') { if (!config.group) { return e.reply('请先设置数据备份群号', true) } else { const isOK = await uploadFileToDir.call( plugin.bot, config.group, dataPath, `[sign]-data.json` ) return e.reply(isOK ? '已上传到群文件' : '上传出现问题, 请查看日志', true) } } if (cmd === 'stat') { const signers = new Set() const todaySigners = new Set() const groups = new Set() const todayGroups = new Set() for (const [gid, ginfo] of Object.entries(data)) { for (const [qq, info] of Object.entries(ginfo)) { const user = `${gid}-${qq}` signers.add(user) if (!groups.has(gid)) { groups.add(gid) } const last = info.last if (last === today()) { todaySigners.add(user) if (!todayGroups.has(gid)) { todayGroups.add(gid) } } if (last !== today() && last !== today() - 1) { info.days = 0 } } } plugin.saveConfig(data, dataPath) return e.reply( [ `〓 签到统计 〓`, `今日签到人数: ${todaySigners.size}`, `总计签到人数: ${signers.size}`, `今日活跃群聊: ${todayGroups.size}`, `总计活跃群聊: ${groups.size}` ].join('\n') ) } if (cmd === 'on') { if (e.message_type !== 'group') { return e.reply('请在群聊中使用此命令', true) } const gid = e.group_id if (gid) { if (!config.enableGroups.includes(gid)) { config.enableGroups.push(gid) plugin.saveConfig(config) } return e.reply('本群签到功能开启成功', true) } } if (cmd === 'off') { if (e.message_type !== 'group') { return e.reply('请在群聊中使用此命令', true) } const gid = e.group_id if (gid) { if (config.enableGroups.includes(gid)) { const idx = config.enableGroups.findIndex(e => e === gid) config.enableGroups.splice(idx, 1) plugin.saveConfig(config) } return e.reply('本群签到功能已关闭', true) } } e.reply(menus.join('\n'), true) } else { return e.reply(menus.join('\n'), true) } } function handleSign(e, plugin) { ensureData(e.group_id, e.sender.user_id) const user = data[e.group_id][e.sender.user_id] if (user.last === today()) { e.reply('今天已经签到过了哦', true) } else { const [min, max] = config.range const todayCoin = randomInt(min, max) if (user.last === today() - 1) { user.days += 1 } else { user.days = 1 } user.last = today() user.coins += todayCoin plugin.saveConfig(data, dataPath) const days = `, 连签 ${user.days} 天` e.reply([segment.at(e.sender.user_id), ` 签到成功, 获得 ${todayCoin} ${config.unit}${days}`]) } } function handleRank(e, plugin) { ensureData(e.group_id) const ginfo = data[e.group_id] const glist = Object.entries(ginfo) glist.sort((a, b) => b[1].coins - a[1].coins) const map = ['〇', '①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩'] if (glist.length) { let msg = `〓 ${config.unit}排行 〓` let i = 1 for (const [qq, info] of glist.slice(0, config.max)) { const name = e.group.pickMember(Number(qq)).card if (info.last !== today() && info.last !== today() - 1) { info.days = 0 } const days = info.days ? `, 连签 ${info.days} 天` : '' msg += `\n${map[i++]} @${name}` msg += `\n拥有 ${info.coins} ${config.unit}${days}` } plugin.saveConfig(data, dataPath) e.reply(msg) } else { e.reply('本群还没有人签到', true) } } function handleMine(e, plugin) { ensureData(e.group_id, e.sender.user_id) const user = data[e.group_id][e.sender.user_id] if (user.coins) { const ginfo = data[e.group_id] const glist = Object.entries(ginfo) glist.sort((a, b) => b[1].coins - a[1].coins) const rank = glist.findIndex(([qq]) => Number(qq) === e.sender.user_id) + 1 const days = user.days ? `, 连签 ${user.days} 天` : '' e.reply([ segment.at(e.sender.user_id), ` 你拥有 ${user.coins} ${config.unit}${days}, 排名第 ${rank}` ]) } else { e.reply('你还没有在本群签到过', true) } } module.exports = { plugin }