UNPKG

koishi-plugin-autochat

Version:
201 lines (199 loc) 9.39 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; 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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Config: () => Config, apply: () => apply, inject: () => inject, name: () => name, reusable: () => reusable }); module.exports = __toCommonJS(src_exports); var import_koishi = require("koishi"); var import_koishi_plugin_chatluna = require("koishi-plugin-chatluna"); var import_chains = require("koishi-plugin-chatluna/chains"); var name = "autochat"; var reusable = true; var inject = ["chatluna", "database"]; var Config = import_koishi.Schema.object({ startTime: import_koishi.Schema.string().role("time").description("\u5B9A\u65F6\u4EFB\u52A1\u7684\u8D77\u59CB\u65F6\u95F4\uFF0C\u683C\u5F0F HH:mm\u3002").default("08:00"), endTime: import_koishi.Schema.string().role("time").description("\u5B9A\u65F6\u4EFB\u52A1\u7684\u7ED3\u675F\u65F6\u95F4\uFF0C\u683C\u5F0F HH:mm\u3002").default("22:00"), interval: import_koishi.Schema.number().description("\u5728\u6307\u5B9A\u65F6\u95F4\u6BB5\u5185\uFF0C\u6309\u56FA\u5B9A\u95F4\u9694\u53D1\u9001\u5BF9\u8BDD\u7684\u95F4\u9694\uFF08\u5C0F\u65F6\uFF09\u3002\u8BBE\u4E3A 0 \u53EF\u7981\u7528\u3002").default(4), randomSends: import_koishi.Schema.number().description("\u5728\u6307\u5B9A\u65F6\u95F4\u6BB5\u5185\uFF0C\u6BCF\u65E5\u989D\u5916\u968F\u673A\u53D1\u9001\u7684\u5BF9\u8BDD\u6B21\u6570\u3002").default(2), prompt: import_koishi.Schema.string().description("\u53D1\u9001\u7ED9 AI \u7684\u5185\u5BB9\u6A21\u677F\uFF0C`{time}` \u5C06\u88AB\u66FF\u6362\u4E3A\u5F53\u524D\u65F6\u95F4\u3002").default("\u73B0\u5728\u662F\u5317\u4EAC\u65F6\u95F4 {time}\uFF0C\u8BF7\u8BB0\u5F55\u4E0B\u6765\u3002"), channelId: import_koishi.Schema.string().description("\u8981\u628A\u56DE\u590D\u53D1\u9001\u5230\u7684\u9891\u9053 ID\uFF08QQ \u53F7\u6216\u7FA4\u53F7\uFF09").required(), channelType: import_koishi.Schema.union(["group", "private"]).description("\u53D1\u9001\u5230\u7FA4\u804A\u8FD8\u662F\u79C1\u804A").default("group"), botSelfId: import_koishi.Schema.string().description("\uFF08\u53EF\u9009\uFF09\u6307\u5B9A\u7528\u4E8E\u53D1\u9001\u6D88\u606F\u7684\u673A\u5668\u4EBA selfId\uFF0C\u5982\u679C\u7559\u7A7A\u5219\u4F7F\u7528\u7B2C\u4E00\u4E2A\u53EF\u7528\u673A\u5668\u4EBA\u3002").default("") }); function buildSession(ctx, bot, config, content) { const s = bot.session(); if (config.channelType === "group") { s.guildId = config.channelId; s.channelId = config.channelId; s.userId = "autochat"; } else { s.guildId = "0"; s.channelId = config.channelId; s.userId = config.channelId; } s.content = content; return s; } function apply(ctx, config) { let intervalTimeout = null; let randomTimeouts = []; let dailyResetTimeout = null; const loadedPlatforms = /* @__PURE__ */ new Set(); const events = { "llm-queue-waiting": async () => { }, "llm-used-token-count": async () => { } }; const cleanup = () => { if (intervalTimeout) clearTimeout(intervalTimeout); if (dailyResetTimeout) clearTimeout(dailyResetTimeout); randomTimeouts.forEach(clearTimeout); intervalTimeout = null; dailyResetTimeout = null; randomTimeouts = []; }; async function sendOnce(customPrompt, sessionSource) { const bot = ctx.bots.find((b) => !config.botSelfId || b.selfId === config.botSelfId); if (!bot) { ctx.logger.warn("[autochat] \u6CA1\u6709\u627E\u5230\u53EF\u7528\u7684 bot\uFF0C\u53D6\u6D88\u53D1\u9001\u3002"); return; } const timeStr = (/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }); const message = customPrompt && customPrompt.length > 0 ? customPrompt : config.prompt.replace("{time}", timeStr); const vSession = sessionSource ?? buildSession(ctx, bot, config, message); let room; if (config.channelType === "private") { room = await (0, import_chains.queryJoinedConversationRoom)(ctx, vSession); } else { room = await (0, import_chains.queryPublicConversationRoom)(ctx, vSession); } if (!room) { ctx.logger.warn("[autochat] \u627E\u4E0D\u5230\u5BF9\u5E94\u623F\u95F4\uFF0C\u5DF2\u8DF3\u8FC7\u3002"); return; } try { const platform = room.model.split("/")[0]; if (!loadedPlatforms.has(platform)) { ctx.logger.info(`[autochat] \u7B49\u5F85\u5E73\u53F0 ${platform} \u52A0\u8F7D...`); await ctx.chatluna.awaitLoadPlatform(platform, 6e4); loadedPlatforms.add(platform); ctx.logger.info(`[autochat] \u5E73\u53F0 ${platform} \u5DF2\u5C31\u7EEA\u3002`); } } catch { } try { ctx.logger.info(`[autochat] \u5411\u623F\u95F4\u53D1\u9001: ${message}`); const replyMsg = await ctx.chatluna.chat( vSession, room, { role: "user", content: message }, events, false ); const reply = replyMsg?.content ?? ""; if (!reply) return; ctx.logger.info(`[autochat] ChatLuna \u56DE\u590D: ${reply}`); const targetId = (config.channelType === "private" ? "private:" : "group:") + config.channelId; await bot.sendMessage(targetId, reply); } catch (err) { ctx.logger.error("[autochat] \u8C03\u7528 ChatLuna \u5931\u8D25", err); } } const scheduleAllTasks = () => { cleanup(); const [startHour, startMinute] = config.startTime.split(":").map(Number); const [endHour, endMinute] = config.endTime.split(":").map(Number); if ([startHour, startMinute, endHour, endMinute].some(isNaN)) { ctx.logger.warn("[autochat] \u65E0\u6548\u7684\u65F6\u95F4\u914D\u7F6E\uFF0C\u5B9A\u65F6\u4EFB\u52A1\u5DF2\u505C\u6B62\u3002"); return; } const now = /* @__PURE__ */ new Date(); const startTimeToday = new Date(now); startTimeToday.setHours(startHour, startMinute, 0, 0); const endTimeToday = new Date(now); endTimeToday.setHours(endHour, endMinute, 0, 0); if (startTimeToday.getTime() >= endTimeToday.getTime()) { ctx.logger.warn("[autochat] \u8D77\u59CB\u65F6\u95F4\u5FC5\u987B\u65E9\u4E8E\u7ED3\u675F\u65F6\u95F4\uFF0C\u5B9A\u65F6\u4EFB\u52A1\u5DF2\u505C\u6B62\u3002"); return; } if (config.interval > 0) { let nextSendTime = new Date(startTimeToday); while (nextSendTime.getTime() < now.getTime()) { nextSendTime.setHours(nextSendTime.getHours() + config.interval); } if (nextSendTime.getTime() > endTimeToday.getTime()) { nextSendTime = new Date(startTimeToday); nextSendTime.setDate(nextSendTime.getDate() + 1); } const delay = nextSendTime.getTime() - now.getTime(); ctx.logger.info(`[autochat] \u4E0B\u6B21\u56FA\u5B9A\u95F4\u9694\u53D1\u9001\u5DF2\u5B89\u6392\u5728 ${nextSendTime.toLocaleString("zh-CN")}`); intervalTimeout = setTimeout(() => { sendOnce(); scheduleAllTasks(); }, delay); } if (config.randomSends > 0) { const scheduleWindowStart = Math.max(now.getTime(), startTimeToday.getTime()); const scheduleWindowEnd = endTimeToday.getTime(); if (scheduleWindowStart < scheduleWindowEnd) { let scheduledCount = 0; for (let i = 0; i < config.randomSends; i++) { const randomTimestamp = scheduleWindowStart + Math.random() * (scheduleWindowEnd - scheduleWindowStart); const delay = randomTimestamp - now.getTime(); if (delay > 0) { const handle = setTimeout(() => sendOnce(), delay); randomTimeouts.push(handle); scheduledCount++; } } if (scheduledCount > 0) { ctx.logger.info(`[autochat] \u5DF2\u5B89\u6392 ${scheduledCount} \u6B21\u968F\u673A\u53D1\u9001\u3002`); } } } const nextMidnight = new Date(now); nextMidnight.setDate(nextMidnight.getDate() + 1); nextMidnight.setHours(0, 1, 0, 0); const delayToMidnight = nextMidnight.getTime() - now.getTime(); dailyResetTimeout = setTimeout(scheduleAllTasks, delayToMidnight); ctx.logger.info(`[autochat] \u5DF2\u5B89\u6392\u5728 ${nextMidnight.toLocaleString("zh-CN")} \u91CD\u65B0\u89C4\u5212\u6B21\u65E5\u4EFB\u52A1\u3002`); }; ctx.on("ready", scheduleAllTasks); ctx.on("dispose", cleanup); ctx.command("autochat [prompt:text]", "\u7ACB\u5373\u89E6\u53D1\u4E00\u6B21\u81EA\u52A8\u804A\u5929", { authority: 1 }).usage("\u793A\u4F8B: /autochat \u73B0\u5728\u51E0\u70B9\uFF1F").action(async ({ session }, prompt) => { await sendOnce(prompt, session); }); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, apply, inject, name, reusable });