UNPKG

koishi-plugin-yutang-levelup

Version:

一个很好用的群发言等级插件

298 lines (295 loc) 11.3 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name2 in all) __defProp(target, name2, { get: all[name2], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Config: () => Config, SigninDatabase: () => SigninDatabase, apply: () => apply, inject: () => inject, name: () => name, usage: () => usage }); module.exports = __toCommonJS(src_exports); var import_koishi = require("koishi"); var fs = __toESM(require("fs/promises")); var path = __toESM(require("path")); var name = "yutang-levelup"; var inject = { required: ["database"], optional: ["puppeteer", "koishi-plugin-message-counter"] }; var usage = `# 💐⭐️群聊等级插件⭐️💐 ### 必须依赖 koishi-plugin-message-counter 插件,此插件才能正常使用 ## 反馈 - 如果你有任何问题或建议,请联系发反馈QQ群:738988912 - 链接跳转【羽棠娱乐&反馈群】:https://qm.qq.com/q/h4KbK4N6a4 `; var Config = import_koishi.Schema.object({ rankingDisplayCount: import_koishi.Schema.number().default(10).min(1).description("等级排行榜显示的人数") }); var SigninDatabase = class { static { __name(this, "SigninDatabase"); } async ensureDirExists(filePath) { const dir = path.dirname(filePath); try { await fs.mkdir(dir, { recursive: true }); } catch (error) { if (error.code !== "EEXIST") { throw error; } } } }; async function generateRankingMessage(ctx, config, channelName) { let rankingData; if (channelName) { rankingData = await ctx.database.select("levelup").where({ channelName }).orderBy("level", "desc").orderBy("totalPostCount", "desc").execute(); } else { rankingData = await ctx.database.select("levelup").orderBy("level", "desc").orderBy("totalPostCount", "desc").execute(); } if (rankingData.length === 0) { return channelName ? "本群暂无等级数据。" : "跨群暂无等级数据。"; } let rankingMessage = channelName ? "本群等级排行榜:\n" : "跨群等级排行榜:\n"; rankingData.slice(0, config.rankingDisplayCount).forEach((user, index) => { const rank = index + 1; rankingMessage += `${rank}. ${user.username} - 等级:${user.level},总发言次数:${user.totalPostCount} `; }); return rankingMessage; } __name(generateRankingMessage, "generateRankingMessage"); function apply(ctx, config) { ctx.model.extend( "levelup", // 表名(需与类型声明中的名称一致) { // 字段定义 id: "unsigned", // 无符号整数(自增主键) uid: "integer", // 整数类型(关联用户表 ID) userId: "string", // 字符串类型(用户平台 ID) createdAt: "timestamp", // 时间戳类型 updatedAt: "timestamp", // 新增更新时间字段 level: "integer", // 用户等级 totalPostCount: "integer", // 新增总发言次数字段 username: "string", // 新增用户名 channelName: "string", // 新增频道名称字段 channelId: "string" // 新增频道 ID 字段 }, { // 表配置 primary: "id", // 主键字段 autoInc: true // 自增配置(需要数据库支持) } ); function calculateLevel(count) { const basePosts = 10; const growthFactorBefore20 = 1.2; let requiredPosts = basePosts; let accumulatedPosts = 0; let level = 0; let fixedPostsAfter20; while (accumulatedPosts + requiredPosts <= count) { accumulatedPosts += requiredPosts; level++; if (level < 20) { requiredPosts *= growthFactorBefore20; } else { if (!fixedPostsAfter20) { fixedPostsAfter20 = requiredPosts; } requiredPosts = fixedPostsAfter20; } } return level; } __name(calculateLevel, "calculateLevel"); function calculateNextLevelRequirements(currentLevel) { const basePosts = 10; const growthFactorBefore20 = 1.2; let requiredPosts = basePosts; let accumulatedPosts = 0; for (let i = 0; i <= currentLevel; i++) { if (i < 20) { if (i > 0) requiredPosts *= growthFactorBefore20; accumulatedPosts += requiredPosts; } else { if (i === 20) { requiredPosts = requiredPosts; } accumulatedPosts += requiredPosts; } } return accumulatedPosts; } __name(calculateNextLevelRequirements, "calculateNextLevelRequirements"); ctx.command("查询等级").action(async ({ session }) => { try { const [bind] = await ctx.database.get("binding", { pid: session.userId }); if (!bind) return "未找到用户绑定信息"; const records = await ctx.database.get("message_counter_records", { userId: session.userId }); const totalMessages = records.reduce((sum, record) => sum + (record.totalPostCount || 0), 0); const username = records.length > 0 ? records[0].username : ""; const channelName = records.length > 0 ? records[0].channelName : ""; const channelId = session.channelId; const level = calculateLevel(totalMessages); const uid = bind.aid; const uidNumber = typeof uid === "string" ? parseInt(uid, 10) : uid; const [existingData] = await ctx.database.get("levelup", { uid: uidNumber }); if (!existingData) { await ctx.database.create("levelup", { uid: uidNumber, userId: session.userId, createdAt: /* @__PURE__ */ new Date(), level, totalPostCount: totalMessages, username, channelName, channelId }); const atUser = import_koishi.h.at(session.userId); return `${atUser} 已添加到数据库,当前等级为 ${level},总发言次数为 ${totalMessages}`; } else { const updateData = { level, updatedAt: /* @__PURE__ */ new Date(), totalPostCount: totalMessages, username, channelName, channelId }; await ctx.database.set("levelup", { uid: uidNumber }, updateData); const atUser = import_koishi.h.at(session.userId); return `${atUser} 修改数据库成功,当前等级为 ${level},总发言次数为 ${totalMessages}`; } } catch (error) { console.error("查询等级时出错:", error); return `查询等级出错,请稍后重试。错误信息: ${error.message}`; } }); ctx.command("level").action(async ({ session }) => { try { const [bind] = await ctx.database.get("binding", { pid: session.userId }); if (!bind) return "未找到用户绑定信息"; const records = await ctx.database.get("message_counter_records", { userId: session.userId }); const count = records.reduce((sum, record) => sum + (record.totalPostCount || 0), 0); const username = records.length > 0 ? records[0].username : ""; const channelName = records.length > 0 ? records[0].channelName : ""; const channelId = session.channelId; const level = calculateLevel(count); const nextLevelTotal = calculateNextLevelRequirements(level); const nextLevelRequiredPosts = Math.ceil(nextLevelTotal - count); const uid = bind.aid; const uidNumber = typeof uid === "string" ? parseInt(uid, 10) : uid; const [existingData] = await ctx.database.get("levelup", { uid: uidNumber }); if (!existingData) { await ctx.database.create("levelup", { uid: uidNumber, userId: session.userId, createdAt: /* @__PURE__ */ new Date(), level, totalPostCount: count, username, channelName, channelId }); } else { const updateData = { level, updatedAt: /* @__PURE__ */ new Date(), totalPostCount: count, username, channelName, channelId }; await ctx.database.set("levelup", { uid: uidNumber }, updateData); } const atUser = import_koishi.h.at(session.userId); return `${atUser} 当前等级为:${level},总发言次数为 ${count},升级到下一级还需 ${nextLevelRequiredPosts} 条消息。`; } catch (error) { console.error("查询等级时出错:", error); return `查询等级出错,请稍后重试。错误信息: ${error.message}`; } }); ctx.command("发言等级排行榜").action(async ({ session }) => { try { const currentChannelId = session.channelId; if (!currentChannelId) { return "无法获取当前群频道 ID,无法查询本群排行榜。"; } const rankingData = await ctx.database.select("levelup").where({ channelId: currentChannelId }).orderBy("level", "desc").orderBy("totalPostCount", "desc").execute(); if (rankingData.length === 0) { return "本群暂无等级数据。"; } let rankingMessage = "本群等级排行榜:\n"; rankingData.slice(0, config.rankingDisplayCount).forEach((user, index) => { const rank = index + 1; rankingMessage += `${rank}. ${user.username} - 等级:${user.level},总发言次数:${user.totalPostCount} `; }); return rankingMessage; } catch (error) { console.error("查询本群等级榜时出错:", error); return `查询本群等级榜出错,请稍后重试。错误信息: ${error.message}`; } }); ctx.command("跨群等级排行榜").alias("跨群发言等级排行榜").action(async () => { try { return await generateRankingMessage(ctx, config); } catch (error) { console.error("查询跨群等级榜时出错:", error); return `查询跨群等级榜出错,请稍后重试。错误信息: ${error.message}`; } }); } __name(apply, "apply"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, SigninDatabase, apply, inject, name, usage });