Blame Raw
Cohee · e3f41666 · · 148 lines (5.1 KB)
1 contributor
1import { MacroRegistry, MacroCategory, MacroValueType } from '../engine/MacroRegistry.js';
2import { chat, chat_metadata } from '../../../script.js';
3
4/**
5 * Registers macros that inspect the current chat log and swipe state
6 * (message texts, indices, swipes, and context boundaries).
7 */
8export function registerChatMacros() {
9 MacroRegistry.registerMacro('lastMessage', {
10 category: MacroCategory.CHAT,
11 description: 'Last message in the chat.',
12 returns: 'Last message in the chat.',
13 handler: () => String(getLastMessage() ?? ''),
14 });
15
16 MacroRegistry.registerMacro('lastMessageId', {
17 category: MacroCategory.CHAT,
18 description: 'Index of the last message in the chat.',
19 returns: 'Index of the last message in the chat.',
20 returnType: MacroValueType.INTEGER,
21 handler: () => String(getLastMessageId() ?? ''),
22 });
23
24 MacroRegistry.registerMacro('lastUserMessage', {
25 category: MacroCategory.CHAT,
26 description: 'Last user message in the chat.',
27 returns: 'Last user message in the chat.',
28 handler: () => String(getLastUserMessage() ?? ''),
29 });
30
31 MacroRegistry.registerMacro('lastCharMessage', {
32 category: MacroCategory.CHAT,
33 description: 'Last character/bot message in the chat.',
34 returns: 'Last character/bot message in the chat.',
35 handler: () => String(getLastCharMessage() ?? ''),
36 });
37
38 MacroRegistry.registerMacro('firstIncludedMessageId', {
39 category: MacroCategory.CHAT,
40 description: 'Index of the first message included in the current context.',
41 returns: 'Index of the first message included in the context.',
42 returnType: MacroValueType.INTEGER,
43 handler: () => String(getFirstIncludedMessageId() ?? ''),
44 });
45
46 MacroRegistry.registerMacro('firstDisplayedMessageId', {
47 category: MacroCategory.CHAT,
48 description: 'Index of the first displayed message in the chat.',
49 returns: 'Index of the first displayed message in the chat.',
50 returnType: MacroValueType.INTEGER,
51 handler: () => String(getFirstDisplayedMessageId() ?? ''),
52 });
53
54 MacroRegistry.registerMacro('lastSwipeId', {
55 category: MacroCategory.CHAT,
56 description: '1-based index of the last swipe for the last message.',
57 returns: '1-based index of the last swipe.',
58 returnType: MacroValueType.INTEGER,
59 handler: () => String(getLastSwipeId() ?? ''),
60 });
61
62 MacroRegistry.registerMacro('currentSwipeId', {
63 category: MacroCategory.CHAT,
64 description: '1-based index of the current swipe.',
65 returns: '1-based index of the current swipe.',
66 returnType: MacroValueType.INTEGER,
67 handler: () => String(getCurrentSwipeId() ?? ''),
68 });
69
70 MacroRegistry.registerMacro('allChatRange', {
71 category: MacroCategory.CHAT,
72 description: 'Range of all message IDs in the chat (e.g. "0-10"). Empty string if the chat is empty.',
73 returns: 'Range string from 0 to last message ID, or empty string.',
74 handler: () => {
75 if (!Array.isArray(chat) || chat.length === 0) {
76 return '';
77 }
78 return `0-${chat.length - 1}`;
79 },
80 });
81}
82
83function getLastMessageId({ exclude_swipe_in_propress = true, filter = null } = {}) {
84 if (!Array.isArray(chat) || chat.length === 0) {
85 return null;
86 }
87
88 for (let i = chat.length - 1; i >= 0; i--) {
89 const message = chat[i];
90
91 if (exclude_swipe_in_propress && message.swipes && message.swipe_id >= message.swipes.length) {
92 continue;
93 }
94
95 if (!filter || filter(message)) {
96 return i;
97 }
98 }
99
100 return null;
101}
102
103function getLastMessage() {
104 const mid = getLastMessageId();
105 return typeof mid === 'number' ? (chat[mid]?.mes ?? '') : '';
106}
107
108function getLastUserMessage() {
109 const mid = getLastMessageId({ filter: m => m.is_user && !m.is_system });
110 return typeof mid === 'number' ? (chat[mid]?.mes ?? '') : '';
111}
112
113function getLastCharMessage() {
114 const mid = getLastMessageId({ filter: m => !m.is_user && !m.is_system });
115 return typeof mid === 'number' ? (chat[mid]?.mes ?? '') : '';
116}
117
118function getFirstIncludedMessageId() {
119 const value = chat_metadata.lastInContextMessageId;
120 return typeof value === 'number' ? value : null;
121}
122
123function getFirstDisplayedMessageId() {
124 const mesElement = document.querySelector('#chat .mes');
125 const mesId = Number(mesElement?.getAttribute('mesid'));
126 if (!Number.isNaN(mesId) && mesId >= 0) {
127 return mesId;
128 }
129 return null;
130}
131
132function getLastSwipeId() {
133 const mid = getLastMessageId({ exclude_swipe_in_propress: false });
134 if (typeof mid !== 'number') {
135 return null;
136 }
137 const swipes = chat[mid]?.swipes;
138 return Array.isArray(swipes) ? swipes.length : null;
139}
140
141function getCurrentSwipeId() {
142 const mid = getLastMessageId({ exclude_swipe_in_propress: false });
143 if (typeof mid !== 'number') {
144 return null;
145 }
146 const swipeId = chat[mid]?.swipe_id;
147 return typeof swipeId === 'number' ? swipeId + 1 : null;
148}