[feat] apply yuso

This commit is contained in:
kwaroran
2023-07-24 20:55:43 +09:00
parent ca2096b4b8
commit 0d8dab3564
6 changed files with 103 additions and 133 deletions

View File

@@ -51,7 +51,8 @@
"tippy.js": "^6.3.7",
"uuid": "^9.0.0",
"wasmoon": "^1.15.0",
"web-streams-polyfill": "^3.2.1"
"web-streams-polyfill": "^3.2.1",
"yuso": "^0.1.1"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^2.4.2",

7
pnpm-lock.yaml generated
View File

@@ -119,6 +119,9 @@ dependencies:
web-streams-polyfill:
specifier: ^3.2.1
version: 3.2.1
yuso:
specifier: ^0.1.1
version: 0.1.1
devDependencies:
'@sveltejs/vite-plugin-svelte':
@@ -3091,3 +3094,7 @@ packages:
resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==}
engines: {node: '>= 14'}
dev: true
/yuso@0.1.1:
resolution: {integrity: sha512-GAPk64cRjlnIgDcMkpgRpydJqJcD41aLF5taY7AXm7JRcmSBaHMubFtgSsPf0oDtbDH5j/FIeVJyDtGFwXXv2Q==}
dev: false

View File

@@ -1,17 +1,15 @@
import { get, writable, type Writable } from "svelte/store"
import { alertConfirm, alertError, alertMd, alertNormal, alertSelect, alertStore, alertTOS } from "./alert"
import { DataBase, defaultSdDataFunc, type character, setDatabase, type customscript, type loreSettings, type loreBook } from "./storage/database"
import { checkNullish, selectMultipleFile, selectSingleFile, sleep } from "./util"
import { checkNullish, selectMultipleFile, sleep } from "./util"
import { language } from "src/lang"
import { encode as encodeMsgpack, decode as decodeMsgpack } from "msgpackr";
import { v4 as uuidv4 } from 'uuid';
import exifr from 'exifr'
import { PngMetadata } from "./exif"
import { characterFormatUpdate } from "./characters"
import { checkCharOrder, downloadFile, readImage, saveAsset } from "./storage/globalApi"
import { cloneDeep } from "lodash"
import { selectedCharID } from "./stores"
import { convertImage } from "./parser"
import * as yuso from 'yuso'
export const hubURL = "https://sv.risuai.xyz"
@@ -60,70 +58,23 @@ async function importCharacterProcess(f:{
})
await sleep(10)
const img = f.data
const readed = (await exifr.parse(img, true))
if(readed.chara){
// standard spec v2 imports
const charaData:CharacterCardV2 = JSON.parse(Buffer.from(readed.chara, 'base64').toString('utf-8'))
const readed = yuso.decode(img, 'chara')
{
const charaData:CharacterCardV2 = JSON.parse(Buffer.from(readed, 'base64').toString('utf-8'))
if(await importSpecv2(charaData, img)){
let db = get(DataBase)
return db.characters.length - 1
}
}
if(readed.risuai){
// old risu imports
await sleep(10)
const va = decodeMsgpack(Buffer.from(readed.risuai, 'base64')) as any
if(va.type !== 101){
alertError(language.errors.noData)
return
}
let char:character = va.data
let db = get(DataBase)
if(char.emotionImages && char.emotionImages.length > 0){
for(let i=0;i<char.emotionImages.length;i++){
alertStore.set({
type: 'wait',
msg: `Loading... (Getting Emotions ${i} / ${char.emotionImages.length})`
})
await sleep(10)
const imgp = await saveAsset(char.emotionImages[i][1] as any)
char.emotionImages[i][1] = imgp
}
}
char.chats = [{
message: [],
note: '',
name: 'Chat 1',
localLore: []
}]
if(checkNullish(char.sdData)){
char.sdData = defaultSdDataFunc()
}
char.chatPage = 0
char.image = await saveAsset(PngMetadata.filter(img))
db.characters.push(characterFormatUpdate(char))
char.chaId = uuidv4()
setDatabase(db)
alertNormal(language.importedCharacter)
return db.characters.length - 1
}
else if(readed.chara){
const charaData:OldTavernChar = JSON.parse(Buffer.from(readed.chara, 'base64').toString('utf-8'))
const imgp = await saveAsset(PngMetadata.filter(img))
const charaData:OldTavernChar = JSON.parse(Buffer.from(readed, 'base64').toString('utf-8'))
const imgp = await saveAsset(yuso.trim(img))
let db = get(DataBase)
db.characters.push(convertOldTavernAndJSON(charaData, imgp))
DataBase.set(db)
alertNormal(language.importedCharacter)
return db.characters.length - 1
}
else{
alertError(language.errors.noData)
return null
}
}
export const showRealmInfoStore:Writable<null|hubType> = writable(null)
@@ -170,18 +121,18 @@ export async function characterURLImport() {
})
const img = new Uint8Array(await chara.arrayBuffer())
const readed = (await exifr.parse(img, true))
const readed = (yuso.decode(img, "chara"))
{
const charaData:CharacterCardV2 = JSON.parse(Buffer.from(readed.chara, 'base64').toString('utf-8'))
const charaData:CharacterCardV2 = JSON.parse(Buffer.from(readed, 'base64').toString('utf-8'))
if(await importSpecv2(charaData, img)){
checkCharOrder()
return
}
}
{
const imgp = await saveAsset(PngMetadata.filter(img))
const imgp = await saveAsset(yuso.trim(img))
let db = get(DataBase)
const charaData:OldTavernChar = JSON.parse(Buffer.from(readed.chara, 'base64').toString('utf-8'))
const charaData:OldTavernChar = JSON.parse(Buffer.from(readed, 'base64').toString('utf-8'))
db.characters.push(convertOldTavernAndJSON(charaData, imgp))
DataBase.set(db)
@@ -268,7 +219,7 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|'
}
const data = card.data
const im = img ? await saveAsset(PngMetadata.filter(img)) : undefined
const im = img ? await saveAsset(yuso.trim(img)) : undefined
let db = get(DataBase)
const risuext = cloneDeep(data.extensions.risuai)
@@ -517,9 +468,8 @@ export async function exportSpecV2(char:character, type:'png'|'json' = 'png') {
})
await sleep(10)
img = PngMetadata.write(img, {
'chara': Buffer.from(JSON.stringify(card)).toString('base64'),
})
img = yuso.encode(img, "chara",Buffer.from(JSON.stringify(card)).toString('base64'))
alertStore.set({
type: 'wait',

View File

@@ -1,14 +1,13 @@
import { get, writable } from "svelte/store";
import { DataBase, saveImage, setDatabase, type character, type Chat, defaultSdDataFunc } from "./storage/database";
import exifr from 'exifr'
import { alertConfirm, alertError, alertNormal, alertSelect, alertStore } from "./alert";
import { language } from "../lang";
import { PngMetadata } from "./exif";
import { encode as encodeMsgpack, decode as decodeMsgpack } from "msgpackr";
import { checkNullish, findCharacterbyId, selectMultipleFile, selectSingleFile, sleep } from "./util";
import { v4 as uuidv4 } from 'uuid';
import { selectedCharID } from "./stores";
import { checkCharOrder, downloadFile, getFileSrc, readImage } from "./storage/globalApi";
import * as yuso from 'yuso'
export function createNewCharacter() {
let db = get(DataBase)
@@ -493,9 +492,9 @@ export async function addDefaultCharacters() {
for(const img of imgs){
const imgBuffer = await (await img).arrayBuffer()
const readed = (await exifr.parse(imgBuffer, true))
const readed = yuso.decode(Buffer.from(imgBuffer), "risuai")
await sleep(10)
const va = decodeMsgpack(Buffer.from(readed.risuai, 'base64')) as any
const va = decodeMsgpack(Buffer.from(readed,'base64')) as any
if(va.type !== 101){
alertError(language.errors.noData)
return
@@ -521,7 +520,7 @@ export async function addDefaultCharacters() {
}
char.chatPage = 0
char.image = await saveImage(PngMetadata.filter(Buffer.from(imgBuffer)))
char.image = await saveImage(yuso.trim(Buffer.from(imgBuffer)))
char.chaId = uuidv4()
db.characters.push(characterFormatUpdate(char))
setDatabase(db)

View File

@@ -1,57 +0,0 @@
import extract from 'png-chunks-extract';
import encode from 'png-chunks-encode';
import textKey from 'png-chunk-text'
export const PngMetadata = {
write: (pngBuffer: Uint8Array, metadata: Record<string, string>): Buffer => {
let chunks:{
name:string
data:Uint8Array
}[] = extract(Buffer.from(pngBuffer));
chunks = chunks.filter((v) => {
return v.name.toLocaleLowerCase() !== 'text'
})
for (const key in metadata) {
const value = metadata[key];
chunks.splice(-1, 0, textKey.encode(key, value))
}
const encoded = encode(chunks);
return encoded
},
writeStream:(pngBuffer: Uint8Array, metadata: Record<string, string>): Buffer => {
let chunks:{
name:string
data:Uint8Array
}[] = extract(Buffer.from(pngBuffer));
chunks = chunks.filter((v) => {
return v.name.toLocaleLowerCase() !== 'text'
})
for (const key in metadata) {
const value = metadata[key];
chunks.splice(-1, 0, textKey.encode(key, value))
}
const encoded = encode(chunks);
return encoded
},
filter: (pngBuffer: Uint8Array) => {
try {
let chunks:{
name:string
data:Uint8Array
}[] = extract(Buffer.from(pngBuffer));
chunks = chunks.filter((v) => {
return v.name.toLocaleLowerCase() !== 'text'
})
const encoded = encode(chunks);
return encoded
} catch (error) {
return pngBuffer
}
}
}

View File

@@ -0,0 +1,70 @@
// vite.config.ts
import { defineConfig } from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/vite@4.4.5_@types+node@18.16.19/node_modules/vite/dist/node/index.js";
import { svelte } from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/@sveltejs+vite-plugin-svelte@2.4.2_svelte@4.1.0_vite@4.4.5/node_modules/@sveltejs/vite-plugin-svelte/src/index.js";
import sveltePreprocess from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/svelte-preprocess@5.0.4_postcss@8.4.26_svelte@4.1.0_typescript@5.1.6/node_modules/svelte-preprocess/dist/index.js";
import wasm from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/vite-plugin-wasm@3.2.2_vite@4.4.5/node_modules/vite-plugin-wasm/exports/import.mjs";
import { internalIpV4 } from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/internal-ip@7.0.0/node_modules/internal-ip/index.js";
import topLevelAwait from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/vite-plugin-top-level-await@1.3.1_rollup@3.26.3_vite@4.4.5/node_modules/vite-plugin-top-level-await/exports/import.mjs";
var vite_config_default = defineConfig(async () => {
const host = await internalIpV4();
return {
plugins: [
svelte({
preprocess: [
sveltePreprocess({
typescript: true
})
],
onwarn: (warning, handler) => {
if (warning.code.startsWith("a11y-"))
return;
handler(warning);
}
}),
wasm(),
topLevelAwait()
],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
// prevent vite from obscuring rust errors
clearScreen: false,
// tauri expects a fixed port, fail if that port is not available
server: {
host: "0.0.0.0",
// listen on all addresses
port: 5174,
strictPort: true,
hmr: {
protocol: "ws",
host,
port: 5184
}
},
// to make use of `TAURI_DEBUG` and other env variables
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
envPrefix: ["VITE_", "TAURI_"],
build: {
// Tauri supports es2021
target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13",
// don't minify for debug builds
minify: process.env.TAURI_DEBUG ? false : "esbuild",
// produce sourcemaps for debug builds
sourcemap: !!process.env.TAURI_DEBUG,
chunkSizeWarningLimit: 2e3
},
optimizeDeps: {
needsInterop: [
"@mlc-ai/web-tokenizers"
]
},
resolve: {
alias: {
"src": "/src",
"modules": "/modules"
}
}
};
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFxibHVlYlxcXFxPbmVEcml2ZVxcXFxEb2N1bWVudHNcXFxcVlNDXFxcXF9SaXN1XFxcXGtha3VuYVxcXFxSaXN1QUlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkM6XFxcXFVzZXJzXFxcXGJsdWViXFxcXE9uZURyaXZlXFxcXERvY3VtZW50c1xcXFxWU0NcXFxcX1Jpc3VcXFxca2FrdW5hXFxcXFJpc3VBSVxcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vQzovVXNlcnMvYmx1ZWIvT25lRHJpdmUvRG9jdW1lbnRzL1ZTQy9fUmlzdS9rYWt1bmEvUmlzdUFJL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVcIjtcclxuaW1wb3J0IHsgc3ZlbHRlIH0gZnJvbSBcIkBzdmVsdGVqcy92aXRlLXBsdWdpbi1zdmVsdGVcIjtcclxuaW1wb3J0IHN2ZWx0ZVByZXByb2Nlc3MgZnJvbSBcInN2ZWx0ZS1wcmVwcm9jZXNzXCI7XHJcbmltcG9ydCB3YXNtIGZyb20gXCJ2aXRlLXBsdWdpbi13YXNtXCI7XHJcbmltcG9ydCB7IGludGVybmFsSXBWNCB9IGZyb20gJ2ludGVybmFsLWlwJ1xyXG5pbXBvcnQgdG9wTGV2ZWxBd2FpdCBmcm9tIFwidml0ZS1wbHVnaW4tdG9wLWxldmVsLWF3YWl0XCI7XHJcblxyXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoYXN5bmMgKCkgPT4ge1xyXG4gIFxyXG4gIGNvbnN0IGhvc3QgPSBhd2FpdCBpbnRlcm5hbElwVjQoKVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgcGx1Z2luczogW1xyXG4gICAgICBcclxuICAgICAgc3ZlbHRlKHtcclxuICAgICAgICBwcmVwcm9jZXNzOiBbXHJcbiAgICAgICAgICBzdmVsdGVQcmVwcm9jZXNzKHtcclxuICAgICAgICAgICAgdHlwZXNjcmlwdDogdHJ1ZSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgIF0sXHJcbiAgICAgICAgb253YXJuOiAod2FybmluZywgaGFuZGxlcikgPT4ge1xyXG4gICAgICAgICAgLy8gZGlzYWJsZSBhMTF5IHdhcm5pbmdzXHJcbiAgICAgICAgICBpZiAod2FybmluZy5jb2RlLnN0YXJ0c1dpdGgoXCJhMTF5LVwiKSkgcmV0dXJuO1xyXG4gICAgICAgICAgaGFuZGxlcih3YXJuaW5nKTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KSxcclxuICAgICAgd2FzbSgpLFxyXG4gICAgICB0b3BMZXZlbEF3YWl0KCksXHJcbiAgICBdLFxyXG5cclxuICAgIC8vIFZpdGUgb3B0aW9ucyB0YWlsb3JlZCBmb3IgVGF1cmkgZGV2ZWxvcG1lbnQgYW5kIG9ubHkgYXBwbGllZCBpbiBgdGF1cmkgZGV2YCBvciBgdGF1cmkgYnVpbGRgXHJcbiAgICAvLyBwcmV2ZW50IHZpdGUgZnJvbSBvYnNjdXJpbmcgcnVzdCBlcnJvcnNcclxuICAgIGNsZWFyU2NyZWVuOiBmYWxzZSxcclxuICAgIC8vIHRhdXJpIGV4cGVjdHMgYSBmaXhlZCBwb3J0LCBmYWlsIGlmIHRoYXQgcG9ydCBpcyBub3QgYXZhaWxhYmxlXHJcbiAgICBzZXJ2ZXI6IHtcclxuICAgICAgaG9zdDogJzAuMC4wLjAnLCAvLyBsaXN0ZW4gb24gYWxsIGFkZHJlc3Nlc1xyXG4gICAgICBwb3J0OiA1MTc0LFxyXG4gICAgICBzdHJpY3RQb3J0OiB0cnVlLFxyXG4gICAgICBobXI6IHtcclxuICAgICAgICBwcm90b2NvbDogJ3dzJyxcclxuICAgICAgICBob3N0LFxyXG4gICAgICAgIHBvcnQ6IDUxODQsXHJcbiAgICAgIH0sXHJcbiAgICB9LFxyXG4gICAgLy8gdG8gbWFrZSB1c2Ugb2YgYFRBVVJJX0RFQlVHYCBhbmQgb3RoZXIgZW52IHZhcmlhYmxlc1xyXG4gICAgLy8gaHR0cHM6Ly90YXVyaS5zdHVkaW8vdjEvYXBpL2NvbmZpZyNidWlsZGNvbmZpZy5iZWZvcmVkZXZjb21tYW5kXHJcbiAgICBlbnZQcmVmaXg6IFtcIlZJVEVfXCIsIFwiVEFVUklfXCJdLFxyXG4gICAgYnVpbGQ6IHtcclxuICAgICAgLy8gVGF1cmkgc3VwcG9ydHMgZXMyMDIxXHJcbiAgICAgIHRhcmdldDogcHJvY2Vzcy5lbnYuVEFVUklfUExBVEZPUk0gPT0gXCJ3aW5kb3dzXCIgPyBcImNocm9tZTEwNVwiIDogXCJzYWZhcmkxM1wiLFxyXG4gICAgICAvLyBkb24ndCBtaW5pZnkgZm9yIGRlYnVnIGJ1aWxkc1xyXG4gICAgICBtaW5pZnk6IHByb2Nlc3MuZW52LlRBVVJJX0RFQlVHID8gZmFsc2UgOiAnZXNidWlsZCcsXHJcbiAgICAgIC8vIHByb2R1Y2Ugc291cmNlbWFwcyBmb3IgZGVidWcgYnVpbGRzXHJcbiAgICAgIHNvdXJjZW1hcDogISFwcm9jZXNzLmVudi5UQVVSSV9ERUJVRyxcclxuICAgICAgY2h1bmtTaXplV2FybmluZ0xpbWl0OiAyMDAwXHJcbiAgICB9LFxyXG4gICAgXHJcbiAgICBvcHRpbWl6ZURlcHM6e1xyXG4gICAgICBuZWVkc0ludGVyb3A6W1xyXG4gICAgICAgIFwiQG1sYy1haS93ZWItdG9rZW5pemVyc1wiXHJcbiAgICAgIF1cclxuICAgIH0sXHJcblxyXG4gICAgcmVzb2x2ZTp7XHJcbiAgICAgIGFsaWFzOntcclxuICAgICAgICAnc3JjJzonL3NyYycsXHJcbiAgICAgICAgJ21vZHVsZXMnOiAnL21vZHVsZXMnXHJcbiAgICAgIH1cclxuICAgIH1cclxufX0pO1xyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQStXLFNBQVMsb0JBQW9CO0FBQzVZLFNBQVMsY0FBYztBQUN2QixPQUFPLHNCQUFzQjtBQUM3QixPQUFPLFVBQVU7QUFDakIsU0FBUyxvQkFBb0I7QUFDN0IsT0FBTyxtQkFBbUI7QUFHMUIsSUFBTyxzQkFBUSxhQUFhLFlBQVk7QUFFdEMsUUFBTSxPQUFPLE1BQU0sYUFBYTtBQUVoQyxTQUFPO0FBQUEsSUFDTCxTQUFTO0FBQUEsTUFFUCxPQUFPO0FBQUEsUUFDTCxZQUFZO0FBQUEsVUFDVixpQkFBaUI7QUFBQSxZQUNmLFlBQVk7QUFBQSxVQUNkLENBQUM7QUFBQSxRQUNIO0FBQUEsUUFDQSxRQUFRLENBQUMsU0FBUyxZQUFZO0FBRTVCLGNBQUksUUFBUSxLQUFLLFdBQVcsT0FBTztBQUFHO0FBQ3RDLGtCQUFRLE9BQU87QUFBQSxRQUNqQjtBQUFBLE1BQ0YsQ0FBQztBQUFBLE1BQ0QsS0FBSztBQUFBLE1BQ0wsY0FBYztBQUFBLElBQ2hCO0FBQUE7QUFBQTtBQUFBLElBSUEsYUFBYTtBQUFBO0FBQUEsSUFFYixRQUFRO0FBQUEsTUFDTixNQUFNO0FBQUE7QUFBQSxNQUNOLE1BQU07QUFBQSxNQUNOLFlBQVk7QUFBQSxNQUNaLEtBQUs7QUFBQSxRQUNILFVBQVU7QUFBQSxRQUNWO0FBQUEsUUFDQSxNQUFNO0FBQUEsTUFDUjtBQUFBLElBQ0Y7QUFBQTtBQUFBO0FBQUEsSUFHQSxXQUFXLENBQUMsU0FBUyxRQUFRO0FBQUEsSUFDN0IsT0FBTztBQUFBO0FBQUEsTUFFTCxRQUFRLFFBQVEsSUFBSSxrQkFBa0IsWUFBWSxjQUFjO0FBQUE7QUFBQSxNQUVoRSxRQUFRLFFBQVEsSUFBSSxjQUFjLFFBQVE7QUFBQTtBQUFBLE1BRTFDLFdBQVcsQ0FBQyxDQUFDLFFBQVEsSUFBSTtBQUFBLE1BQ3pCLHVCQUF1QjtBQUFBLElBQ3pCO0FBQUEsSUFFQSxjQUFhO0FBQUEsTUFDWCxjQUFhO0FBQUEsUUFDWDtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsSUFFQSxTQUFRO0FBQUEsTUFDTixPQUFNO0FBQUEsUUFDSixPQUFNO0FBQUEsUUFDTixXQUFXO0FBQUEsTUFDYjtBQUFBLElBQ0Y7QUFBQSxFQUNKO0FBQUMsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K