Merge branch 'main' of https://github.com/kwaroran/RisuAI
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { get } from "svelte/store"
|
||||
import { get, writable } from "svelte/store"
|
||||
import { DataBase } from "./database"
|
||||
import { hubURL } from "../characterCards"
|
||||
import localforage from "localforage"
|
||||
@@ -7,6 +7,10 @@ import { forageStorage, getUnpargeables, replaceDbResources } from "./globalApi"
|
||||
import { encodeRisuSave } from "./risuSave"
|
||||
import { v4 } from "uuid"
|
||||
|
||||
export const AccountWarning = writable('')
|
||||
|
||||
let seenWarnings:string[] = []
|
||||
|
||||
export class AccountStorage{
|
||||
auth:string
|
||||
usingSync:boolean
|
||||
@@ -25,10 +29,23 @@ export class AccountStorage{
|
||||
'X-Format': 'nocheck'
|
||||
}
|
||||
})
|
||||
if(da.headers.get('Content-Type') === 'application/json'){
|
||||
const json = (await da.json())
|
||||
if(json?.warning){
|
||||
if(!seenWarnings.includes(json.warning)){
|
||||
seenWarnings.push(json.warning)
|
||||
AccountWarning.set(json.warning)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(da.status === 304){
|
||||
return key
|
||||
}
|
||||
if(da.status === 403){
|
||||
if(da.headers.get('x-risu-status') === 'warn'){
|
||||
return
|
||||
}
|
||||
localStorage.setItem("fallbackRisuToken",await alertLogin())
|
||||
this.checkAuth()
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export const DataBase = writable({} as any as Database)
|
||||
export const loadedStore = writable(false)
|
||||
export let appVer = "122.1.2"
|
||||
export let webAppSubVer = ''
|
||||
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { checkNullish, decryptBuffer, encryptBuffer, selectSingleFile } from '../util';
|
||||
import { changeLanguage, language } from '../../lang';
|
||||
@@ -12,11 +17,6 @@ import { defaultColorScheme, type ColorScheme } from '../gui/colorscheme';
|
||||
import type { PromptItem, PromptSettings } from '../process/prompt';
|
||||
import type { OobaChatCompletionRequestParams } from '../model/ooba';
|
||||
|
||||
export const DataBase = writable({} as any as Database)
|
||||
export const loadedStore = writable(false)
|
||||
export let appVer = "115.0.1"
|
||||
export let webAppSubVer = ''
|
||||
|
||||
export function setDatabase(data:Database){
|
||||
if(checkNullish(data.characters)){
|
||||
data.characters = []
|
||||
@@ -419,6 +419,16 @@ export function setDatabase(data:Database){
|
||||
data.stabilityModel ??= 'sd3-large'
|
||||
data.stabllityStyle ??= ''
|
||||
data.legacyTranslation ??= false
|
||||
data.comfyUiUrl ??= 'http://localhost:8188'
|
||||
data.comfyConfig ??= {
|
||||
workflow: '',
|
||||
posNodeID: '',
|
||||
posInputName: 'text',
|
||||
negNodeID: '',
|
||||
negInputName: 'text',
|
||||
timeout: 30
|
||||
}
|
||||
|
||||
changeLanguage(data.language)
|
||||
DataBase.set(data)
|
||||
}
|
||||
@@ -585,6 +595,7 @@ export interface Database{
|
||||
name:string
|
||||
icon:string
|
||||
largePortrait?:boolean
|
||||
id?:string
|
||||
}[]
|
||||
assetWidth:number
|
||||
animationSpeed:number
|
||||
@@ -695,6 +706,8 @@ export interface Database{
|
||||
stabilityKey: string
|
||||
stabllityStyle: string
|
||||
legacyTranslation: boolean
|
||||
comfyConfig: ComfyConfig
|
||||
comfyUiUrl: string
|
||||
}
|
||||
|
||||
export interface customscript{
|
||||
@@ -826,6 +839,7 @@ export interface character{
|
||||
}>
|
||||
defaultVariables?:string
|
||||
lowLevelAccess?:boolean
|
||||
hideChatIcon?:boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -873,6 +887,7 @@ export interface groupChat{
|
||||
nickname?:string
|
||||
defaultVariables?:string
|
||||
lowLevelAccess?:boolean
|
||||
hideChatIcon?:boolean
|
||||
}
|
||||
|
||||
export interface botPreset{
|
||||
@@ -965,6 +980,16 @@ interface NAIImgConfig{
|
||||
InfoExtracted:number,
|
||||
RefStrength:number
|
||||
}
|
||||
|
||||
interface ComfyConfig{
|
||||
workflow:string,
|
||||
posNodeID: string,
|
||||
posInputName:string,
|
||||
negNodeID: string,
|
||||
negInputName:string,
|
||||
timeout: number
|
||||
}
|
||||
|
||||
export type FormatingOrderItem = 'main'|'jailbreak'|'chats'|'lorebook'|'globalNote'|'authorNote'|'lastChat'|'description'|'postEverything'|'personaPrompt'
|
||||
|
||||
export interface Chat{
|
||||
@@ -981,6 +1006,7 @@ export interface Chat{
|
||||
scriptstate?:{[key:string]:string|number|boolean}
|
||||
modules?:string[]
|
||||
id?:string
|
||||
bindedPersona?:string
|
||||
}
|
||||
|
||||
export interface Message{
|
||||
@@ -1299,9 +1325,9 @@ export async function downloadPreset(id:number, type:'json'|'risupreset'|'return
|
||||
}
|
||||
else if(type === 'risupreset' || type === 'return'){
|
||||
const buf = fflate.compressSync(encodeMsgpack({
|
||||
presetVersion: 0,
|
||||
presetVersion: 2,
|
||||
type: 'preset',
|
||||
pres: await encryptBuffer(
|
||||
preset: await encryptBuffer(
|
||||
encodeMsgpack(pres),
|
||||
'risupreset'
|
||||
)
|
||||
@@ -1342,8 +1368,8 @@ export async function importPreset(f:{
|
||||
if(f.name.endsWith('.risupreset')){
|
||||
const decoded = await decodeMsgpack(fflate.decompressSync(f.data))
|
||||
console.log(decoded)
|
||||
if(decoded.presetVersion === 0 && decoded.type === 'preset'){
|
||||
pre = {...presetTemplate,...decodeMsgpack(Buffer.from(await decryptBuffer(decoded.pres, 'risupreset')))}
|
||||
if((decoded.presetVersion === 0 || decoded.presetVersion === 2) && decoded.type === 'preset'){
|
||||
pre = {...presetTemplate,...decodeMsgpack(Buffer.from(await decryptBuffer(decoded.preset ?? decoded.pres, 'risupreset')))}
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -1484,4 +1510,4 @@ export async function importPreset(f:{
|
||||
pre.name ??= "Imported"
|
||||
db.botPresets.push(pre)
|
||||
setDatabase(db)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { writeBinaryFile,BaseDirectory, readBinaryFile, exists, createDir, readDir, removeFile } from "@tauri-apps/api/fs"
|
||||
|
||||
import { changeFullscreen, checkNullish, findCharacterbyId, sleep } from "../util"
|
||||
import { convertFileSrc, invoke } from "@tauri-apps/api/tauri"
|
||||
import { v4 as uuidv4, v4 } from 'uuid';
|
||||
@@ -11,7 +12,7 @@ import { checkRisuUpdate } from "../update";
|
||||
import { botMakerMode, selectedCharID } from "../stores";
|
||||
import { Body, ResponseType, fetch as TauriFetch } from "@tauri-apps/api/http";
|
||||
import { loadPlugins } from "../plugins/plugins";
|
||||
import { alertConfirm, alertError, alertNormal, alertNormalWait } from "../alert";
|
||||
import { alertConfirm, alertError, alertNormal, alertNormalWait, alertSelect } from "../alert";
|
||||
import { checkDriverInit, syncDrive } from "../drive/drive";
|
||||
import { hasher } from "../parser";
|
||||
import { characterURLImport, hubURL } from "../characterCards";
|
||||
@@ -55,12 +56,26 @@ interface fetchLog{
|
||||
|
||||
let fetchLog:fetchLog[] = []
|
||||
|
||||
/**
|
||||
* Downloads a file with the given name and data.
|
||||
*
|
||||
* @param {string} name - The name of the file to be downloaded.
|
||||
* @param {Uint8Array|ArrayBuffer|string} dat - The data of the file to be downloaded.
|
||||
*/
|
||||
async function writeBinaryFileFast(appPath: string, data: Uint8Array) {
|
||||
const secret = await invoke('get_http_secret') as string;
|
||||
const port = await invoke('get_http_port') as number;
|
||||
|
||||
const apiUrl = `http://127.0.0.1:${port}/?path=${encodeURIComponent(appPath)}`;
|
||||
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'x-tauri-secret': secret
|
||||
},
|
||||
body: new Blob([data])
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function downloadFile(name:string, dat:Uint8Array|ArrayBuffer|string) {
|
||||
if(typeof(dat) === 'string'){
|
||||
dat = Buffer.from(dat, 'utf-8')
|
||||
@@ -266,7 +281,7 @@ export async function saveAsset(data:Uint8Array, customId:string = '', fileName:
|
||||
fileExtension = fileName.split('.').pop()
|
||||
}
|
||||
if(isTauri){
|
||||
await writeBinaryFile(`assets/${id}.${fileExtension}`, data ,{dir: BaseDirectory.AppData})
|
||||
await writeBinaryFileFast(`assets/${id}.${fileExtension}`, data);
|
||||
return `assets/${id}.${fileExtension}`
|
||||
}
|
||||
else{
|
||||
@@ -341,13 +356,14 @@ export async function saveDb(){
|
||||
changed = false
|
||||
let db = get(DataBase)
|
||||
db.saveTime = Math.floor(Date.now() / 1000)
|
||||
const dbData = encodeRisuSave(db)
|
||||
if(isTauri){
|
||||
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
||||
await writeBinaryFile(`database/dbbackup-${(Date.now()/100).toFixed()}.bin`, dbData, {dir: BaseDirectory.AppData})
|
||||
const dbData = encodeRisuSave(db)
|
||||
await writeBinaryFileFast('database/database.bin', dbData);
|
||||
await writeBinaryFileFast(`database/dbbackup-${(Date.now()/100).toFixed()}.bin`, dbData);
|
||||
}
|
||||
else{
|
||||
if(!forageStorage.isAccount){
|
||||
const dbData = encodeRisuSave(db)
|
||||
await forageStorage.setItem('database/database.bin', dbData)
|
||||
await forageStorage.setItem(`database/dbbackup-${(Date.now()/100).toFixed()}.bin`, dbData)
|
||||
}
|
||||
@@ -386,7 +402,7 @@ export async function saveDb(){
|
||||
async function getDbBackups() {
|
||||
let db = get(DataBase)
|
||||
if(db?.account?.useSync){
|
||||
return
|
||||
return []
|
||||
}
|
||||
if(isTauri){
|
||||
const keys = await readDir('database', {dir: BaseDirectory.AppData})
|
||||
@@ -446,14 +462,11 @@ export async function loadData() {
|
||||
await createDir('assets', {dir: BaseDirectory.AppData})
|
||||
}
|
||||
if(!await exists('database/database.bin', {dir: BaseDirectory.AppData})){
|
||||
await writeBinaryFile('database/database.bin',
|
||||
encodeRisuSave({})
|
||||
,{dir: BaseDirectory.AppData})
|
||||
await writeBinaryFileFast('database/database.bin', encodeRisuSave({}));
|
||||
}
|
||||
try {
|
||||
setDatabase(
|
||||
decodeRisuSave(await readBinaryFile('database/database.bin',{dir: BaseDirectory.AppData}))
|
||||
)
|
||||
const decoded = decodeRisuSave(await readBinaryFile('database/database.bin',{dir: BaseDirectory.AppData}))
|
||||
setDatabase(decoded)
|
||||
} catch (error) {
|
||||
const backups = await getDbBackups()
|
||||
let backupLoaded = false
|
||||
@@ -483,10 +496,11 @@ export async function loadData() {
|
||||
await forageStorage.setItem('database/database.bin', gotStorage)
|
||||
}
|
||||
try {
|
||||
setDatabase(
|
||||
decodeRisuSave(gotStorage)
|
||||
)
|
||||
const decoded = decodeRisuSave(gotStorage)
|
||||
console.log(decoded)
|
||||
setDatabase(decoded)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
const backups = await getDbBackups()
|
||||
let backupLoaded = false
|
||||
for(const backup of backups){
|
||||
@@ -1076,23 +1090,24 @@ async function checkNewFormat(): Promise<void> {
|
||||
if (v.lorebook) {
|
||||
v.lorebook = updateLorebooks(v.lorebook);
|
||||
}
|
||||
return v;
|
||||
});
|
||||
return v
|
||||
})
|
||||
|
||||
if (!db.formatversion) {
|
||||
/**
|
||||
* Checks and updates the path of a given data string.
|
||||
*
|
||||
* @param {string} data - The data string to be checked and updated.
|
||||
* @returns {string} - The updated data string with the correct path.
|
||||
*/
|
||||
function checkParge(data: string): string {
|
||||
if (data.startsWith('assets') || (data.length < 3)) {
|
||||
return data;
|
||||
} else {
|
||||
const d = 'assets/' + (data.replace(/\\/g, '/').split('assets/')[1]);
|
||||
if (!d) {
|
||||
return data;
|
||||
db.personas = (db.personas ?? []).map((v) => {
|
||||
v.id ??= uuidv4()
|
||||
return v
|
||||
})
|
||||
|
||||
if(!db.formatversion){
|
||||
function checkParge(data:string){
|
||||
|
||||
if(data.startsWith('assets') || (data.length < 3)){
|
||||
return data
|
||||
}
|
||||
else{
|
||||
const d = 'assets/' + (data.replace(/\\/g, '/').split('assets/')[1])
|
||||
if(!d){
|
||||
return data
|
||||
}
|
||||
return d;
|
||||
}
|
||||
@@ -2021,4 +2036,47 @@ export class BlankWriter{
|
||||
async end(){
|
||||
//do nothing, just to make compatible with other writer
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadInternalBackup(){
|
||||
|
||||
const keys = isTauri ? (await readDir('database', {dir: BaseDirectory.AppData})).map((v) => {
|
||||
return v.name
|
||||
}) : (await forageStorage.keys())
|
||||
let internalBackups:string[] = []
|
||||
for(const key of keys){
|
||||
if(key.includes('dbbackup-')){
|
||||
internalBackups.push(key)
|
||||
}
|
||||
}
|
||||
|
||||
const selectOptions = [
|
||||
'Cancel',
|
||||
...(internalBackups.map((a) => {
|
||||
return (new Date(parseInt(a.replace('database/dbbackup-', '').replace('dbbackup-','')) * 100)).toLocaleString()
|
||||
}))
|
||||
]
|
||||
|
||||
const alertResult = parseInt(
|
||||
await alertSelect(selectOptions)
|
||||
) - 1
|
||||
|
||||
if(alertResult === -1){
|
||||
return
|
||||
}
|
||||
|
||||
const selectedBackup = internalBackups[alertResult]
|
||||
|
||||
const data = isTauri ? (
|
||||
await readBinaryFile('database/' + selectedBackup, {dir: BaseDirectory.AppData})
|
||||
) : (await forageStorage.getItem(selectedBackup))
|
||||
|
||||
setDatabase(
|
||||
decodeRisuSave(data)
|
||||
)
|
||||
|
||||
await alertNormal('Loaded backup')
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ const magicCompressedHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69,
|
||||
|
||||
export function encodeRisuSave(data:any, compression:'noCompression'|'compression' = 'noCompression'){
|
||||
let encoded:Uint8Array = packr.encode(data)
|
||||
if(isTauri || compression === 'compression'){
|
||||
if(compression === 'compression'){
|
||||
encoded = fflate.compressSync(encoded)
|
||||
const result = new Uint8Array(encoded.length + magicCompressedHeader.length);
|
||||
result.set(magicCompressedHeader, 0)
|
||||
|
||||
Reference in New Issue
Block a user