QR auto-execute on group member draft

This commit is contained in:
Cohee 2024-01-18 18:08:38 +02:00
parent b8445eb2cd
commit 4f55824d7f
8 changed files with 39 additions and 1 deletions

View File

@ -335,6 +335,7 @@ export const event_types = {
CHAT_DELETED: 'chat_deleted', CHAT_DELETED: 'chat_deleted',
GROUP_CHAT_DELETED: 'group_chat_deleted', GROUP_CHAT_DELETED: 'group_chat_deleted',
GENERATE_BEFORE_COMBINE_PROMPTS: 'generate_before_combine_prompts', GENERATE_BEFORE_COMBINE_PROMPTS: 'generate_before_combine_prompts',
GROUP_MEMBER_DRAFTED: 'group_member_drafted',
}; };
export const eventSource = new EventEmitter(); export const eventSource = new EventEmitter();

View File

@ -190,6 +190,7 @@ export class QuickReplyApi {
* @param {Boolean} [props.executeOnUser] whether to execute the quick reply after a user has sent a message * @param {Boolean} [props.executeOnUser] whether to execute the quick reply after a user has sent a message
* @param {Boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message * @param {Boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message
* @param {Boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded * @param {Boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded
* @param {Boolean} [props.executeOnGroupMemberDraft] whether to execute the quick reply when a group member is selected
* @returns {QuickReply} the new quick reply * @returns {QuickReply} the new quick reply
*/ */
createQuickReply(setName, label, { createQuickReply(setName, label, {
@ -200,6 +201,7 @@ export class QuickReplyApi {
executeOnUser, executeOnUser,
executeOnAi, executeOnAi,
executeOnChatChange, executeOnChatChange,
executeOnGroupMemberDraft,
} = {}) { } = {}) {
const set = this.getSetByName(setName); const set = this.getSetByName(setName);
if (!set) { if (!set) {
@ -214,6 +216,7 @@ export class QuickReplyApi {
qr.executeOnUser = executeOnUser ?? false; qr.executeOnUser = executeOnUser ?? false;
qr.executeOnAi = executeOnAi ?? false; qr.executeOnAi = executeOnAi ?? false;
qr.executeOnChatChange = executeOnChatChange ?? false; qr.executeOnChatChange = executeOnChatChange ?? false;
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? false;
qr.onUpdate(); qr.onUpdate();
return qr; return qr;
} }
@ -232,6 +235,7 @@ export class QuickReplyApi {
* @param {Boolean} [props.executeOnUser] whether to execute the quick reply after a user has sent a message * @param {Boolean} [props.executeOnUser] whether to execute the quick reply after a user has sent a message
* @param {Boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message * @param {Boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message
* @param {Boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded * @param {Boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded
* @param {Boolean} [props.executeOnGroupMemberDraft] whether to execute the quick reply when a group member is selected
* @returns {QuickReply} the altered quick reply * @returns {QuickReply} the altered quick reply
*/ */
updateQuickReply(setName, label, { updateQuickReply(setName, label, {
@ -243,6 +247,7 @@ export class QuickReplyApi {
executeOnUser, executeOnUser,
executeOnAi, executeOnAi,
executeOnChatChange, executeOnChatChange,
executeOnGroupMemberDraft,
} = {}) { } = {}) {
const qr = this.getQrByLabel(setName, label); const qr = this.getQrByLabel(setName, label);
if (!qr) { if (!qr) {
@ -256,6 +261,7 @@ export class QuickReplyApi {
qr.executeOnUser = executeOnUser ?? qr.executeOnUser; qr.executeOnUser = executeOnUser ?? qr.executeOnUser;
qr.executeOnAi = executeOnAi ?? qr.executeOnAi; qr.executeOnAi = executeOnAi ?? qr.executeOnAi;
qr.executeOnChatChange = executeOnChatChange ?? qr.executeOnChatChange; qr.executeOnChatChange = executeOnChatChange ?? qr.executeOnChatChange;
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? qr.executeOnGroupMemberDraft;
qr.onUpdate(); qr.onUpdate();
return qr; return qr;
} }

View File

@ -66,6 +66,10 @@
<input type="checkbox" id="qr--executeOnChatChange" > <input type="checkbox" id="qr--executeOnChatChange" >
<span><i class="fa-solid fa-fw fa-message"></i> Execute on opening chat</span> <span><i class="fa-solid fa-fw fa-message"></i> Execute on opening chat</span>
</label> </label>
<label class="checkbox_label">
<input type="checkbox" id="qr--executeOnGroupMemberDraft">
<span><i class="fa-solid fa-fw fa-people-group"></i> Execute on group member draft</span>
</label>
</div> </div>

View File

@ -103,6 +103,7 @@ const loadSets = async () => {
qr.executeOnUser = slot.autoExecute_userMessage ?? false; qr.executeOnUser = slot.autoExecute_userMessage ?? false;
qr.executeOnAi = slot.autoExecute_botMessage ?? false; qr.executeOnAi = slot.autoExecute_botMessage ?? false;
qr.executeOnChatChange = slot.autoExecute_chatLoad ?? false; qr.executeOnChatChange = slot.autoExecute_chatLoad ?? false;
qr.executeOnGroupMemberDraft = slot.autoExecute_groupMemberDraft ?? false;
qr.contextList = (slot.contextMenu ?? []).map(it=>({ qr.contextList = (slot.contextMenu ?? []).map(it=>({
set: it.preset, set: it.preset,
isChained: it.chain, isChained: it.chain,
@ -235,3 +236,8 @@ const onAiMessage = async () => {
await autoExec.handleAi(); await autoExec.handleAi();
}; };
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onAiMessage, args)); eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onAiMessage, args));
const onGroupMemberDraft = async () => {
await autoExec.handleGroupMemberDraft();
};
eventSource.on(event_types.GROUP_MEMBER_DRAFTED, (...args) => executeIfReadyElseQueue(onGroupMemberDraft, args));

View File

@ -73,4 +73,13 @@ export class AutoExecuteHandler {
]; ];
await this.performAutoExecute(qrList); await this.performAutoExecute(qrList);
} }
async handleGroupMemberDraft() {
if (!this.checkExecute()) return;
const qrList = [
...this.settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnGroupMemberDraft)).flat(),
...(this.settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnGroupMemberDraft))?.flat() ?? []),
];
await this.performAutoExecute(qrList);
}
} }

View File

@ -30,6 +30,7 @@ export class QuickReply {
/**@type {Boolean}*/ executeOnUser = false; /**@type {Boolean}*/ executeOnUser = false;
/**@type {Boolean}*/ executeOnAi = false; /**@type {Boolean}*/ executeOnAi = false;
/**@type {Boolean}*/ executeOnChatChange = false; /**@type {Boolean}*/ executeOnChatChange = false;
/**@type {Boolean}*/ executeOnGroupMemberDraft = false;
/**@type {Function}*/ onExecute; /**@type {Function}*/ onExecute;
/**@type {Function}*/ onDelete; /**@type {Function}*/ onDelete;
@ -351,7 +352,13 @@ export class QuickReply {
this.executeOnChatChange = executeOnChatChange.checked; this.executeOnChatChange = executeOnChatChange.checked;
this.updateContext(); this.updateContext();
}); });
/**@type {HTMLInputElement}*/
const executeOnGroupMemberDraft = dom.querySelector('#qr--executeOnGroupMemberDraft');
executeOnGroupMemberDraft.checked = this.executeOnGroupMemberDraft;
executeOnGroupMemberDraft.addEventListener('click', ()=>{
this.executeOnGroupMemberDraft = executeOnGroupMemberDraft.checked;
this.updateContext();
});
/**@type {HTMLElement}*/ /**@type {HTMLElement}*/
const executeErrors = dom.querySelector('#qr--modal-executeErrors'); const executeErrors = dom.querySelector('#qr--modal-executeErrors');
@ -484,6 +491,7 @@ export class QuickReply {
executeOnUser: this.executeOnUser, executeOnUser: this.executeOnUser,
executeOnAi: this.executeOnAi, executeOnAi: this.executeOnAi,
executeOnChatChange: this.executeOnChatChange, executeOnChatChange: this.executeOnChatChange,
executeOnGroupMemberDraft: this.executeOnGroupMemberDraft,
}; };
} }
} }

View File

@ -36,6 +36,7 @@ export class SlashCommandHandler {
user - bool - auto execute on user message, e.g., user=true user - bool - auto execute on user message, e.g., user=true
bot - bool - auto execute on AI message, e.g., bot=true bot - bool - auto execute on AI message, e.g., bot=true
load - bool - auto execute on chat load, e.g., load=true load - bool - auto execute on chat load, e.g., load=true
group - bool - auto execute on group member selection, e.g., group=true
title - string - title / tooltip to be shown on button, e.g., title="My Fancy Button" title - string - title / tooltip to be shown on button, e.g., title="My Fancy Button"
`.trim(); `.trim();
const qrUpdateArgs = ` const qrUpdateArgs = `
@ -148,6 +149,7 @@ export class SlashCommandHandler {
executeOnUser: isTrueBoolean(args.user), executeOnUser: isTrueBoolean(args.user),
executeOnAi: isTrueBoolean(args.bot), executeOnAi: isTrueBoolean(args.bot),
executeOnChatChange: isTrueBoolean(args.load), executeOnChatChange: isTrueBoolean(args.load),
executeOnGroupMemberDraft: isTrueBoolean(args.group),
}, },
); );
} catch (ex) { } catch (ex) {
@ -168,6 +170,7 @@ export class SlashCommandHandler {
executeOnUser: args.user === undefined ? undefined : isTrueBoolean(args.user), executeOnUser: args.user === undefined ? undefined : isTrueBoolean(args.user),
executeOnAi: args.bot === undefined ? undefined : isTrueBoolean(args.bot), executeOnAi: args.bot === undefined ? undefined : isTrueBoolean(args.bot),
executeOnChatChange: args.load === undefined ? undefined : isTrueBoolean(args.load), executeOnChatChange: args.load === undefined ? undefined : isTrueBoolean(args.load),
executeOnGroupMemberDraft: args.group === undefined ? undefined : isTrueBoolean(args.group),
}, },
); );
} catch (ex) { } catch (ex) {

View File

@ -729,6 +729,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
const generateType = type == 'swipe' || type == 'impersonate' || type == 'quiet' || type == 'continue' ? type : 'group_chat'; const generateType = type == 'swipe' || type == 'impersonate' || type == 'quiet' || type == 'continue' ? type : 'group_chat';
setCharacterId(chId); setCharacterId(chId);
setCharacterName(characters[chId].name); setCharacterName(characters[chId].name);
await eventSource.emit(event_types.GROUP_MEMBER_DRAFTED, chId);
if (type !== 'swipe' && type !== 'impersonate' && !isStreamingEnabled()) { if (type !== 'swipe' && type !== 'impersonate' && !isStreamingEnabled()) {
// update indicator and scroll down // update indicator and scroll down