koishi-plugin-yutang-levelup
Version:
一个很好用的群发言等级插件
298 lines (295 loc) • 11.3 kB
JavaScript
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
});