import { get } from "svelte/store"; import { CharEmotion, selectedCharID } from "../stores"; import { DataBase, setDatabase, type character, type customscript, type groupChat, type Database } from "../storage/database"; import { downloadFile } from "../storage/globalApi"; import { alertError, alertNormal } from "../alert"; import { language } from "src/lang"; import { selectSingleFile } from "../util"; import { risuChatParser as risuChatParserOrg, type simpleCharacterArgument } from "../parser"; import { autoMarkPlugin } from "../plugins/automark"; import { runCharacterJS } from "../plugins/embedscript"; import { metricaPlugin } from "../plugins/metrica"; import { OaiFixKorean } from "../plugins/fixer"; const dreg = /{{data}}/g const randomness = /\|\|\|/g export type ScriptMode = 'editinput'|'editoutput'|'editprocess'|'editdisplay' export async function processScript(char:character|groupChat, data:string, mode:ScriptMode){ return (await processScriptFull(char, data, mode)).data } export function exportRegex(){ let db = get(DataBase) const script = db.globalscript const data = Buffer.from(JSON.stringify({ type: 'regex', data: script }), 'utf-8') downloadFile(`regexscript_export.json`,data) alertNormal(language.successExport) } export async function importRegex(){ const filedata = (await selectSingleFile(['json'])).data if(!filedata){ return } let db = get(DataBase) try { const imported= JSON.parse(Buffer.from(filedata).toString('utf-8')) if(imported.type === 'regex' && imported.data){ const datas:customscript[] = imported.data const script = db.globalscript for(const data of datas){ script.push(data) } db.globalscript = script setDatabase(db) } else{ alertError("File invaid or corrupted") } } catch (error) { alertError(`${error}`) } } export async function processScriptFull(char:character|groupChat|simpleCharacterArgument, data:string, mode:ScriptMode, chatID = -1){ let db = get(DataBase) let emoChanged = false const scripts = (db.globalscript ?? []).concat(char.customscript) if(db.officialplugins.automark && mode === 'editdisplay'){ data = autoMarkPlugin(data) } if(db.officialplugins.metrica && mode === 'editdisplay'){ data = metricaPlugin(data, 'metrics') } if(db.officialplugins.metrica && (mode === 'editinput' || mode === 'editoutput' || mode === 'editprocess')){ data = metricaPlugin(data, 'imperial') } if(db.officialplugins.oaiFixLetters && db.officialplugins.oaiFix && (mode === 'editoutput' || mode === 'editdisplay')){ data = OaiFixKorean(data) } data = await runCharacterJS({ code: char.virtualscript ?? null, mode, data, }) if(scripts.length === 0){ return {data, emoChanged} } for (const script of scripts){ if(script.type === mode){ const reg = new RegExp(script.in, script.ableFlag ? script.flag : 'g') let outScript2 = script.out.replaceAll("$n", "\n") let outScript = risuChatParser(outScript2.replace(dreg, "$&"), {chatID: chatID, db:db}) if(outScript.startsWith('@@')){ if(reg.test(data)){ if(outScript.startsWith('@@emo ')){ const emoName = script.out.substring(6).trim() let charemotions = get(CharEmotion) let tempEmotion = charemotions[char.chaId] if(!tempEmotion){ tempEmotion = [] } if(tempEmotion.length > 4){ tempEmotion.splice(0, 1) } if(char.type !== 'simple'){ for(const emo of char.emotionImages){ if(emo[0] === emoName){ const emos:[string, string,number] = [emo[0], emo[1], Date.now()] tempEmotion.push(emos) charemotions[char.chaId] = tempEmotion CharEmotion.set(charemotions) emoChanged = true break } } } } if(outScript.startsWith('@@inject') && chatID !== -1){ const selchar = db.characters[get(selectedCharID)] selchar.chats[selchar.chatPage].message[chatID].data = data data = data.replace(reg, "") } } else{ if(outScript.startsWith('@@repeat_back') && chatID !== -1){ const v = outScript.split(' ', 2)[1] const selchar = db.characters[get(selectedCharID)] const chat = selchar.chats[selchar.chatPage] let lastChat = selchar.firstMsgIndex === -1 ? selchar.firstMessage : selchar.alternateGreetings[selchar.firstMsgIndex] let pointer = chatID - 1 while(pointer >= 0){ if(chat.message[pointer].role === chat.message[chatID].role){ lastChat = chat.message[pointer].data break } pointer-- } const r = lastChat.match(reg) if(!v){ data = data + r[0] } else if(r[0]){ switch(v){ case 'end': data = data + r[0] break case 'start': data = r[0] + data break case 'end_nl': data = data + "\n" + r[0] break case 'start_nl': data = r[0] + "\n" + data break } } } } } else{ data = data.replace(reg, outScript) } } } return {data, emoChanged} } const rgx = /(?:{{|<)(.+?)(?:}}|>)/gm export const risuChatParser = risuChatParserOrg