From 8bbdf06a5565650448d827460f5e92cd9af6e2e2 Mon Sep 17 00:00:00 2001 From: kwaroran Date: Tue, 27 Aug 2024 22:02:55 +0900 Subject: [PATCH] Add module assets --- .../Pages/Module/ModuleChatMenu.svelte | 10 - .../Setting/Pages/Module/ModuleMenu.svelte | 215 +++++++++++------- .../Pages/Module/ModuleSettings.svelte | 8 - src/ts/parser.ts | 12 +- src/ts/process/modules.ts | 161 ++++++++++++- src/ts/storage/globalApi.ts | 11 + 6 files changed, 304 insertions(+), 113 deletions(-) diff --git a/src/lib/Setting/Pages/Module/ModuleChatMenu.svelte b/src/lib/Setting/Pages/Module/ModuleChatMenu.svelte index dd72ef60..89ad0c7e 100644 --- a/src/lib/Setting/Pages/Module/ModuleChatMenu.svelte +++ b/src/lib/Setting/Pages/Module/ModuleChatMenu.svelte @@ -19,16 +19,6 @@ }).sort((a, b) => { let score = a.name.toLowerCase().localeCompare(b.name.toLowerCase()) - - if(!alertMode){ - if(db.enabledModules.includes(a.id)){ - score += 1000 - } - if(db.enabledModules.includes(b.id)){ - score -= 1000 - } - } - return score }) } diff --git a/src/lib/Setting/Pages/Module/ModuleMenu.svelte b/src/lib/Setting/Pages/Module/ModuleMenu.svelte index 6cfab131..2f022c4a 100644 --- a/src/lib/Setting/Pages/Module/ModuleMenu.svelte +++ b/src/lib/Setting/Pages/Module/ModuleMenu.svelte @@ -3,74 +3,39 @@ import TextInput from "src/lib/UI/GUI/TextInput.svelte"; import LoreBookData from "src/lib/SideBars/LoreBook/LoreBookData.svelte"; import type { RisuModule } from "src/ts/process/modules"; - import { DownloadIcon, FolderUpIcon, PlusIcon } from "lucide-svelte"; + import { DownloadIcon, FolderUpIcon, PlusIcon, TrashIcon } from "lucide-svelte"; import { alertConfirm } from "src/ts/alert"; import RegexList from "src/lib/SideBars/Scripts/RegexList.svelte"; import TriggerList from "src/lib/SideBars/Scripts/TriggerList.svelte"; import Check from "src/lib/UI/GUI/CheckInput.svelte"; - import Help from "src/lib/Others/Help.svelte"; - import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte"; - import Button from "src/lib/UI/GUI/Button.svelte"; - import { openURL } from "src/ts/storage/globalApi"; - import { hubURL } from "src/ts/characterCards"; - import { exportRegex, importRegex } from "src/ts/process/scripts"; - + import Help from "src/lib/Others/Help.svelte"; + import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte"; + import Button from "src/lib/UI/GUI/Button.svelte"; + import { getFileSrc, openURL, saveAsset } from "src/ts/storage/globalApi"; + import { hubURL } from "src/ts/characterCards"; + import { exportRegex, importRegex } from "src/ts/process/scripts"; + import { selectMultipleFile } from "src/ts/util"; + import { DataBase } from 'src/ts/storage/database'; + let submenu = 0 export let currentModule:RisuModule + let assetFileExtensions:string[] = [] + let assetFilePath:string[] = [] - - async function toggleLorebook(){ - if(!Array.isArray(currentModule.lorebook)){ - currentModule.lorebook = [] - } - else if(currentModule.lorebook.length > 0){ - const conf = await alertConfirm(language.confirmRemoveModuleFeature) - if(conf){ - currentModule.lorebook = undefined + $: { + if($DataBase.useAdditionalAssetsPreview){ + if(currentModule?.assets){ + for(let i = 0; i < currentModule.assets.length; i++){ + if(currentModule.assets[i].length > 2 && currentModule.assets[i][2]) { + assetFileExtensions[i] = currentModule.assets[i][2] + } else + assetFileExtensions[i] = currentModule.assets[i][1].split('.').pop() + getFileSrc(currentModule.assets[i][1]).then((filePath) => { + assetFilePath[i] = filePath + }) + } } } - else{ - currentModule.lorebook = undefined - } - } - - async function toggleRegex(){ - if(!Array.isArray(currentModule.regex)){ - currentModule.regex = [] - } - else if(currentModule.regex.length > 0){ - const conf = await alertConfirm(language.confirmRemoveModuleFeature) - if(conf){ - currentModule.regex = undefined - } - } - else{ - currentModule.regex = undefined - } - } - - async function toggleTrigger(){ - if(!Array.isArray(currentModule.trigger)){ - currentModule.trigger = [] - } - else if(currentModule.trigger.length > 0){ - const conf = await alertConfirm(language.confirmRemoveModuleFeature) - if(conf){ - currentModule.trigger = undefined - } - } - else{ - currentModule.trigger = undefined - } - } - - function toggleBackground(){ - if(typeof(currentModule.backgroundEmbedding) !== 'string'){ - currentModule.backgroundEmbedding = '' - } - else{ - currentModule.backgroundEmbedding = undefined - } } function addLorebook(){ @@ -117,27 +82,52 @@ } -{language.basicInfo} - - -{language.moduleContent} -
- - - - + +
-{#if (Array.isArray(currentModule.lorebook))} - {language.loreBook} +{#if submenu === 0} + + +
+ +
+{/if} +{#if submenu === 1 && (Array.isArray(currentModule.lorebook))}
{#each currentModule.lorebook as lore, i} { @@ -151,8 +141,7 @@ {/if} -{#if (Array.isArray(currentModule.regex))} - {language.regexScript} +{#if submenu === 2 && (Array.isArray(currentModule.regex))}
{/if} -{#if typeof(currentModule.backgroundEmbedding) === 'string'} - {language.backgroundHTML} +{#if submenu === 4 && typeof(currentModule.backgroundEmbedding) === 'string'} {/if} -{#if (Array.isArray(currentModule.trigger))} - {language.triggerScript} +{#if submenu === 5 && (Array.isArray(currentModule.assets))} +
+ + + + + + {#if (!currentModule.assets) || currentModule.assets.length === 0} + +
No Assets
+ + {:else} + {#each currentModule.assets as assets, i} + + + + + + {/each} + {/if} +
{language.value} + +
+ {#if assetFilePath[i] && $DataBase.useAdditionalAssetsPreview} + {#if assetFileExtensions[i] === 'mp4'} + + + {:else if assetFileExtensions[i] === 'mp3'} + + {:else} + {assets[0]}/ + {/if} + {/if} + + + +
+
+{/if} + +{#if submenu === 3 && (Array.isArray(currentModule.trigger))}
-{/if} - -
- -
\ No newline at end of file +{/if} \ No newline at end of file diff --git a/src/lib/Setting/Pages/Module/ModuleSettings.svelte b/src/lib/Setting/Pages/Module/ModuleSettings.svelte index 74e80420..f9186613 100644 --- a/src/lib/Setting/Pages/Module/ModuleSettings.svelte +++ b/src/lib/Setting/Pages/Module/ModuleSettings.svelte @@ -27,14 +27,6 @@ }).sort((a, b) => { let score = a.name.toLowerCase().localeCompare(b.name.toLowerCase()) - - if(db.enabledModules.includes(a.id)){ - score += 1000 - } - if(db.enabledModules.includes(b.id)){ - score -= 1000 - } - return score }) } diff --git a/src/ts/parser.ts b/src/ts/parser.ts index 86907784..47f4860e 100644 --- a/src/ts/parser.ts +++ b/src/ts/parser.ts @@ -9,7 +9,7 @@ import { CurrentCharacter, CurrentChat, SizeStore, selectedCharID } from './stor import { calcString } from './process/infunctions'; import { findCharacterbyId, getPersonaPrompt, getUserIcon, getUserName, parseKeyValue, sfc32, sleep, uuidtoNumber } from './util'; import { getInlayImage, writeInlayImage } from './process/files/image'; -import { getModuleLorebooks } from './process/modules'; +import { getModuleAssets, getModuleLorebooks } from './process/modules'; import { HypaProcesser } from './process/memory/hypamemory'; import { generateAIImage } from './process/stableDiff'; import { requestChatData } from './process/request'; @@ -281,6 +281,16 @@ async function parseAdditionalAssets(data:string, char:simpleCharacterArgument|c } } } + const moduleAssets = getModuleAssets() + if(moduleAssets.length > 0){ + for(const asset of moduleAssets){ + const assetPath = await getFileSrc(asset[1]) + assetPaths[asset[0].toLocaleLowerCase()] = { + path: assetPath, + ext: asset[2] + } + } + } const videoExtention = ['mp4', 'webm', 'avi', 'm4p', 'm4v'] let needsSourceAccess = false data = data.replaceAll(assetRegex, (full:string, type:string, name:string) => { diff --git a/src/ts/process/modules.ts b/src/ts/process/modules.ts index 37ea7165..c366df6b 100644 --- a/src/ts/process/modules.ts +++ b/src/ts/process/modules.ts @@ -1,14 +1,16 @@ import { language } from "src/lang" -import { alertConfirm, alertError, alertModuleSelect, alertNormal } from "../alert" +import { alertConfirm, alertError, alertModuleSelect, alertNormal, alertStore } from "../alert" import { DataBase, setDatabase, type customscript, type loreBook, type triggerscript } from "../storage/database" -import { downloadFile } from "../storage/globalApi" +import { AppendableBuffer, downloadFile, isNodeServer, isTauri, readImage, saveAsset } from "../storage/globalApi" import { get } from "svelte/store" import { CurrentCharacter, CurrentChat } from "../stores" -import { selectSingleFile } from "../util" +import { selectSingleFile, sleep } from "../util" import { v4 } from "uuid" import { convertExternalLorebook } from "./lorebook" import { encode } from "msgpackr" import { decodeRPack, encodeRPack } from "../rpack/rpack_bg" +import { convertImage } from "../parser" +import { Capacitor } from "@capacitor/core" export interface RisuModule{ name: string @@ -21,15 +23,58 @@ export interface RisuModule{ lowLevelAccess?: boolean hideIcon?: boolean backgroundEmbedding?:string + assets?:[string,string,string][] } export async function exportModule(module:RisuModule){ - const dat = await encodeRPack(Buffer.from(JSON.stringify({ - ...module, + const apb = new AppendableBuffer() + const writeLength = (len:number) => { + const lenbuf = Buffer.alloc(4) + lenbuf.writeUInt32LE(len, 0) + apb.append(lenbuf) + } + const writeByte = (byte:number) => { + //byte is 0-255 + const buf = Buffer.alloc(1) + buf.writeUInt8(byte, 0) + apb.append(buf) + } + + const assets = module.assets ?? [] + module = structuredClone(module) + module.assets = module.assets.map((asset) => { + return [asset[0], '', asset[2]] as [string,string,string] + }) + + const mainbuf = await encodeRPack(Buffer.from(JSON.stringify({ + module: module, type: 'risuModule' }, null, 2), 'utf-8')) - await downloadFile(module.name + '.risum', dat) + writeByte(111) //magic number + writeByte(0) //version + writeLength(mainbuf.length) + apb.append(mainbuf) + + for(let i=0;i { + const len = buf.readUInt32LE(pos) + pos += 4 + return len + } + const readByte = () => { + const byte = buf.readUInt8(pos) + pos += 1 + return byte + } + const readData = (len:number) => { + const data = buf.subarray(pos, pos + len) + pos += len + return data + } + + if(readByte() !== 111){ + console.error("Invalid magic number") + alertError(language.errors.noData) + return + } + if(readByte() !== 0){ //Version check + console.error("Invalid version") + alertError(language.errors.noData) + return + } + + const mainLen = readLength() + const mainData = readData(mainLen) + const main:{ + type:'risuModule' + module:RisuModule + } = JSON.parse(Buffer.from(await decodeRPack(mainData)).toString()) + + if(main.type !== 'risuModule'){ + console.error("Invalid module type") + alertError(language.errors.noData) + return + } + + let module = main.module + + let i = 0 + while(true){ + const mark = readByte() + if(mark === 0){ + break + } + if(mark !== 1){ + alertError(language.errors.noData) + return + } + const len = readLength() + const data = readData(len) + module.assets[i][1] = await saveAsset(Buffer.from(await decodeRPack(data))) + alertStore.set({ + type: 'wait', + msg: `Loading... (Adding Assets ${i} / ${module.assets.length})` + }) + if(!isTauri && !Capacitor.isNativePlatform() &&!isNodeServer){ + await sleep(100) + } + i++ + } + alertStore.set({ + type: 'none', + msg: '' + }) + + db.modules.push(module) + setDatabase(db) + return + } catch (error) { + console.error(error) + alertError(language.errors.noData) } + } + try { const importData = JSON.parse(Buffer.from(fileData).toString()) if(importData.type === 'risuModule'){ if( @@ -155,6 +279,25 @@ export function getModuleLorebooks() { return lorebooks } +export function getModuleAssets() { + const currentChat = get(CurrentChat) + const db = get(DataBase) + if (!currentChat) return [] + let moduleIds = currentChat.modules ?? [] + moduleIds = moduleIds.concat(db.enabledModules) + const modules = getModules(moduleIds) + let assets: [string,string,string][] = [] + for (const module of modules) { + if(!module){ + continue + } + if (module.assets) { + assets = assets.concat(module.assets) + } + } + return assets +} + export function getModuleTriggers() { const currentChat = get(CurrentChat) diff --git a/src/ts/storage/globalApi.ts b/src/ts/storage/globalApi.ts index 1c0c85a5..20c37e1c 100644 --- a/src/ts/storage/globalApi.ts +++ b/src/ts/storage/globalApi.ts @@ -847,6 +847,17 @@ export function getUnpargeables(db:Database, uptype:'basename'|'pure' = 'basenam } } + if(db.modules){ + for(const module of db.modules){ + const assets = module.assets + if(assets){ + for(const asset of assets){ + addUnparge(asset[1]) + } + } + } + } + if(db.personas){ db.personas.map((v) => { addUnparge(v.icon)