{#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))}
+
+
+
+ | {language.value} |
+
+
+ |
+
+ {#if (!currentModule.assets) || currentModule.assets.length === 0}
+
+ No Assets
+
+ {:else}
+ {#each currentModule.assets as assets, i}
+
+
+ {#if assetFilePath[i] && $DataBase.useAdditionalAssetsPreview}
+ {#if assetFileExtensions[i] === 'mp4'}
+
+
+ {:else if assetFileExtensions[i] === 'mp3'}
+
+ {:else}
+
+ {/if}
+ {/if}
+
+ |
+
+
+
+ |
+
+ {/each}
+ {/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)