Add module assets
This commit is contained in:
@@ -19,16 +19,6 @@
|
|||||||
|
|
||||||
}).sort((a, b) => {
|
}).sort((a, b) => {
|
||||||
let score = a.name.toLowerCase().localeCompare(b.name.toLowerCase())
|
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
|
return score
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import TextInput from "src/lib/UI/GUI/TextInput.svelte";
|
import TextInput from "src/lib/UI/GUI/TextInput.svelte";
|
||||||
import LoreBookData from "src/lib/SideBars/LoreBook/LoreBookData.svelte";
|
import LoreBookData from "src/lib/SideBars/LoreBook/LoreBookData.svelte";
|
||||||
import type { RisuModule } from "src/ts/process/modules";
|
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 { alertConfirm } from "src/ts/alert";
|
||||||
import RegexList from "src/lib/SideBars/Scripts/RegexList.svelte";
|
import RegexList from "src/lib/SideBars/Scripts/RegexList.svelte";
|
||||||
import TriggerList from "src/lib/SideBars/Scripts/TriggerList.svelte";
|
import TriggerList from "src/lib/SideBars/Scripts/TriggerList.svelte";
|
||||||
@@ -11,65 +11,30 @@
|
|||||||
import Help from "src/lib/Others/Help.svelte";
|
import Help from "src/lib/Others/Help.svelte";
|
||||||
import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte";
|
import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte";
|
||||||
import Button from "src/lib/UI/GUI/Button.svelte";
|
import Button from "src/lib/UI/GUI/Button.svelte";
|
||||||
import { openURL } from "src/ts/storage/globalApi";
|
import { getFileSrc, openURL, saveAsset } from "src/ts/storage/globalApi";
|
||||||
import { hubURL } from "src/ts/characterCards";
|
import { hubURL } from "src/ts/characterCards";
|
||||||
import { exportRegex, importRegex } from "src/ts/process/scripts";
|
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
|
export let currentModule:RisuModule
|
||||||
|
let assetFileExtensions:string[] = []
|
||||||
|
let assetFilePath:string[] = []
|
||||||
|
|
||||||
|
$: {
|
||||||
async function toggleLorebook(){
|
if($DataBase.useAdditionalAssetsPreview){
|
||||||
if(!Array.isArray(currentModule.lorebook)){
|
if(currentModule?.assets){
|
||||||
currentModule.lorebook = []
|
for(let i = 0; i < currentModule.assets.length; i++){
|
||||||
}
|
if(currentModule.assets[i].length > 2 && currentModule.assets[i][2]) {
|
||||||
else if(currentModule.lorebook.length > 0){
|
assetFileExtensions[i] = currentModule.assets[i][2]
|
||||||
const conf = await alertConfirm(language.confirmRemoveModuleFeature)
|
} else
|
||||||
if(conf){
|
assetFileExtensions[i] = currentModule.assets[i][1].split('.').pop()
|
||||||
currentModule.lorebook = undefined
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,27 +82,52 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<span class="mt-4 text-xl">{language.basicInfo}</span>
|
<div class="flex w-full rounded-md border border-darkborderc mb-4 overflow-x-auto">
|
||||||
<TextInput bind:value={currentModule.name} className="mt-1" placeholder={language.name}/>
|
<button on:click={() => {
|
||||||
<TextInput bind:value={currentModule.description} className="mt-1" placeholder={language.description} size="sm"/>
|
submenu = 0
|
||||||
<span class="mt-6 text-xl">{language.moduleContent}</span>
|
}} class="p-2 flex-1 border-r border-darkborderc" class:bg-darkbutton={submenu === 0}>
|
||||||
<div class="grid grid-cols-2 border-selected border rounded-md">
|
<span>{language.basicInfo}</span>
|
||||||
<button class={(!Array.isArray(currentModule.lorebook)) ? 'p-4' : "p-4 bg-selected rounded-tl-md"} on:click={toggleLorebook}>
|
|
||||||
{language.loreBook}
|
|
||||||
</button>
|
</button>
|
||||||
<button class={(!Array.isArray(currentModule.regex)) ? 'p-4' : "p-4 bg-selected rounded-tr-md"} on:click={toggleRegex}>
|
<button on:click={() => {
|
||||||
{language.regexScript}
|
currentModule.lorebook ??= []
|
||||||
|
submenu = 1
|
||||||
|
}} class="p2 flex-1 border-r border-darkborderc" class:bg-darkbutton={submenu === 1}>
|
||||||
|
<span>{language.loreBook}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class={(!Array.isArray(currentModule.trigger)) ? 'p-4' : "p-4 bg-selected rounded-bl-md"} on:click={toggleTrigger}>
|
<button on:click={() => {
|
||||||
{language.triggerScript}
|
currentModule.regex ??= []
|
||||||
|
submenu = 2
|
||||||
|
}} class="p-2 flex-1 border-r border-darkborderc" class:bg-darkbutton={submenu === 2}>
|
||||||
|
<span>{language.regexScript}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class={(!Array.isArray(currentModule.trigger)) ? 'p-4' : "p-4 bg-selected rounded-bl-md"} on:click={toggleBackground}>
|
<button on:click={() => {
|
||||||
{language.backgroundHTML}
|
currentModule.trigger ??= []
|
||||||
|
submenu = 3
|
||||||
|
}} class="p-2 flex-1 border-r border-darkborderc" class:bg-darkbutton={submenu === 3}>
|
||||||
|
<span>{language.triggerScript}</span>
|
||||||
|
</button>
|
||||||
|
<button on:click={() => {
|
||||||
|
currentModule.backgroundEmbedding ??= ''
|
||||||
|
submenu = 4
|
||||||
|
}} class="p-2 flex-1 border-r border-darkborderc" class:bg-darkbutton={submenu === 4}>
|
||||||
|
<span>{language.backgroundHTML}</span>
|
||||||
|
</button>
|
||||||
|
<button on:click={() => {
|
||||||
|
currentModule.assets ??= []
|
||||||
|
submenu = 5
|
||||||
|
}} class="p-2 flex-1" class:bg-darkbutton={submenu === 5}>
|
||||||
|
<span>{language.additionalAssets}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if (Array.isArray(currentModule.lorebook))}
|
{#if submenu === 0}
|
||||||
<span class="mt-8 text-xl">{language.loreBook}</span>
|
<TextInput bind:value={currentModule.name} className="mt-1" placeholder={language.name}/>
|
||||||
|
<TextInput bind:value={currentModule.description} className="mt-1" placeholder={language.description} size="sm"/>
|
||||||
|
<div class="flex items-center mt-4">
|
||||||
|
<Check bind:check={currentModule.hideIcon} name={language.hideChatIcon}/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if submenu === 1 && (Array.isArray(currentModule.lorebook))}
|
||||||
<div class="border border-selected p-2 flex flex-col rounded-md mt-2">
|
<div class="border border-selected p-2 flex flex-col rounded-md mt-2">
|
||||||
{#each currentModule.lorebook as lore, i}
|
{#each currentModule.lorebook as lore, i}
|
||||||
<LoreBookData bind:value={currentModule.lorebook[i]} idx={i} onRemove={() => {
|
<LoreBookData bind:value={currentModule.lorebook[i]} idx={i} onRemove={() => {
|
||||||
@@ -151,8 +141,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if (Array.isArray(currentModule.regex))}
|
{#if submenu === 2 && (Array.isArray(currentModule.regex))}
|
||||||
<span class="mt-8 text-xl">{language.regexScript}</span>
|
|
||||||
<RegexList bind:value={currentModule.regex}/>
|
<RegexList bind:value={currentModule.regex}/>
|
||||||
<div class="text-textcolor2 mt-2 flex gap-2">
|
<div class="text-textcolor2 mt-2 flex gap-2">
|
||||||
<button class="font-medium cursor-pointer hover:text-green-500" on:click={() => {
|
<button class="font-medium cursor-pointer hover:text-green-500" on:click={() => {
|
||||||
@@ -167,13 +156,73 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if typeof(currentModule.backgroundEmbedding) === 'string'}
|
{#if submenu === 4 && typeof(currentModule.backgroundEmbedding) === 'string'}
|
||||||
<span class="mt-8 text-xl">{language.backgroundHTML}</span>
|
|
||||||
<TextAreaInput bind:value={currentModule.backgroundEmbedding} className="mt-2" placeholder={language.backgroundHTML} size="sm"/>
|
<TextAreaInput bind:value={currentModule.backgroundEmbedding} className="mt-2" placeholder={language.backgroundHTML} size="sm"/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if (Array.isArray(currentModule.trigger))}
|
{#if submenu === 5 && (Array.isArray(currentModule.assets))}
|
||||||
<span class="mt-8 text-xl">{language.triggerScript}</span>
|
<div class="w-full max-w-full border border-selected rounded-md p-2">
|
||||||
|
<table class="contain w-full max-w-full tabler mt-2">
|
||||||
|
<tr>
|
||||||
|
<th class="font-medium">{language.value}</th>
|
||||||
|
<th class="font-medium cursor-pointer w-10">
|
||||||
|
<button class="hover:text-green-500" on:click={async () => {
|
||||||
|
const da = await selectMultipleFile(['png', 'webp', 'mp4', 'mp3', 'gif'])
|
||||||
|
currentModule.assets = currentModule.assets ?? []
|
||||||
|
if(!da){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for(const f of da){
|
||||||
|
const img = f.data
|
||||||
|
const name = f.name
|
||||||
|
const extension = name.split('.').pop().toLowerCase()
|
||||||
|
const imgp = await saveAsset(img,'', extension)
|
||||||
|
currentModule.assets.push([name, imgp, extension])
|
||||||
|
currentModule.assets = currentModule.assets
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<PlusIcon />
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
{#if (!currentModule.assets) || currentModule.assets.length === 0}
|
||||||
|
<tr>
|
||||||
|
<div class="text-textcolor2"> No Assets</div>
|
||||||
|
</tr>
|
||||||
|
{:else}
|
||||||
|
{#each currentModule.assets as assets, i}
|
||||||
|
<tr>
|
||||||
|
<td class="font-medium truncate">
|
||||||
|
{#if assetFilePath[i] && $DataBase.useAdditionalAssetsPreview}
|
||||||
|
{#if assetFileExtensions[i] === 'mp4'}
|
||||||
|
<!-- svelte-ignore a11y-media-has-caption -->
|
||||||
|
<video controls class="mt-2 px-2 w-full m-1 rounded-md"><source src={assetFilePath[i]} type="video/mp4"></video>
|
||||||
|
{:else if assetFileExtensions[i] === 'mp3'}
|
||||||
|
<audio controls class="mt-2 px-2 w-full h-16 m-1 rounded-md" loop><source src={assetFilePath[i]} type="audio/mpeg"></audio>
|
||||||
|
{:else}
|
||||||
|
<img src={assetFilePath[i]} class="w-16 h-16 m-1 rounded-md" alt={assets[0]}/>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
<TextInput fullwidth size="sm" marginBottom bind:value={currentModule.assets[i][0]} placeholder="..." />
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<th class="font-medium cursor-pointer w-10">
|
||||||
|
<button class="hover:text-green-500" on:click={() => {
|
||||||
|
let additionalAssets = currentModule.assets
|
||||||
|
additionalAssets.splice(i, 1)
|
||||||
|
currentModule.assets = additionalAssets
|
||||||
|
}}>
|
||||||
|
<TrashIcon />
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if submenu === 3 && (Array.isArray(currentModule.trigger))}
|
||||||
<div class="flex items-start mt-2 gap-2">
|
<div class="flex items-start mt-2 gap-2">
|
||||||
<button class="bg-bgcolor py-1 rounded-md text-sm px-2" class:ring-1={
|
<button class="bg-bgcolor py-1 rounded-md text-sm px-2" class:ring-1={
|
||||||
currentModule?.trigger?.[0]?.effect?.[0]?.type !== 'triggercode' &&
|
currentModule?.trigger?.[0]?.effect?.[0]?.type !== 'triggercode' &&
|
||||||
@@ -228,7 +277,3 @@
|
|||||||
<span> <Help key="lowLevelAccess" name={language.lowLevelAccess}/></span>
|
<span> <Help key="lowLevelAccess" name={language.lowLevelAccess}/></span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
|
||||||
<Check bind:check={currentModule.hideIcon} name={language.hideChatIcon}/>
|
|
||||||
</div>
|
|
||||||
@@ -27,14 +27,6 @@
|
|||||||
|
|
||||||
}).sort((a, b) => {
|
}).sort((a, b) => {
|
||||||
let score = a.name.toLowerCase().localeCompare(b.name.toLowerCase())
|
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
|
return score
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { CurrentCharacter, CurrentChat, SizeStore, selectedCharID } from './stor
|
|||||||
import { calcString } from './process/infunctions';
|
import { calcString } from './process/infunctions';
|
||||||
import { findCharacterbyId, getPersonaPrompt, getUserIcon, getUserName, parseKeyValue, sfc32, sleep, uuidtoNumber } from './util';
|
import { findCharacterbyId, getPersonaPrompt, getUserIcon, getUserName, parseKeyValue, sfc32, sleep, uuidtoNumber } from './util';
|
||||||
import { getInlayImage, writeInlayImage } from './process/files/image';
|
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 { HypaProcesser } from './process/memory/hypamemory';
|
||||||
import { generateAIImage } from './process/stableDiff';
|
import { generateAIImage } from './process/stableDiff';
|
||||||
import { requestChatData } from './process/request';
|
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']
|
const videoExtention = ['mp4', 'webm', 'avi', 'm4p', 'm4v']
|
||||||
let needsSourceAccess = false
|
let needsSourceAccess = false
|
||||||
data = data.replaceAll(assetRegex, (full:string, type:string, name:string) => {
|
data = data.replaceAll(assetRegex, (full:string, type:string, name:string) => {
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { language } from "src/lang"
|
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 { 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 { get } from "svelte/store"
|
||||||
import { CurrentCharacter, CurrentChat } from "../stores"
|
import { CurrentCharacter, CurrentChat } from "../stores"
|
||||||
import { selectSingleFile } from "../util"
|
import { selectSingleFile, sleep } from "../util"
|
||||||
import { v4 } from "uuid"
|
import { v4 } from "uuid"
|
||||||
import { convertExternalLorebook } from "./lorebook"
|
import { convertExternalLorebook } from "./lorebook"
|
||||||
import { encode } from "msgpackr"
|
import { encode } from "msgpackr"
|
||||||
import { decodeRPack, encodeRPack } from "../rpack/rpack_bg"
|
import { decodeRPack, encodeRPack } from "../rpack/rpack_bg"
|
||||||
|
import { convertImage } from "../parser"
|
||||||
|
import { Capacitor } from "@capacitor/core"
|
||||||
|
|
||||||
export interface RisuModule{
|
export interface RisuModule{
|
||||||
name: string
|
name: string
|
||||||
@@ -21,15 +23,58 @@ export interface RisuModule{
|
|||||||
lowLevelAccess?: boolean
|
lowLevelAccess?: boolean
|
||||||
hideIcon?: boolean
|
hideIcon?: boolean
|
||||||
backgroundEmbedding?:string
|
backgroundEmbedding?:string
|
||||||
|
assets?:[string,string,string][]
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function exportModule(module:RisuModule){
|
export async function exportModule(module:RisuModule){
|
||||||
const dat = await encodeRPack(Buffer.from(JSON.stringify({
|
const apb = new AppendableBuffer()
|
||||||
...module,
|
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'
|
type: 'risuModule'
|
||||||
}, null, 2), 'utf-8'))
|
}, 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<assets.length;i++){
|
||||||
|
const asset = assets[i]
|
||||||
|
writeByte(1) //mark as asset
|
||||||
|
alertStore.set({
|
||||||
|
type: 'wait',
|
||||||
|
msg: `Loading... (Adding Assets ${i} / ${assets.length})`
|
||||||
|
})
|
||||||
|
let rData = await readImage(asset[1])
|
||||||
|
if(!rData){
|
||||||
|
rData = new Uint8Array(0) //blank buffer
|
||||||
|
}
|
||||||
|
let encoded = await encodeRPack(Buffer.from(await convertImage(rData)))
|
||||||
|
writeLength(encoded.length)
|
||||||
|
apb.append(encoded)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeByte(0) //end of file
|
||||||
|
|
||||||
|
await downloadFile(module.name + '.risum', apb.buffer)
|
||||||
alertNormal(language.successExport)
|
alertNormal(language.successExport)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,10 +85,89 @@ export async function importModule(){
|
|||||||
}
|
}
|
||||||
let fileData = f.data
|
let fileData = f.data
|
||||||
const db = get(DataBase)
|
const db = get(DataBase)
|
||||||
try {
|
|
||||||
if(f.name.endsWith('.risum')){
|
if(f.name.endsWith('.risum')){
|
||||||
fileData = Buffer.from(await decodeRPack(fileData))
|
try {
|
||||||
|
const buf = Buffer.from(fileData)
|
||||||
|
let pos = 0
|
||||||
|
|
||||||
|
const readLength = () => {
|
||||||
|
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())
|
const importData = JSON.parse(Buffer.from(fileData).toString())
|
||||||
if(importData.type === 'risuModule'){
|
if(importData.type === 'risuModule'){
|
||||||
if(
|
if(
|
||||||
@@ -155,6 +279,25 @@ export function getModuleLorebooks() {
|
|||||||
return lorebooks
|
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() {
|
export function getModuleTriggers() {
|
||||||
const currentChat = get(CurrentChat)
|
const currentChat = get(CurrentChat)
|
||||||
|
|||||||
@@ -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){
|
if(db.personas){
|
||||||
db.personas.map((v) => {
|
db.personas.map((v) => {
|
||||||
addUnparge(v.icon)
|
addUnparge(v.icon)
|
||||||
|
|||||||
Reference in New Issue
Block a user