koishi-plugin-autochat
Version:
201 lines (199 loc) • 9.39 kB
JavaScript
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
});