koishi-plugin-satori-ai 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/broadcast.d.ts +24 -0
- package/lib/gameOneTouch.d.ts +2 -2
- package/lib/index.d.ts +2 -0
- package/lib/index.js +253 -118
- package/lib/mood.d.ts +1 -1
- package/lib/types.d.ts +2 -0
- package/lib/utils.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Context, Session } from 'koishi';
|
|
2
|
+
import { Sat } from './types';
|
|
3
|
+
export declare class BroadcastManager {
|
|
4
|
+
private ctx;
|
|
5
|
+
private config;
|
|
6
|
+
private idCounter;
|
|
7
|
+
private broadcastMessages;
|
|
8
|
+
constructor(ctx: Context, cfg: Sat.Config);
|
|
9
|
+
createBroadcast(message: string, img: boolean): Promise<string>;
|
|
10
|
+
deleteBroadcast(id: string): Promise<string>;
|
|
11
|
+
seedBroadcast(session: Session): Promise<void>;
|
|
12
|
+
getBroadcastList(): Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
export declare class broadcastMessage {
|
|
15
|
+
private ctx;
|
|
16
|
+
private config;
|
|
17
|
+
message: string;
|
|
18
|
+
private alreadySentChannels;
|
|
19
|
+
setTime: Date;
|
|
20
|
+
private img;
|
|
21
|
+
constructor(ctx: Context, cfg: Sat.Config, message: string, img: boolean);
|
|
22
|
+
sendMessage(session: Session): Promise<void>;
|
|
23
|
+
getAlreadySentChannels(): string;
|
|
24
|
+
}
|
package/lib/gameOneTouch.d.ts
CHANGED
|
@@ -30,8 +30,7 @@ declare class OneTouchSingleGame extends abstractGameSingleGame {
|
|
|
30
30
|
private buildMyTurnBonusMessage;
|
|
31
31
|
private processAiTurn;
|
|
32
32
|
private buildAiTurnBonusMessage;
|
|
33
|
-
private
|
|
34
|
-
private applyEffectToSelf;
|
|
33
|
+
private applyEffect;
|
|
35
34
|
private checkCombo;
|
|
36
35
|
private buildResultMessage;
|
|
37
36
|
private aiSearchEntrance;
|
|
@@ -42,6 +41,7 @@ declare class OneTouchSingleGame extends abstractGameSingleGame {
|
|
|
42
41
|
private evaluateState;
|
|
43
42
|
private generateChat;
|
|
44
43
|
private instuction;
|
|
44
|
+
private skillList;
|
|
45
45
|
}
|
|
46
46
|
export declare class OneTouchGame extends abstractGame<OneTouchSingleGame> {
|
|
47
47
|
constructor();
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Context, Session } from 'koishi';
|
|
2
2
|
import { Sat, User } from './types';
|
|
3
3
|
import Puppeteer from 'koishi-plugin-puppeteer';
|
|
4
|
+
import { BroadcastManager } from './broadcast';
|
|
4
5
|
export declare let puppeteer: Puppeteer | null;
|
|
5
6
|
export declare function refreshPuppeteer(ctx: Context): void;
|
|
6
7
|
export declare class SAT extends Sat {
|
|
@@ -11,6 +12,7 @@ export declare class SAT extends Sat {
|
|
|
11
12
|
private ChannelParallelCount;
|
|
12
13
|
private onlineUsers;
|
|
13
14
|
private moodManager;
|
|
15
|
+
broadcastManager: BroadcastManager;
|
|
14
16
|
private usersToWarn;
|
|
15
17
|
private game;
|
|
16
18
|
constructor(ctx: Context, config: Sat.Config);
|
package/lib/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
33
33
|
// src/locales/zh.yml
|
|
34
34
|
var require_zh = __commonJS({
|
|
35
35
|
"src/locales/zh.yml"(exports, module2) {
|
|
36
|
-
module2.exports = { commands: { sat: { description: "AI聊天", messages: { "no-prompt": "你好。使用说明可以看我的空间哦。", tooManyEnglishLetters: "请不要用这么多英文......", err: "寄!{0}", tooLong: "你的话太多了。", content_tooLong: "这个问题有点复杂,你还是去问别人吧。", "duplicate-dialogue": "这个刚刚说过了吧......", online: "思考中,请再等一会!", "no-response": "我不知道你在说什么……", update_level_succeed: "用户等级已更新为{0}", exceeds: "已经差不多够了吧?请明天再来。", usage: "今日次数{0}/{1}", hatMan: "叮!帽子先生保护了你的好感度,快说谢谢帽子先生吧!", rockBottom: "叮!谷底小石保护了你的好感度,快说谢谢谷底小石吧!", not_good_mood: "别得寸进尺……(好感↓)", pocket_money: "心情不错,给你点零花钱吧~(获得了{0}p点)", warning: "<at id={0}/>", block1: "我讨厌你!", block2: "我讨厌你们!" } }, "sat.clear": { description: "清空当前频道会话", messages: { clean: "已清空当前会话。", Allclean: "已清空所有会话。" } }, "sat.common_sense": { description: "添加常识", messages: { "no-prompt": "你想让我知道什么?", succeed: "我知道了,{0}" } } } };
|
|
36
|
+
module2.exports = { commands: { sat: { description: "AI聊天", messages: { "no-prompt": "你好。使用说明可以看我的空间哦。", tooManyEnglishLetters: "请不要用这么多英文......", err: "寄!{0}", tooLong: "你的话太多了。", content_tooLong: "这个问题有点复杂,你还是去问别人吧。", "duplicate-dialogue": "这个刚刚说过了吧......", online: "思考中,请再等一会!", "no-response": "我不知道你在说什么……", update_level_succeed: "用户等级已更新为{0}", exceeds: "已经差不多够了吧?请明天再来。", usage: "今日次数{0}/{1}", hatMan: "叮!帽子先生保护了你的好感度,快说谢谢帽子先生吧!", rockBottom: "叮!谷底小石保护了你的好感度,快说谢谢谷底小石吧!", not_good_mood: "别得寸进尺……(好感↓)", pocket_money: "心情不错,给你点零花钱吧~(获得了{0}p点)", warning: "<at id={0}/>", block1: "我讨厌你!", block2: "我讨厌你们!" } }, "sat.clear": { description: "清空当前频道会话", messages: { clean: "已清空当前会话。", Allclean: "已清空所有会话。" } }, "sat.common_sense": { description: "添加常识", messages: { "no-prompt": "你想让我知道什么?", succeed: "我知道了,{0}" } }, "sat.broadcast": { description: "广播一条消息,在每个生效群收到首条消息时会推送", options: { delete: "删除一条广播,参数为广播的ID", list: "查看当前所有广播", img: "使用puppeteer图片化广播消息" } } } };
|
|
37
37
|
}
|
|
38
38
|
});
|
|
39
39
|
|
|
@@ -46,7 +46,7 @@ __export(src_exports, {
|
|
|
46
46
|
refreshPuppeteer: () => refreshPuppeteer
|
|
47
47
|
});
|
|
48
48
|
module.exports = __toCommonJS(src_exports);
|
|
49
|
-
var
|
|
49
|
+
var import_koishi14 = require("koishi");
|
|
50
50
|
var path7 = __toESM(require("path"));
|
|
51
51
|
|
|
52
52
|
// src/api.ts
|
|
@@ -255,7 +255,7 @@ function processPrompt(prompt) {
|
|
|
255
255
|
prompt = prompt.replace(/\*\*/g, "");
|
|
256
256
|
if (!prompt)
|
|
257
257
|
return "**";
|
|
258
|
-
return prompt;
|
|
258
|
+
return prompt.trim();
|
|
259
259
|
}
|
|
260
260
|
__name(processPrompt, "processPrompt");
|
|
261
261
|
function filterResponse(prompt, words) {
|
|
@@ -607,7 +607,7 @@ var MemoryManager = class {
|
|
|
607
607
|
return acc;
|
|
608
608
|
}, []);
|
|
609
609
|
const filtered = sentences.filter((sentence) => !filterWords.some((word) => sentence.includes(word))).join("");
|
|
610
|
-
const result = filtered.replace(/([
|
|
610
|
+
const result = filtered.replace(/([,、…])\1+/g, "$1").replace(/^[,。!?;,.!?]+/, "").trim();
|
|
611
611
|
return result || content;
|
|
612
612
|
}
|
|
613
613
|
// 更新短期记忆
|
|
@@ -1028,6 +1028,7 @@ function createMiddleware(ctx, sat, config) {
|
|
|
1028
1028
|
return async (session, next) => {
|
|
1029
1029
|
if (config.enable_favorability && config.enable_warning && session.channelId === config.warning_group)
|
|
1030
1030
|
sat.getWarningList(session);
|
|
1031
|
+
await sat.broadcastManager.seedBroadcast(session);
|
|
1031
1032
|
if (!isSpecialMessage(session))
|
|
1032
1033
|
await sat.handleChannelMemoryManager(session);
|
|
1033
1034
|
if (config.private && isPrivateSession(session)) {
|
|
@@ -1217,6 +1218,10 @@ var Sat = class extends import_koishi5.Service {
|
|
|
1217
1218
|
max_pocket_money: import_koishi5.Schema.number().default(400).description("随机p点最大值"),
|
|
1218
1219
|
pocket_money_cost: import_koishi5.Schema.number().default(2).description("消耗心情换p点的心情值")
|
|
1219
1220
|
}).description("好感度拓展:心情设置(需要开启好感度模块才能生效)"),
|
|
1221
|
+
import_koishi5.Schema.object({
|
|
1222
|
+
Broadcast_block_channel: import_koishi5.Schema.array(String).description("不提供广播的频道id"),
|
|
1223
|
+
waiting_time: import_koishi5.Schema.number().default(1440).description("广播在缓存中等待的最大时间(分钟)(超过时间后没有触发会不再推送)")
|
|
1224
|
+
}).description("广播设置(发出后在每个生效群收到首条消息时会推送)"),
|
|
1220
1225
|
import_koishi5.Schema.object({
|
|
1221
1226
|
enable_game: import_koishi5.Schema.boolean().default(false).description("是否开启游戏模块"),
|
|
1222
1227
|
game_block_channel: import_koishi5.Schema.array(String).description("不提供游戏的频道id"),
|
|
@@ -1292,12 +1297,11 @@ var UserPortraitManager = class {
|
|
|
1292
1297
|
return [{
|
|
1293
1298
|
role: "user",
|
|
1294
1299
|
content: `你是一个角色扮演智能体工作流中的一环,请根据以下信息更新用户画像。需包括:
|
|
1295
|
-
1.
|
|
1300
|
+
1. 基本信息(性别、年龄、生日等,不要遗漏或改动已有的信息)
|
|
1296
1301
|
2. 生活习惯(作息等)
|
|
1297
1302
|
3. 反感点(如有)
|
|
1298
1303
|
4. 对AI的期望(从对话历史中推断)
|
|
1299
1304
|
5. 用户希望记住的信息(如有)
|
|
1300
|
-
6. 需要短期记忆的信息(如有)
|
|
1301
1305
|
|
|
1302
1306
|
用户名:${user.usersname}
|
|
1303
1307
|
你与用户的关系:${level}
|
|
@@ -1310,9 +1314,7 @@ ${history}
|
|
|
1310
1314
|
注意事项:
|
|
1311
1315
|
·用户一定是人类,其他情况是角色扮演
|
|
1312
1316
|
·根据发言修正历史画像内容,但是历史画像中与发言无关的部分必须保留
|
|
1313
|
-
·除非用户要求,否则不要删除基本信息中的内容
|
|
1314
1317
|
·尤其注意用户说“记住”的部分,可能是用户希望记录的信息
|
|
1315
|
-
·历史画像中的需要短期记忆的信息不需要保留,只需要删除旧的添加新的
|
|
1316
1318
|
·因为在角色扮演中,用户可能会说出不符合事实的信息,需要根据事实推断,避免盲目相信或主观臆测
|
|
1317
1319
|
·使用尽可能简洁的表达
|
|
1318
1320
|
·保留不确定性的表述(如"可能"、"似乎"、"用户自称")
|
|
@@ -1448,7 +1450,6 @@ var MoodManager = class {
|
|
|
1448
1450
|
const userId = user.userid;
|
|
1449
1451
|
if (!this.moodMap.has(userId))
|
|
1450
1452
|
this.initUser(userId);
|
|
1451
|
-
await this.checkDailyReset(userId);
|
|
1452
1453
|
let effect = this.config.value_of_input_mood;
|
|
1453
1454
|
switch (favorabilityLevel) {
|
|
1454
1455
|
case "厌恶":
|
|
@@ -1484,7 +1485,6 @@ var MoodManager = class {
|
|
|
1484
1485
|
const userId = user.userid;
|
|
1485
1486
|
if (!this.moodMap.has(userId))
|
|
1486
1487
|
this.initUser(userId);
|
|
1487
|
-
await this.checkDailyReset(userId);
|
|
1488
1488
|
let effect = this.config.value_of_output_mood;
|
|
1489
1489
|
switch (favorabilityLevel) {
|
|
1490
1490
|
case "厌恶":
|
|
@@ -1514,7 +1514,7 @@ var MoodManager = class {
|
|
|
1514
1514
|
return;
|
|
1515
1515
|
}
|
|
1516
1516
|
// 应用心情变化
|
|
1517
|
-
applyMoodChange(user, delta) {
|
|
1517
|
+
async applyMoodChange(user, delta) {
|
|
1518
1518
|
if (!this.config.enable_mood)
|
|
1519
1519
|
return;
|
|
1520
1520
|
const userId = user.userid;
|
|
@@ -1528,6 +1528,7 @@ var MoodManager = class {
|
|
|
1528
1528
|
mood: newMood,
|
|
1529
1529
|
lastUpdate: Date.now()
|
|
1530
1530
|
});
|
|
1531
|
+
await this.checkDailyReset(userId);
|
|
1531
1532
|
return;
|
|
1532
1533
|
}
|
|
1533
1534
|
// 获取心情等级
|
|
@@ -2171,7 +2172,7 @@ var import_koishi11 = require("koishi");
|
|
|
2171
2172
|
var logger10 = new import_koishi11.Logger("satori-game-onetouch");
|
|
2172
2173
|
var SKILL_MAP = {
|
|
2173
2174
|
// 基础技能
|
|
2174
|
-
"-1": {
|
|
2175
|
+
"-1": {},
|
|
2175
2176
|
"1": { pierceDamage: 1, bleed: 3, name: "锥刺" },
|
|
2176
2177
|
//特性:流血
|
|
2177
2178
|
"2": { pierceDamage: 1, stun: true, name: "点穴" },
|
|
@@ -2203,13 +2204,13 @@ var SKILL_MAP = {
|
|
|
2203
2204
|
"4+6": { shield: 2, heal: 5, selfbleed: -3, name: "固守" },
|
|
2204
2205
|
"8+8": { damage: 13, damageTimes: 2, selfStun: true, name: "双持" },
|
|
2205
2206
|
"1+2": { pierceDamage: 3, vulnerablility: 3, stun: true, name: "弱点刺击" },
|
|
2206
|
-
"2+8": { damage:
|
|
2207
|
+
"2+8": { damage: 12, stun: true, selfStun: true, addLeft: 1, addRight: 9, name: "点射" },
|
|
2207
2208
|
"3+4": { name: "防御反击", shield: 1, counterAttack: 15 },
|
|
2208
2209
|
"7+7": { pierceDamage: 7, destroyShield: 5, name: "穿龙枪" },
|
|
2209
2210
|
"7+8": { pierceDamage: 13, destroyShield: 3, selfStun: true, name: "穿甲弹" },
|
|
2210
2211
|
"2+6": { damage: 5, heal: 6, selfbleed: -1, selfstrengthChange: 1, stun: true, name: "点辰" },
|
|
2211
2212
|
"3+7": { name: "混沌", counterAttack: 7, destroyShield: 2, addLeft: 9, addRight: 1 },
|
|
2212
|
-
"0+9": { name: "将大局逆转吧", revwersalOfStrength: true },
|
|
2213
|
+
"0+9": { name: "将大局逆转吧", revwersalOfStrength: true, selfstrengthChange: 2, strengthChange: -1 },
|
|
2213
2214
|
"0+0": { name: "华丽收场", bleed: 5, selfstrengthChange: -99, magnificentEnd: true }
|
|
2214
2215
|
};
|
|
2215
2216
|
var OneTouchSingleGame = class extends abstractGameSingleGame {
|
|
@@ -2266,17 +2267,18 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
|
|
|
2266
2267
|
例如"左 右"表示用你的左手触碰对方的右手
|
|
2267
2268
|
注:
|
|
2268
2269
|
发送"游戏规则"查看游戏规则
|
|
2270
|
+
发送"技能列表"查看技能列表
|
|
2269
2271
|
发送"结束游戏"退出游戏`);
|
|
2270
2272
|
}
|
|
2271
2273
|
// 结束游戏,返回结果
|
|
2272
2274
|
endGame = async () => {
|
|
2273
2275
|
if (this.winningFlag === 4 /* pending */ || this.winningFlag === 2 /* lose */) {
|
|
2274
2276
|
this.bonus = Math.abs(Math.floor(this.level * 0.2 * this.bonus));
|
|
2275
|
-
this.bonus -= Math.floor(this.level * this.level * (Math.random() * 2 + 2) +
|
|
2277
|
+
this.bonus -= Math.floor(this.level * this.level * (Math.random() * 2 + 2) + 50);
|
|
2276
2278
|
this.bonus = Math.min(this.bonus, 0);
|
|
2277
2279
|
}
|
|
2278
2280
|
if (this.winningFlag === 1 /* win */) {
|
|
2279
|
-
this.bonus = Math.floor(this.level * this.bonus * 0.
|
|
2281
|
+
this.bonus = Math.floor(this.level * this.bonus * 0.1 * (Math.random() * 1 + 1));
|
|
2280
2282
|
}
|
|
2281
2283
|
const finalBonus = this.bonus;
|
|
2282
2284
|
super.endGame();
|
|
@@ -2287,7 +2289,7 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
|
|
|
2287
2289
|
left: this.player.left,
|
|
2288
2290
|
right: this.player.right,
|
|
2289
2291
|
hp: this.baseHP + level * this.playerLevelHP,
|
|
2290
|
-
shield: Math.round(level / 2),
|
|
2292
|
+
shield: Math.round(6 - level / 2),
|
|
2291
2293
|
strength: 0,
|
|
2292
2294
|
bleed: 0,
|
|
2293
2295
|
counterAttack: 0,
|
|
@@ -2309,6 +2311,8 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
|
|
|
2309
2311
|
async processInput(input) {
|
|
2310
2312
|
if (input === "游戏规则")
|
|
2311
2313
|
return await wrapInHTML2(this.instuction);
|
|
2314
|
+
if (input === "技能列表")
|
|
2315
|
+
return await wrapInHTML2(this.skillList);
|
|
2312
2316
|
if (this.turnCount === 0)
|
|
2313
2317
|
this.initState(this.level);
|
|
2314
2318
|
this.turnCount++;
|
|
@@ -2369,11 +2373,11 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
|
|
|
2369
2373
|
judgeEnd() {
|
|
2370
2374
|
if (this.ai.hp <= 0) {
|
|
2371
2375
|
this.winningFlag = 1 /* win */;
|
|
2372
|
-
return
|
|
2376
|
+
return `你赢了!发送"结束游戏"退出`;
|
|
2373
2377
|
}
|
|
2374
2378
|
if (this.player.hp <= 0) {
|
|
2375
2379
|
this.winningFlag = 2 /* lose */;
|
|
2376
|
-
return
|
|
2380
|
+
return `你输了!发送"结束游戏"退出`;
|
|
2377
2381
|
}
|
|
2378
2382
|
}
|
|
2379
2383
|
processPlayerTurn(handA, handB) {
|
|
@@ -2382,8 +2386,8 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
|
|
|
2382
2386
|
}
|
|
2383
2387
|
if (this.player.status === 1 /* Stunned */) {
|
|
2384
2388
|
this.player.status = 2 /* lastStunned */;
|
|
2385
|
-
this.
|
|
2386
|
-
return "你被眩晕,跳过回合";
|
|
2389
|
+
this.applyEffect(this.player, this.ai, SKILL_MAP["-1"], false);
|
|
2390
|
+
return "你被眩晕,跳过回合" + this.buildResultMessage(SKILL_MAP["-1"], false, this.player, this.ai);
|
|
2387
2391
|
}
|
|
2388
2392
|
const sum = (handA + handB) % 10;
|
|
2389
2393
|
this.player[handA === this.player.left ? "left" : "right"] = sum;
|
|
@@ -2398,10 +2402,7 @@ var OneTouchSingleGame = class extends abstractGameSingleGame {
|
|
|
2398
2402
|
this.comboCombos = 0;
|
|
2399
2403
|
}
|
|
2400
2404
|
const bonusMessage = this.buildMyTurnBonusMessage(effect, isCombo);
|
|
2401
|
-
|
|
2402
|
-
const aiState = this.ai;
|
|
2403
|
-
this.ai = this.applyEffectToEnemy(playerState, aiState, effect, !!combo);
|
|
2404
|
-
this.player = this.applyEffectToSelf(aiState, playerState, effect);
|
|
2405
|
+
this.applyEffect(this.player, this.ai, effect, !!combo);
|
|
2405
2406
|
return this.buildResultMessage(effect, isCombo, this.player, this.ai) + (bonusMessage ? `
|
|
2406
2407
|
|
|
2407
2408
|
${bonusMessage}` : "");
|
|
@@ -2440,7 +2441,7 @@ ${bonusMessage}` : "");
|
|
|
2440
2441
|
bonusMessage += `流血打击!获得${effectBonus}点分数!
|
|
2441
2442
|
`;
|
|
2442
2443
|
}
|
|
2443
|
-
if ((effect.shield || 0) + this.player.shield >= 5) {
|
|
2444
|
+
if (effect.shield && (effect.shield || 0) + this.player.shield >= 5) {
|
|
2444
2445
|
const effectBonus = Math.round(((effect.shield || 0) + this.player.shield) * 2);
|
|
2445
2446
|
this.singleBonus += effectBonus;
|
|
2446
2447
|
bonusMessage += `强效护盾!获得${effectBonus}点分数!
|
|
@@ -2477,7 +2478,7 @@ ${bonusMessage}` : "");
|
|
|
2477
2478
|
`;
|
|
2478
2479
|
}
|
|
2479
2480
|
if (effect.revwersalOfStrength && this.player.strength <= this.ai.strength - 5) {
|
|
2480
|
-
const effectBonus = Math.
|
|
2481
|
+
const effectBonus = Math.min((this.ai.strength - this.player.strength) * 3, 100);
|
|
2481
2482
|
this.singleBonus += effectBonus;
|
|
2482
2483
|
bonusMessage += `逆转大局!获得${effectBonus}点分数!
|
|
2483
2484
|
`;
|
|
@@ -2495,7 +2496,7 @@ ${bonusMessage}` : "");
|
|
|
2495
2496
|
bonusMessage += `压倒性的优势!获得${effectBonus}点分数!本回合分数*2!
|
|
2496
2497
|
`;
|
|
2497
2498
|
}
|
|
2498
|
-
if (effect.magnificentEnd && this.ai.bleed >
|
|
2499
|
+
if (effect.magnificentEnd && this.ai.bleed > 1) {
|
|
2499
2500
|
const effectBonus = Math.round(this.ai.bleed * 1.5);
|
|
2500
2501
|
this.singleBonusMultiplier *= effectBonus;
|
|
2501
2502
|
this.bonus *= 2;
|
|
@@ -2518,8 +2519,8 @@ ${bonusMessage}` : "");
|
|
|
2518
2519
|
}
|
|
2519
2520
|
if (this.ai.status === 1 /* Stunned */) {
|
|
2520
2521
|
this.ai.status = 2 /* lastStunned */;
|
|
2521
|
-
this.
|
|
2522
|
-
return "被眩晕,跳过回合,本回合分数奖励继承到下一回合";
|
|
2522
|
+
this.applyEffect(this.ai, this.player, SKILL_MAP["-1"], false);
|
|
2523
|
+
return "被眩晕,跳过回合,本回合分数奖励继承到下一回合" + this.buildResultMessage(SKILL_MAP["-1"], false, this.ai, this.player);
|
|
2523
2524
|
}
|
|
2524
2525
|
const sum = (handA + handB) % 10;
|
|
2525
2526
|
this.ai[handA === this.ai.left ? "left" : "right"] = sum;
|
|
@@ -2530,11 +2531,8 @@ ${bonusMessage}` : "");
|
|
|
2530
2531
|
isCombo = true;
|
|
2531
2532
|
effect = { ...combo };
|
|
2532
2533
|
}
|
|
2533
|
-
const playerState = this.player;
|
|
2534
|
-
const aiState = this.ai;
|
|
2535
2534
|
const bonusMessage = this.buildAiTurnBonusMessage(effect);
|
|
2536
|
-
this.
|
|
2537
|
-
this.ai = this.applyEffectToSelf(playerState, aiState, effect);
|
|
2535
|
+
this.applyEffect(this.ai, this.player, effect, !!combo);
|
|
2538
2536
|
return handA + "碰" + handB + "," + this.buildResultMessage(effect, isCombo, this.ai, this.player) + (bonusMessage ? `
|
|
2539
2537
|
|
|
2540
2538
|
${bonusMessage}` : "");
|
|
@@ -2587,50 +2585,31 @@ ${bonusMessage}` : "");
|
|
|
2587
2585
|
// destroyShield?: number // 破坏护盾
|
|
2588
2586
|
// weakStun?: boolean // 弱眩晕
|
|
2589
2587
|
// strengthChange?: number // 力量变化
|
|
2590
|
-
|
|
2588
|
+
// heal?: number // 治疗
|
|
2589
|
+
// shield?: number // 护盾
|
|
2590
|
+
// selfbleed?: number // 自身流血
|
|
2591
|
+
// selfStun?: boolean // 自身眩晕
|
|
2592
|
+
// selfstrengthChange?: number // 自身力量变化
|
|
2593
|
+
applyEffect(self, enemy, effect, isCombo) {
|
|
2594
|
+
if (effect.revwersalOfStrength) {
|
|
2595
|
+
const temp = self.strength;
|
|
2596
|
+
self.strength = enemy.strength;
|
|
2597
|
+
enemy.strength = temp;
|
|
2598
|
+
}
|
|
2591
2599
|
if (effect.pierceDamage)
|
|
2592
|
-
|
|
2600
|
+
enemy.hp -= Math.max(effect.pierceDamage + (self.strength || 0), 0);
|
|
2593
2601
|
if (effect.destroyShield)
|
|
2594
|
-
|
|
2602
|
+
enemy.shield = Math.max(0, enemy.shield - effect.destroyShield);
|
|
2595
2603
|
if (effect.bleed)
|
|
2596
|
-
|
|
2604
|
+
enemy.bleed += effect.bleed;
|
|
2597
2605
|
if (effect.strengthChange)
|
|
2598
|
-
|
|
2606
|
+
enemy.strength = enemy.strength + effect.strengthChange;
|
|
2599
2607
|
if (effect.addLeft)
|
|
2600
|
-
|
|
2608
|
+
enemy.left = (enemy.left + effect.addLeft) % 10;
|
|
2601
2609
|
if (effect.addRight)
|
|
2602
|
-
|
|
2610
|
+
enemy.right = (enemy.right + effect.addRight) % 10;
|
|
2603
2611
|
if (effect.vulnerablility)
|
|
2604
|
-
|
|
2605
|
-
if (effect.damage) {
|
|
2606
|
-
effect.damageTimes = effect.damageTimes || 1;
|
|
2607
|
-
for (let i = 0; i < effect.damageTimes; i++) {
|
|
2608
|
-
const blocked = target.shield > 0;
|
|
2609
|
-
target.shield = Math.max(0, target.shield - (isCombo ? 2 : 1));
|
|
2610
|
-
if (!blocked) {
|
|
2611
|
-
target.hp -= Math.round(Math.max(0, effect.damage + (self.strength || 0)) * (target.vulnerablility ? 1.5 : 1));
|
|
2612
|
-
if (effect.weakStun && target.status !== 2 /* lastStunned */) {
|
|
2613
|
-
target.status = 1 /* Stunned */;
|
|
2614
|
-
}
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
if (effect.revwersalOfStrength)
|
|
2619
|
-
target.strength = self.strength;
|
|
2620
|
-
if (effect.magnificentEnd) {
|
|
2621
|
-
target.hp -= target.bleed * (target.bleed + 1) / 2;
|
|
2622
|
-
target.bleed = 0;
|
|
2623
|
-
}
|
|
2624
|
-
if (effect.stun && target.status !== 2 /* lastStunned */)
|
|
2625
|
-
target.status = 1 /* Stunned */;
|
|
2626
|
-
return target;
|
|
2627
|
-
}
|
|
2628
|
-
// heal?: number // 治疗
|
|
2629
|
-
// shield?: number // 护盾
|
|
2630
|
-
// selfbleed?: number // 自身流血
|
|
2631
|
-
// selfStun?: boolean // 自身眩晕
|
|
2632
|
-
// selfstrengthChange?: number // 自身力量变化
|
|
2633
|
-
applyEffectToSelf(enemy, self, effect) {
|
|
2612
|
+
enemy.vulnerablility = (enemy.vulnerablility || 0) + effect.vulnerablility;
|
|
2634
2613
|
if (effect.heal)
|
|
2635
2614
|
self.hp += effect.heal;
|
|
2636
2615
|
if (effect.shield)
|
|
@@ -2641,24 +2620,41 @@ ${bonusMessage}` : "");
|
|
|
2641
2620
|
self.left = (self.left + effect.addSelfLeft) % 10;
|
|
2642
2621
|
if (effect.addSelfRight)
|
|
2643
2622
|
self.right = (self.right + effect.addSelfRight) % 10;
|
|
2623
|
+
if (effect.damage) {
|
|
2624
|
+
effect.damageTimes = effect.damageTimes || 1;
|
|
2625
|
+
for (let i = 0; i < effect.damageTimes; i++) {
|
|
2626
|
+
const blocked = enemy.shield > 0;
|
|
2627
|
+
enemy.shield = Math.max(0, enemy.shield - (isCombo ? 2 : 1));
|
|
2628
|
+
if (!blocked) {
|
|
2629
|
+
enemy.hp -= Math.round(Math.max(0, effect.damage + (self.strength || 0)) * (enemy.vulnerablility ? 1.5 : 1));
|
|
2630
|
+
if (effect.weakStun && enemy.status !== 2 /* lastStunned */) {
|
|
2631
|
+
enemy.status = 1 /* Stunned */;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2644
2636
|
if (self.counterAttack)
|
|
2645
2637
|
self.counterAttack = 0;
|
|
2646
2638
|
if (effect.counterAttack)
|
|
2647
2639
|
self.counterAttack = effect.counterAttack;
|
|
2648
2640
|
if (enemy.counterAttack > 0 && (effect.damage > 0 || effect.pierceDamage > 0))
|
|
2649
2641
|
self.hp -= Math.max(enemy.counterAttack + (enemy.strength || 0), 0);
|
|
2650
|
-
if (effect.revwersalOfStrength)
|
|
2651
|
-
self.strength = enemy.strength;
|
|
2652
|
-
if (effect.selfStun && self.status !== 2 /* lastStunned */)
|
|
2653
|
-
self.status = 1 /* Stunned */;
|
|
2654
2642
|
if (effect.selfbleed)
|
|
2655
|
-
self.bleed
|
|
2643
|
+
self.bleed += effect.selfbleed;
|
|
2656
2644
|
if (self.bleed > 0)
|
|
2657
2645
|
self.hp -= self.bleed;
|
|
2658
2646
|
self.bleed = Math.max(0, self.bleed - 1);
|
|
2647
|
+
if (effect.magnificentEnd) {
|
|
2648
|
+
enemy.hp -= enemy.bleed * (enemy.bleed + 1) / 2;
|
|
2649
|
+
enemy.bleed = 0;
|
|
2650
|
+
}
|
|
2659
2651
|
if (self.vulnerablility)
|
|
2660
2652
|
self.vulnerablility = Math.max(0, self.vulnerablility - 1);
|
|
2661
|
-
|
|
2653
|
+
if (effect.stun && enemy.status !== 2 /* lastStunned */)
|
|
2654
|
+
enemy.status = 1 /* Stunned */;
|
|
2655
|
+
if (effect.selfStun && self.status !== 2 /* lastStunned */)
|
|
2656
|
+
self.status = 1 /* Stunned */;
|
|
2657
|
+
return;
|
|
2662
2658
|
}
|
|
2663
2659
|
checkCombo(a, b) {
|
|
2664
2660
|
const key = `${Math.min(a, b)}+${Math.max(a, b)}`;
|
|
@@ -2668,6 +2664,8 @@ ${bonusMessage}` : "");
|
|
|
2668
2664
|
let msg = [];
|
|
2669
2665
|
if (effect.name)
|
|
2670
2666
|
msg.push(`${effect.name}!`);
|
|
2667
|
+
if (effect.revwersalOfStrength)
|
|
2668
|
+
msg.push(`双方力量反转!`);
|
|
2671
2669
|
if (effect.pierceDamage)
|
|
2672
2670
|
msg.push(`对对方造成穿刺伤害${Math.max(0, effect.pierceDamage + (self.strength || 0))}`);
|
|
2673
2671
|
if (effect.damage)
|
|
@@ -2729,7 +2727,7 @@ ${bonusMessage}` : "");
|
|
|
2729
2727
|
];
|
|
2730
2728
|
const newState = this.simulateMove(move, simulatedState, 1);
|
|
2731
2729
|
const score = this.aiSearch(
|
|
2732
|
-
this.level,
|
|
2730
|
+
Math.round(this.level / 2),
|
|
2733
2731
|
false,
|
|
2734
2732
|
newState,
|
|
2735
2733
|
-Infinity,
|
|
@@ -2788,7 +2786,7 @@ ${bonusMessage}` : "");
|
|
|
2788
2786
|
}
|
|
2789
2787
|
return moves;
|
|
2790
2788
|
}
|
|
2791
|
-
//
|
|
2789
|
+
// 克隆玩家状态
|
|
2792
2790
|
cloneState(state) {
|
|
2793
2791
|
return {
|
|
2794
2792
|
left: state.left,
|
|
@@ -2797,6 +2795,8 @@ ${bonusMessage}` : "");
|
|
|
2797
2795
|
shield: state.shield,
|
|
2798
2796
|
strength: state.strength,
|
|
2799
2797
|
bleed: state.bleed,
|
|
2798
|
+
counterAttack: state.counterAttack,
|
|
2799
|
+
vulnerablility: state.vulnerablility,
|
|
2800
2800
|
status: state.status
|
|
2801
2801
|
};
|
|
2802
2802
|
}
|
|
@@ -2809,16 +2809,13 @@ ${bonusMessage}` : "");
|
|
|
2809
2809
|
attacker.status = 0 /* Normal */;
|
|
2810
2810
|
if (attacker.status === 1 /* Stunned */) {
|
|
2811
2811
|
attacker.status = 2 /* lastStunned */;
|
|
2812
|
-
|
|
2812
|
+
this.applyEffect(attacker, defender, SKILL_MAP["-1"], false);
|
|
2813
2813
|
} else {
|
|
2814
2814
|
const sum = (handA + handB) % 10;
|
|
2815
2815
|
attacker[handA === attacker.left ? "left" : "right"] = sum;
|
|
2816
2816
|
const combo = this.checkCombo(attacker.left, attacker.right);
|
|
2817
2817
|
const effect = combo ? combo : SKILL_MAP[sum.toString()] || {};
|
|
2818
|
-
|
|
2819
|
-
const attackerState = attacker;
|
|
2820
|
-
defender = this.applyEffectToEnemy(attackerState, defenderState, effect, !!combo);
|
|
2821
|
-
attacker = this.applyEffectToSelf(defenderState, attackerState, effect);
|
|
2818
|
+
this.applyEffect(attacker, defender, effect, !!combo);
|
|
2822
2819
|
}
|
|
2823
2820
|
if (attackerIndex === 1) {
|
|
2824
2821
|
const temp = attacker;
|
|
@@ -2848,11 +2845,7 @@ ${bonusMessage}` : "");
|
|
|
2848
2845
|
if (player.hp < playerBaseHP / 8)
|
|
2849
2846
|
score += Math.round(playerBaseHP / 4);
|
|
2850
2847
|
score += Math.min(ai.strength * 5, 100);
|
|
2851
|
-
score -= Math.
|
|
2852
|
-
if (ai.strength < 0)
|
|
2853
|
-
score += Math.round(ai.strength * 5);
|
|
2854
|
-
if (player.strength < 0)
|
|
2855
|
-
score -= Math.round(player.strength * 5);
|
|
2848
|
+
score -= Math.max(player.strength * 5, -100);
|
|
2856
2849
|
score += ai.shield * 8;
|
|
2857
2850
|
score -= player.shield * 8;
|
|
2858
2851
|
score -= Math.min(Math.round(ai.bleed * ai.bleed / 2.5));
|
|
@@ -2879,10 +2872,10 @@ ${bonusMessage}` : "");
|
|
|
2879
2872
|
if (this.lastScore < 9e4 && Score > 9e4) {
|
|
2880
2873
|
return "我觉得你要输了哦~";
|
|
2881
2874
|
}
|
|
2882
|
-
if (this.lastScore < 0 && Score > 0) {
|
|
2875
|
+
if (this.lastScore < 0 && Score > 0 && Math.random() > 0.5) {
|
|
2883
2876
|
return "局势发生变化了呢~";
|
|
2884
2877
|
}
|
|
2885
|
-
if (Score - this.lastScore > 10)
|
|
2878
|
+
if (Score - this.lastScore > 10 && Math.random() > 0.8)
|
|
2886
2879
|
return "看招!";
|
|
2887
2880
|
}
|
|
2888
2881
|
instuction = `游戏说明:
|
|
@@ -2895,9 +2888,23 @@ ${bonusMessage}` : "");
|
|
|
2895
2888
|
当自身两手手势相同时,无论选择左手还是右手最终发生变化的都是左手。
|
|
2896
2889
|
玩家初始有"${this.baseHP} + ${this.playerLevelHP} * 难度"血量。
|
|
2897
2890
|
ai初始有"${this.baseHP} + ${this.aiLevelHp} * 难度"血量。
|
|
2898
|
-
玩家初始有"难度 / 2"护盾,四舍五入取整。
|
|
2891
|
+
玩家初始有"6 - 难度 / 2"护盾,四舍五入取整。
|
|
2899
2892
|
血量没有上限,率先将对方血量减到零的人获胜:
|
|
2900
|
-
|
|
2893
|
+
|
|
2894
|
+
游戏名称说明:
|
|
2895
|
+
流血效果:每次到自己回合结束时,收到流血层数点伤害,不可被护盾阻挡,然后流血层数减1;
|
|
2896
|
+
护盾效果:每一层护盾可阻挡下一次受到的普通伤害,如果伤害来源是组合技则消耗两层护盾(若仅有一层则消耗一层)。护盾上限为五层。
|
|
2897
|
+
眩晕效果:跳过自己的下一个回合,若上回合已经被眩晕,则本回合不受眩晕影响(即不可被连续眩晕)
|
|
2898
|
+
弱眩晕效果:若对方没有护盾,则眩晕对方一回合
|
|
2899
|
+
反击:下一回合若对方行动中有攻击,则对方攻击前受到反击层数点穿刺伤害,此效果受力量加成,且仅持续一回合
|
|
2900
|
+
穿刺伤害:不被护盾影响的伤害(不会消耗护盾)
|
|
2901
|
+
力量效果:每有一点力量,每次造成的伤害+1,若为负数则减一
|
|
2902
|
+
易伤效果:受到的普通伤害+50%,自己的回合结束时减少一层
|
|
2903
|
+
组合技:在触碰完成后,若你的两只手手势符合组合技条件,则触发组合技,组合技的效果会覆盖普通技能的效果,组合无序
|
|
2904
|
+
bonus: 当行动导致关键效果时,获得额外奖励,在ai回合结束时结算,若ai被眩晕则奖励继承到下一回合
|
|
2905
|
+
`;
|
|
2906
|
+
skillList = `
|
|
2907
|
+
具体的技能设计如下:
|
|
2901
2908
|
一:${SKILL_MAP["1"].name}:造成${SKILL_MAP["1"].pierceDamage}穿刺伤害,${SKILL_MAP["1"].bleed}流血;
|
|
2902
2909
|
二:${SKILL_MAP["2"].name}:造成${SKILL_MAP["2"].pierceDamage}穿刺伤害,眩晕对方;
|
|
2903
2910
|
三:${SKILL_MAP["3"].name}:造成${SKILL_MAP["3"].damage}伤害,获得${SKILL_MAP["3"].counterAttack}层反击;
|
|
@@ -2925,20 +2932,8 @@ ${bonusMessage}` : "");
|
|
|
2925
2932
|
七+八:${SKILL_MAP["7+8"].name}:造成${SKILL_MAP["7+8"].pierceDamage}穿刺伤害,破坏对方${SKILL_MAP["7+8"].destroyShield}层护盾,眩晕自己
|
|
2926
2933
|
六+二:${SKILL_MAP["2+6"].name}:造成${SKILL_MAP["2+6"].damage}伤害,恢复${SKILL_MAP["2+6"].heal}生命,自身${SKILL_MAP["2+6"].selfbleed}流血,自身增加${SKILL_MAP["2+6"].selfstrengthChange}力量,眩晕对方
|
|
2927
2934
|
三+七:${SKILL_MAP["3+7"].name}:获得${SKILL_MAP["3+7"].counterAttack}层反击,破坏对方${SKILL_MAP["3+7"].destroyShield}层护盾,对方左手数值增加${SKILL_MAP["3+7"].addLeft},右手数值增加${SKILL_MAP["3+7"].addRight}
|
|
2928
|
-
九+十:${SKILL_MAP["0+9"].name}
|
|
2935
|
+
九+十:${SKILL_MAP["0+9"].name}:逆转双方力量,然后增加自身${SKILL_MAP["0+9"].selfstrengthChange}力量,对方${SKILL_MAP["0+9"].strengthChange}力量
|
|
2929
2936
|
十+十:${SKILL_MAP["0+0"].name}:对对方造成${SKILL_MAP["0+0"].bleed}流血,自身${SKILL_MAP["0+0"].selfstrengthChange}力量,然后立即结算对方全部流血
|
|
2930
|
-
}
|
|
2931
|
-
注:
|
|
2932
|
-
流血效果:每次到自己回合结束时,收到流血层数点伤害,不可被护盾阻挡,然后流血层数减1;
|
|
2933
|
-
护盾效果:每一层护盾可阻挡下一次受到的普通伤害,如果伤害来源是组合技则消耗两层护盾(若仅有一层则消耗一层)。护盾上限为五层。
|
|
2934
|
-
眩晕效果:跳过自己的下一个回合,若上回合已经被眩晕,则本回合不受眩晕影响(即不可被连续眩晕)
|
|
2935
|
-
弱眩晕效果:若对方没有护盾,则眩晕对方一回合
|
|
2936
|
-
反击:下一回合若对方行动中有攻击,则对方攻击前受到反击层数点穿刺伤害,此效果受力量加成,且仅持续一回合
|
|
2937
|
-
穿刺伤害:不被护盾影响的伤害(不会消耗护盾)
|
|
2938
|
-
力量效果:每有一点力量,每次造成的伤害+1,若为负数则减一
|
|
2939
|
-
易伤效果:受到的普通伤害+50%,自己的回合结束时减少一层
|
|
2940
|
-
组合技:两只手势符合组合技条件时触发组合技,组合技的效果会覆盖普通技能的效果,组合无序
|
|
2941
|
-
bonus: 当行动导致关键效果时,获得额外奖励,在ai回合结束时结算,若ai被眩晕则奖励继承到下一回合
|
|
2942
2937
|
`;
|
|
2943
2938
|
};
|
|
2944
2939
|
var OneTouchGame = class extends abstractGame {
|
|
@@ -3134,14 +3129,152 @@ var Game = class {
|
|
|
3134
3129
|
}
|
|
3135
3130
|
};
|
|
3136
3131
|
|
|
3132
|
+
// src/broadcast.ts
|
|
3133
|
+
var import_koishi13 = require("koishi");
|
|
3134
|
+
var logger12 = new import_koishi13.Logger("satori-ai-broadcast");
|
|
3135
|
+
var BroadcastManager = class {
|
|
3136
|
+
static {
|
|
3137
|
+
__name(this, "BroadcastManager");
|
|
3138
|
+
}
|
|
3139
|
+
ctx;
|
|
3140
|
+
config;
|
|
3141
|
+
idCounter = 0;
|
|
3142
|
+
broadcastMessages = /* @__PURE__ */ new Map();
|
|
3143
|
+
constructor(ctx, cfg) {
|
|
3144
|
+
this.ctx = ctx;
|
|
3145
|
+
this.config = cfg;
|
|
3146
|
+
this.idCounter = 0;
|
|
3147
|
+
ctx.command("sat.broadcast <text:text>", "推送广播", { authority: 4 }).alias("广播").option("delete", "-d <id:string>", { authority: 4 }).option("list", "-l", { authority: 4 }).option("img", "-i", { authority: 4 }).action(async ({ options }, prompt) => {
|
|
3148
|
+
refreshPuppeteer(this.ctx);
|
|
3149
|
+
if (options.list) {
|
|
3150
|
+
const list = this.broadcastMessages.size > 0 ? await this.getBroadcastList() : null;
|
|
3151
|
+
return list ? `${list}` : "当前没有广播";
|
|
3152
|
+
}
|
|
3153
|
+
if (options.delete) {
|
|
3154
|
+
return await this.deleteBroadcast(options.delete);
|
|
3155
|
+
} else {
|
|
3156
|
+
return await this.createBroadcast(prompt, options.img);
|
|
3157
|
+
}
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
3160
|
+
async createBroadcast(message, img) {
|
|
3161
|
+
const id = `broadcast-${this.idCounter++}`;
|
|
3162
|
+
const broadcast = new broadcastMessage(this.ctx, this.config, message, img);
|
|
3163
|
+
this.broadcastMessages.set(id, broadcast);
|
|
3164
|
+
logger12.info(`广播已创建 ID: ${id}`);
|
|
3165
|
+
return `广播已创建 ID: ${id}`;
|
|
3166
|
+
}
|
|
3167
|
+
async deleteBroadcast(id) {
|
|
3168
|
+
if (this.broadcastMessages.has(id)) {
|
|
3169
|
+
this.broadcastMessages.delete(id);
|
|
3170
|
+
logger12.info(`广播已删除 ID: ${id}`);
|
|
3171
|
+
return "已删除广播:" + id;
|
|
3172
|
+
} else {
|
|
3173
|
+
logger12.warn(`未找到广播 ID: ${id}`);
|
|
3174
|
+
return "未找到该广播";
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
async seedBroadcast(session) {
|
|
3178
|
+
for (const [id, broadcast] of this.broadcastMessages.entries()) {
|
|
3179
|
+
if (broadcast.setTime.getTime() + 1e3 * 60 * this.config.waiting_time < Date.now()) {
|
|
3180
|
+
this.broadcastMessages.delete(id);
|
|
3181
|
+
logger12.info(`广播已过期 ID: ${id}`);
|
|
3182
|
+
continue;
|
|
3183
|
+
}
|
|
3184
|
+
await broadcast.sendMessage(session);
|
|
3185
|
+
}
|
|
3186
|
+
return;
|
|
3187
|
+
}
|
|
3188
|
+
async getBroadcastList() {
|
|
3189
|
+
const idList = Array.from(this.broadcastMessages.keys());
|
|
3190
|
+
const list = [];
|
|
3191
|
+
list.push("当前广播列表:");
|
|
3192
|
+
for (const id of idList) {
|
|
3193
|
+
const broadcast = this.broadcastMessages.get(id);
|
|
3194
|
+
if (broadcast) {
|
|
3195
|
+
const time = broadcast.setTime.toLocaleString("zh-CN", { hour12: false });
|
|
3196
|
+
const ddl = new Date(broadcast.setTime.getTime() + 1e3 * 60 * this.config.waiting_time).toLocaleString("zh-CN", { hour12: false });
|
|
3197
|
+
const message = broadcast.message;
|
|
3198
|
+
const alreadySentChannels = broadcast.getAlreadySentChannels();
|
|
3199
|
+
list.push(`ID: ${id}
|
|
3200
|
+
消息: ${message}
|
|
3201
|
+
已发送频道:
|
|
3202
|
+
${alreadySentChannels}
|
|
3203
|
+
创建时间: ${time}
|
|
3204
|
+
过期时间: ${ddl}
|
|
3205
|
+
`);
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
const result = list.length > 0 ? list.join("\n") : null;
|
|
3209
|
+
return result ? wrapInHTML3(result) : null;
|
|
3210
|
+
}
|
|
3211
|
+
};
|
|
3212
|
+
var broadcastMessage = class {
|
|
3213
|
+
static {
|
|
3214
|
+
__name(this, "broadcastMessage");
|
|
3215
|
+
}
|
|
3216
|
+
ctx;
|
|
3217
|
+
config;
|
|
3218
|
+
message;
|
|
3219
|
+
alreadySentChannels = /* @__PURE__ */ new Set();
|
|
3220
|
+
setTime;
|
|
3221
|
+
img;
|
|
3222
|
+
constructor(ctx, cfg, message, img) {
|
|
3223
|
+
this.message = message;
|
|
3224
|
+
this.alreadySentChannels = /* @__PURE__ */ new Set();
|
|
3225
|
+
this.ctx = ctx;
|
|
3226
|
+
this.config = cfg;
|
|
3227
|
+
this.img = img;
|
|
3228
|
+
this.setTime = /* @__PURE__ */ new Date();
|
|
3229
|
+
for (const channelId of this.config.Broadcast_block_channel) {
|
|
3230
|
+
this.alreadySentChannels.add(channelId);
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
async sendMessage(session) {
|
|
3234
|
+
const channelId = session.channelId;
|
|
3235
|
+
if (this.alreadySentChannels.has(channelId))
|
|
3236
|
+
return;
|
|
3237
|
+
try {
|
|
3238
|
+
this.alreadySentChannels.add(channelId);
|
|
3239
|
+
if (this.img) {
|
|
3240
|
+
session.send(await wrapInHTML3(this.message));
|
|
3241
|
+
} else {
|
|
3242
|
+
session.send(this.message);
|
|
3243
|
+
}
|
|
3244
|
+
logger12.info(`向群 ${channelId} 广播: ${this.message}`);
|
|
3245
|
+
} catch (error) {
|
|
3246
|
+
logger12.error(`广播失败 ${channelId}: ${error}`);
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
getAlreadySentChannels() {
|
|
3250
|
+
const alreadySentChannels = Array.from(this.alreadySentChannels).filter((channelId) => !this.config.Broadcast_block_channel.includes(channelId));
|
|
3251
|
+
return alreadySentChannels.length > 0 ? alreadySentChannels.join("\n") : "无";
|
|
3252
|
+
}
|
|
3253
|
+
};
|
|
3254
|
+
async function wrapInHTML3(str) {
|
|
3255
|
+
if (!puppeteer) {
|
|
3256
|
+
logger12.warn("puppeteer未就绪");
|
|
3257
|
+
return str;
|
|
3258
|
+
}
|
|
3259
|
+
return puppeteer.render(`<html><body>${str.replaceAll(/\n/g, "<BR>")}</body>
|
|
3260
|
+
<style>
|
|
3261
|
+
body {
|
|
3262
|
+
padding: 10px;
|
|
3263
|
+
display: inline-block;
|
|
3264
|
+
}
|
|
3265
|
+
</style>
|
|
3266
|
+
</html>`);
|
|
3267
|
+
}
|
|
3268
|
+
__name(wrapInHTML3, "wrapInHTML");
|
|
3269
|
+
|
|
3137
3270
|
// src/index.tsx
|
|
3138
|
-
var
|
|
3271
|
+
var logger13 = new import_koishi14.Logger("satori-ai");
|
|
3139
3272
|
var puppeteer = null;
|
|
3140
3273
|
function refreshPuppeteer(ctx) {
|
|
3141
3274
|
if (ctx.puppeteer) {
|
|
3142
3275
|
puppeteer = ctx.puppeteer;
|
|
3143
3276
|
} else {
|
|
3144
|
-
|
|
3277
|
+
logger13.warn("puppeteer未就绪");
|
|
3145
3278
|
}
|
|
3146
3279
|
}
|
|
3147
3280
|
__name(refreshPuppeteer, "refreshPuppeteer");
|
|
@@ -3157,6 +3290,7 @@ var SAT = class extends Sat {
|
|
|
3157
3290
|
this.memoryManager = new MemoryManager(ctx, this.getMemoryConfig());
|
|
3158
3291
|
this.portraitManager = new UserPortraitManager(ctx, config);
|
|
3159
3292
|
this.moodManager = new MoodManager(ctx, config);
|
|
3293
|
+
this.broadcastManager = new BroadcastManager(ctx, config);
|
|
3160
3294
|
ensureCensorFileExists(this.config.dataDir);
|
|
3161
3295
|
ctx.middleware(createMiddleware(ctx, this, this.getMiddlewareConfig()));
|
|
3162
3296
|
this.registerCommands(ctx);
|
|
@@ -3172,6 +3306,7 @@ var SAT = class extends Sat {
|
|
|
3172
3306
|
ChannelParallelCount = /* @__PURE__ */ new Map();
|
|
3173
3307
|
onlineUsers = [];
|
|
3174
3308
|
moodManager;
|
|
3309
|
+
broadcastManager;
|
|
3175
3310
|
usersToWarn = /* @__PURE__ */ new Map();
|
|
3176
3311
|
game;
|
|
3177
3312
|
getAPIConfig() {
|
|
@@ -3327,9 +3462,9 @@ var SAT = class extends Sat {
|
|
|
3327
3462
|
const messages = generateAuxiliaryPrompt(prompt, response.content, user, this.getFavorabilityConfig());
|
|
3328
3463
|
const result = await this.apiClient.auxiliaryChat(messages);
|
|
3329
3464
|
if (result.error) {
|
|
3330
|
-
|
|
3465
|
+
logger13.error(`辅助判断失败:${result.content}`);
|
|
3331
3466
|
} else {
|
|
3332
|
-
|
|
3467
|
+
logger13.info(`辅助判断:${result.content}`);
|
|
3333
3468
|
return handleAuxiliaryResult(this.ctx, session, this.getFavorabilityConfig(), result.content);
|
|
3334
3469
|
}
|
|
3335
3470
|
}
|
|
@@ -3416,13 +3551,13 @@ var SAT = class extends Sat {
|
|
|
3416
3551
|
await inputContentCheck(this.ctx, censored, session.userId, this.getFavorabilityConfig(), session, this.moodManager);
|
|
3417
3552
|
}
|
|
3418
3553
|
if (this.config.log_ask_response)
|
|
3419
|
-
|
|
3554
|
+
logger13.info(`用户 ${session.username}:${processedPrompt}`);
|
|
3420
3555
|
return censored;
|
|
3421
3556
|
}
|
|
3422
3557
|
// 生成回复
|
|
3423
3558
|
async generateResponse(session, prompt) {
|
|
3424
3559
|
if (this.getChannelParallelCount(session) > this.config.max_parallel_count) {
|
|
3425
|
-
|
|
3560
|
+
logger13.info(`频道 ${session.channelId} 并发数过高(${this.getChannelParallelCount(session)}),${session.username}等待中...`);
|
|
3426
3561
|
}
|
|
3427
3562
|
while (this.getChannelParallelCount(session) > this.config.max_parallel_count) {
|
|
3428
3563
|
this.updateChannelParallelCount(session, -1);
|
|
@@ -3430,7 +3565,7 @@ var SAT = class extends Sat {
|
|
|
3430
3565
|
this.updateChannelParallelCount(session, 1);
|
|
3431
3566
|
}
|
|
3432
3567
|
const messages = await this.buildMessages(session, prompt);
|
|
3433
|
-
|
|
3568
|
+
logger13.info(`频道 ${session.channelId} 处理:${session.userId},剩余${this.getChannelParallelCount(session)}并发`);
|
|
3434
3569
|
const user = await getUser(this.ctx, session.userId);
|
|
3435
3570
|
let response = await this.getChatResponse(user, messages);
|
|
3436
3571
|
if (response.error)
|
|
@@ -3444,9 +3579,9 @@ var SAT = class extends Sat {
|
|
|
3444
3579
|
let response = await this.apiClient.chat(user, messages);
|
|
3445
3580
|
if (this.config.log_ask_response) {
|
|
3446
3581
|
if (this.config.enable_favorability && this.config.enable_mood)
|
|
3447
|
-
|
|
3582
|
+
logger13.info(`Satori AI:(心情值:${this.moodManager.getMoodValue(user.userid)})${response.content}`);
|
|
3448
3583
|
else
|
|
3449
|
-
|
|
3584
|
+
logger13.info(`Satori AI:${response.content}`);
|
|
3450
3585
|
}
|
|
3451
3586
|
if (this.config.reasoner_filter && !response.error)
|
|
3452
3587
|
response = filterResponse(response.content, this.config.reasoner_filter_word.split("-"));
|
|
@@ -3470,7 +3605,7 @@ var SAT = class extends Sat {
|
|
|
3470
3605
|
messages.push({ role: "user", content: prompt });
|
|
3471
3606
|
let payload = messages.map((msg) => msg.role + ":" + msg.content).join("\n");
|
|
3472
3607
|
if (this.config.log_system_prompt)
|
|
3473
|
-
|
|
3608
|
+
logger13.info(`系统提示:
|
|
3474
3609
|
${payload}`);
|
|
3475
3610
|
return messages;
|
|
3476
3611
|
}
|
|
@@ -3575,7 +3710,7 @@ ${useNoReasoner ? promptForNoReasoner : promptForReasoner}
|
|
|
3575
3710
|
response = `@${session.username} ` + response;
|
|
3576
3711
|
}
|
|
3577
3712
|
if (this.config.sentences_divide && response.length > 10) {
|
|
3578
|
-
const sentences = splitSentences(response, this.config.min_sentences_length, this.config.max_sentences_length).map((text) =>
|
|
3713
|
+
const sentences = splitSentences(response, this.config.min_sentences_length, this.config.max_sentences_length).map((text) => import_koishi14.h.text(text));
|
|
3579
3714
|
for (const sentence of sentences) {
|
|
3580
3715
|
await session.send(sentence);
|
|
3581
3716
|
await new Promise((resolve3) => setTimeout(resolve3, this.config.time_interval));
|
|
@@ -3588,7 +3723,7 @@ ${useNoReasoner ? promptForNoReasoner : promptForReasoner}
|
|
|
3588
3723
|
if (!this.config.enable_warning)
|
|
3589
3724
|
return;
|
|
3590
3725
|
if (auxiliaryResult.includes("好感↓")) {
|
|
3591
|
-
|
|
3726
|
+
logger13.info(`在群${session.channelId}中,${session.username}骚扰我!`);
|
|
3592
3727
|
this.usersToWarn.set(session.channelId, session.username);
|
|
3593
3728
|
}
|
|
3594
3729
|
}
|
package/lib/mood.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class MoodManager {
|
|
|
9
9
|
private checkDailyReset;
|
|
10
10
|
handleInputMoodChange(user: User, favorabilityLevel: string): Promise<void>;
|
|
11
11
|
handleOutputMoodChange(user: User, favorabilityLevel: string): Promise<void>;
|
|
12
|
-
applyMoodChange(user: User, delta: number): void
|
|
12
|
+
applyMoodChange(user: User, delta: number): Promise<void>;
|
|
13
13
|
getMoodLevel(userId: string): string;
|
|
14
14
|
getMoodValue(userId: string): number;
|
|
15
15
|
generateMoodPrompt(userId: string): string;
|
package/lib/types.d.ts
CHANGED
|
@@ -240,6 +240,8 @@ export declare namespace Sat {
|
|
|
240
240
|
warning_admin_id: string;
|
|
241
241
|
maxRetryTimes: number;
|
|
242
242
|
retry_delay_time: number;
|
|
243
|
+
Broadcast_block_channel: string[];
|
|
244
|
+
waiting_time: number;
|
|
243
245
|
enable_game: boolean;
|
|
244
246
|
game_block_channel: string[];
|
|
245
247
|
enable_gobang: boolean;
|
package/lib/utils.d.ts
CHANGED
|
@@ -29,3 +29,5 @@ export declare function filterResponse(prompt: string, words: string[]): {
|
|
|
29
29
|
};
|
|
30
30
|
export declare function addOutputCensor(session: Session, word: string, baseURL: string): void;
|
|
31
31
|
export declare function updateUserPWithTicket(ctx: Context, user: User, adjustment: number): Promise<void>;
|
|
32
|
+
export declare function findLongestCommonSubstring(str1: string, str2: string): number;
|
|
33
|
+
export declare function countCommonChars(str1: string, str2: string): number;
|