diff --git a/package.json b/package.json
index fcf73bab..5f53d9e8 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"@msgpack/msgpack": "3.0.0-beta2",
"@tauri-apps/api": "1.3.0",
"@xenova/transformers": "^2.1.1",
+ "blueimp-md5": "^2.19.0",
"body-parser": "^1.20.2",
"buffer": "^6.0.3",
"core-js": "^3.30.2",
@@ -43,6 +44,7 @@
"showdown": "^2.1.0",
"sweetalert2": "^11.7.3",
"uuid": "^9.0.0",
+ "wasmoon": "^1.15.0",
"web-streams-polyfill": "^3.2.1"
},
"devDependencies": {
@@ -50,6 +52,7 @@
"@tailwindcss/typography": "^0.5.9",
"@tauri-apps/cli": "1.3.1",
"@tsconfig/svelte": "^3.0.0",
+ "@types/blueimp-md5": "^2.18.0",
"@types/dompurify": "^3.0.1",
"@types/lodash": "^4.14.194",
"@types/lodash.clonedeep": "^4.5.7",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 670f657c..5e0793d9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -16,6 +16,9 @@ dependencies:
'@xenova/transformers':
specifier: ^2.1.1
version: 2.1.1
+ blueimp-md5:
+ specifier: ^2.19.0
+ version: 2.19.0
body-parser:
specifier: ^1.20.2
version: 1.20.2
@@ -88,6 +91,9 @@ dependencies:
uuid:
specifier: ^9.0.0
version: 9.0.0
+ wasmoon:
+ specifier: ^1.15.0
+ version: 1.15.0
web-streams-polyfill:
specifier: ^3.2.1
version: 3.2.1
@@ -105,6 +111,9 @@ devDependencies:
'@tsconfig/svelte':
specifier: ^3.0.0
version: 3.0.0
+ '@types/blueimp-md5':
+ specifier: ^2.18.0
+ version: 2.18.0
'@types/dompurify':
specifier: ^3.0.1
version: 3.0.1
@@ -731,12 +740,20 @@ packages:
resolution: {integrity: sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==}
dev: true
+ /@types/blueimp-md5@2.18.0:
+ resolution: {integrity: sha512-f4A+++lGZGJvVSgeyMkqA7BEf2BVQli6F+qEykKb49c5ieWQBkfpn6CP5c1IZr2Yi2Ofl6Fj+v0e1fN18Z8Cnw==}
+ dev: true
+
/@types/dompurify@3.0.1:
resolution: {integrity: sha512-ubq8VKmf8W+U48jUOiZO4BoSGS7NnbITPMvrF+7HgMN4L+eezCKv8QBPB8p3o4YPicLMmNeTyDkE5X4c2ViHJQ==}
dependencies:
'@types/jsdom': 21.1.1
'@types/trusted-types': 2.0.3
+ /@types/emscripten@1.39.5:
+ resolution: {integrity: sha512-DIOOg+POSrYl+OlNRHQuIEqCd8DCtynG57H862UCce16nXJX7J8eWxNGgOcf8Eyge8zXeSs27mz1UcFu8L/L7g==}
+ dev: false
+
/@types/jsdom@21.1.1:
resolution: {integrity: sha512-cZFuoVLtzKP3gmq9eNosUL1R50U+USkbLtUQ1bYVgl/lKp0FZM7Cq4aIHAL8oIvQ17uSHi7jXPtfDOdjPwBE7A==}
dependencies:
@@ -912,6 +929,10 @@ packages:
readable-stream: 3.6.2
dev: false
+ /blueimp-md5@2.19.0:
+ resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==}
+ dev: false
+
/body-parser@1.20.1:
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -3190,6 +3211,13 @@ packages:
xml-name-validator: 4.0.0
dev: false
+ /wasmoon@1.15.0:
+ resolution: {integrity: sha512-QU33AnnMTgbcGOJLzcqM2UBcSksmLvwkvB/Bcgkf5hS+EFoHxB6nyiQiDG+ZnALN8mn/ezeeMSm6eY1zs0cKTg==}
+ hasBin: true
+ dependencies:
+ '@types/emscripten': 1.39.5
+ dev: false
+
/web-streams-polyfill@3.2.1:
resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
engines: {node: '>= 8'}
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index e74c7145..cee0bae6 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -11,6 +11,8 @@ use serde_json::Value;
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
use base64::{engine::general_purpose, Engine as _};
use std::time::Duration;
+use serde_json::json;
+use std::collections::HashMap;
#[tauri::command]
@@ -61,13 +63,15 @@ async fn native_request(url: String, body: String, header: String, method:String
match response {
Ok(resp) => {
+ let headers = resp.headers();
+ let header_json = header_map_to_json(headers);
let bytes = match resp.bytes().await {
Ok(b) => b,
Err(e) => return format!(r#"{{"success":false,"body":"{}"}}"#, e.to_string()),
};
let encoded = general_purpose::STANDARD.encode(&bytes);
- format!(r#"{{"success":true,"body":"{}"}}"#, encoded)
+ format!(r#"{{"success":true,"body":"{}","headers":{}}}"#, encoded, header_json)
}
Err(e) => format!(r#"{{"success":false,"body":"{}"}}"#, e.to_string()),
}
@@ -79,3 +83,12 @@ fn main() {
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
+
+
+fn header_map_to_json(header_map: &HeaderMap) -> serde_json::Value {
+ let mut map = HashMap::new();
+ for (key, value) in header_map {
+ map.insert(key.as_str().to_string(), value.to_str().unwrap().to_string());
+ }
+ json!(map)
+}
\ No newline at end of file
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 1b499f4e..6a142c80 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -8,7 +8,7 @@
},
"package": {
"productName": "RisuAI",
- "version": "1.26.0"
+ "version": "1.27.1"
},
"tauri": {
"allowlist": {
diff --git a/src/lib/UI/ModelList.svelte b/src/lib/UI/ModelList.svelte
index 9feecb1a..f2a71248 100644
--- a/src/lib/UI/ModelList.svelte
+++ b/src/lib/UI/ModelList.svelte
@@ -3,7 +3,7 @@
import { getHordeModels } from "src/ts/horde/getModels";
import Arcodion from "./Arcodion.svelte";
import { language } from "src/lang";
- import { isNodeServer, isTauri } from "src/ts/storage/globalApi";
+ import { isNodeServer, isTauri } from "src/ts/storage/globalApi";
export let value = ""
export let onChange: (v:string) => void = (v) => {}
@@ -63,10 +63,11 @@
-
-
+
+
+
@@ -80,6 +81,7 @@
{#if isTauri ||isNodeServer}
+
{/if}
{#await getHordeModels()}
diff --git a/src/ts/drive/drive.ts b/src/ts/drive/drive.ts
index e1278d7a..88ce9f33 100644
--- a/src/ts/drive/drive.ts
+++ b/src/ts/drive/drive.ts
@@ -2,7 +2,6 @@ import { get } from "svelte/store";
import { alertError, alertInput, alertNormal, alertSelect, alertStore } from "../alert";
import { DataBase, setDatabase, type Database } from "../storage/database";
import { forageStorage, getUnpargeables, isNodeServer, isTauri, openURL } from "../storage/globalApi";
-import pako from "pako";
import { BaseDirectory, exists, readBinaryFile, readDir, writeBinaryFile } from "@tauri-apps/api/fs";
import { language } from "../../lang";
import { relaunch } from '@tauri-apps/api/process';
@@ -10,6 +9,7 @@ import { open } from '@tauri-apps/api/shell';
import { cloneDeep, isEqual, last } from "lodash";
import { sleep } from "../util";
import { hubURL } from "../characterCards";
+import { decodeRisuSave, encodeRisuSave } from "../storage/risuSave";
export async function checkDriver(type:'save'|'load'|'loadtauri'|'savetauri'|'reftoken'){
const CLIENT_ID = '580075990041-l26k2d3c0nemmqiu3d3aag01npfrkn76.apps.googleusercontent.com';
@@ -245,10 +245,7 @@ async function backupDrive(ACCESS_TOKEN:string) {
}
}
- const dbjson = JSON.stringify(get(DataBase))
- const dbData = pako.deflate(
- Buffer.from(dbjson, 'utf-8')
- )
+ const dbData = encodeRisuSave(get(DataBase))
alertStore.set({
type: "wait",
@@ -355,7 +352,7 @@ async function loadDrive(ACCESS_TOKEN:string, mode: 'backup'|'sync'):Promise {
}
})
-export async function ParseMarkdown(data:string, char:(character | groupChat) = null, mode:'normal'|'back' = 'normal') {
- if(char && char.type !== 'group'){
- if(char.additionalAssets){
- for(const asset of char.additionalAssets){
- const assetPath = await getFileSrc(asset[1])
- data = data.replaceAll(`{{raw::${asset[0]}}}`, assetPath).
- replaceAll(`{{img::${asset[0]}}}`,`
`)
- .replaceAll(`{{video::${asset[0]}}}`,``)
- .replaceAll(`{{audio::${asset[0]}}}`,``)
- if(mode === 'back'){
- data = data.replaceAll(`{{bg::${asset[0]}}}`, ``)
- }
+async function parseAdditionalAssets(data:string, char:character, mode:'normal'|'back'){
+ if(char.additionalAssets){
+ for(const asset of char.additionalAssets){
+ const assetPath = await getFileSrc(asset[1])
+ data = data.replaceAll(`{{raw::${asset[0]}}}`, assetPath).
+ replaceAll(`{{img::${asset[0]}}}`,`
`)
+ .replaceAll(`{{video::${asset[0]}}}`,``)
+ .replaceAll(`{{audio::${asset[0]}}}`,``)
+ if(mode === 'back'){
+ data = data.replaceAll(`{{bg::${asset[0]}}}`, ``)
}
}
}
+
+ return data
+}
+
+export async function ParseMarkdown(data:string, char:(character | groupChat) = null, mode:'normal'|'back' = 'normal') {
+ let firstParsed = ''
+ if(char && char.type !== 'group'){
+ data = await parseAdditionalAssets(data, char, mode)
+ firstParsed = data
+ }
if(char){
data = processScript(char, data, 'editdisplay')
}
+ if(firstParsed !== data && char && char.type !== 'group'){
+ data = await parseAdditionalAssets(data, char, mode)
+ }
return DOMPurify.sanitize(convertor.makeHtml(data), {
ADD_TAGS: ["iframe"],
ADD_ATTR: ["allow", "allowfullscreen", "frameborder", "scrolling"],
diff --git a/src/ts/process/deepai.ts b/src/ts/process/deepai.ts
new file mode 100644
index 00000000..8d117df1
--- /dev/null
+++ b/src/ts/process/deepai.ts
@@ -0,0 +1,40 @@
+import md5 from "blueimp-md5";
+import { globalFetch } from "../storage/globalApi";
+import type { OpenAIChat } from ".";
+
+function randomBytes(size: number): Uint8Array {
+ const array = new Uint8Array(size);
+ return crypto.getRandomValues(array);
+}
+export async function createDeep(messages: OpenAIChat[]) {
+ const userAgent = navigator.userAgent;
+
+ const part1 = Math.floor(Math.random() * Math.pow(10, 11)).toString();
+
+ const md5Text = (text: string): string => {
+ return md5(text).split('').reverse().join('');
+ }
+
+ const part2 = md5Text(userAgent + md5Text(userAgent + md5Text(userAgent + part1 + "x")));
+
+ const apiKey = `tryit-${part1}-${part2}`;
+
+ const headers = {
+ "api-key": apiKey,
+ "user-agent": userAgent
+ };
+
+ const body = new URLSearchParams();
+ body.append("chat_style", "chat");
+ console.log(messages);
+ body.append("chatHistory", JSON.stringify(messages));
+
+ const response = await globalFetch("https://api.deepai.org/chat_response", {
+ method: 'POST',
+ headers: headers,
+ body: body,
+ rawResponse: true
+ });
+
+ return response;
+}
\ No newline at end of file
diff --git a/src/ts/process/index.ts b/src/ts/process/index.ts
index 83e483cd..e634fe72 100644
--- a/src/ts/process/index.ts
+++ b/src/ts/process/index.ts
@@ -139,6 +139,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
maxContextTokens = 8000
}
}
+ if(db.aiModel === 'deepai'){
+ if(maxContextTokens > 3000){
+ maxContextTokens = 3000
+ }
+ }
let unformated = {
@@ -154,7 +159,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
}
if(!currentChar.utilityBot){
- const mainp = currentChar.systemPrompt || db.mainPrompt
+ const mainp = currentChar.systemPrompt?.replaceAll('{{original}}', db.mainPrompt) || db.mainPrompt
function formatPrompt(data:string){
@@ -183,7 +188,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
unformated.jailbreak.push(...formatPrompt(replacePlaceholders(db.jailbreak, currentChar.name)))
}
- unformated.globalNote.push(...formatPrompt(replacePlaceholders(currentChar.replaceGlobalNote || db.globalNote, currentChar.name)))
+ unformated.globalNote.push(...formatPrompt(replacePlaceholders(currentChar.replaceGlobalNote?.replaceAll('{{original}}', db.globalNote) || db.globalNote, currentChar.name)))
}
if(currentChat.note){
diff --git a/src/ts/process/lua.ts b/src/ts/process/lua.ts
new file mode 100644
index 00000000..296580e0
--- /dev/null
+++ b/src/ts/process/lua.ts
@@ -0,0 +1,33 @@
+import { get } from "svelte/store";
+import { DataBase, type character } from "../storage/database";
+import type {LuaEngine} from 'wasmoon'
+import { selectedCharID } from "../stores";
+
+let lua: LuaEngine = null
+
+
+export class CharacterLua{
+ char:character
+ constructor(char:character){
+ this.char = char
+ }
+ async init(){
+ if(!lua){
+ const factory = new (await import("wasmoon")).LuaFactory
+ lua = await factory.createEngine()
+ lua.global.set('getChat', () => {
+ const cha = get(DataBase).characters[get(selectedCharID)]
+ return cha.chats[cha.chatPage].message
+ })
+ lua.global.set('setChat', () => {
+ const cha = get(DataBase).characters[get(selectedCharID)]
+ return cha.chats[cha.chatPage].message
+ })
+ lua.global.set('doSend', (a:string) => {
+ console.log(a)
+ })
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/ts/process/request.ts b/src/ts/process/request.ts
index 3fe36380..b81eeadd 100644
--- a/src/ts/process/request.ts
+++ b/src/ts/process/request.ts
@@ -6,6 +6,7 @@ import { language } from "../../lang";
import { stringlizeChat, unstringlizeChat } from "./stringlize";
import { globalFetch, isTauri } from "../storage/globalApi";
import { sleep } from "../util";
+import { createDeep } from "./deepai";
interface requestDataArgument{
formated: OpenAIChat[]
@@ -183,6 +184,13 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model'
}
}
+ if(da.headers.get('Content-Type') !== 'text/event-stream'){
+ return {
+ type: "fail",
+ result: await da.text()
+ }
+ }
+
let dataUint = new Uint8Array([])
const transtream = new TransformStream( {
@@ -572,6 +580,40 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model'
'result': unstringlizeChat(result, formated, currentChar?.name ?? '')
}
}
+ case "deepai":{
+
+ for(let i=0;i {
+ changed = true
+ })
while(true){
- const dbjson = JSON.stringify(get(DataBase))
- if(dbjson !== lastSave){
- lastSave = dbjson
- const dbData = pako.deflate(
- Buffer.from(dbjson, 'utf-8')
- )
+ if(changed){
+ const dbData = encodeRisuSave(get(DataBase))
if(isTauri){
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
await writeBinaryFile(`database/dbbackup-${(Date.now()/100).toFixed()}.bin`, dbData, {dir: BaseDirectory.AppData})
@@ -279,13 +279,13 @@ export async function loadData() {
}
if(!await exists('database/database.bin', {dir: BaseDirectory.AppData})){
await writeBinaryFile('database/database.bin',
- pako.deflate(Buffer.from(JSON.stringify({}), 'utf-8'))
+ encodeRisuSave({})
,{dir: BaseDirectory.AppData})
}
try {
setDatabase(
- JSON.parse(Buffer.from(pako.inflate(Buffer.from(await readBinaryFile('database/database.bin',{dir: BaseDirectory.AppData})))).toString('utf-8'))
- )
+ decodeRisuSave(await readBinaryFile('database/database.bin',{dir: BaseDirectory.AppData}))
+ )
} catch (error) {
const backups = await getDbBackups()
let backupLoaded = false
@@ -293,7 +293,7 @@ export async function loadData() {
try {
const backupData = await readBinaryFile(`database/dbbackup-${backup}.bin`,{dir: BaseDirectory.AppData})
setDatabase(
- JSON.parse(Buffer.from(pako.inflate(Buffer.from(backupData))).toString('utf-8'))
+ decodeRisuSave(backupData)
)
backupLoaded = true
} catch (error) {}
@@ -309,12 +309,11 @@ export async function loadData() {
else{
let gotStorage:Uint8Array = await forageStorage.getItem('database/database.bin')
if(checkNullish(gotStorage)){
- gotStorage = pako.deflate(Buffer.from(JSON.stringify({}), 'utf-8'))
- await forageStorage.setItem('database/database.bin', gotStorage)
+ await forageStorage.setItem('database/database.bin', encodeRisuSave({}))
}
try {
setDatabase(
- JSON.parse(Buffer.from(pako.inflate(Buffer.from(gotStorage))).toString('utf-8'))
+ decodeRisuSave(gotStorage)
)
} catch (error) {
const backups = await getDbBackups()
@@ -323,7 +322,7 @@ export async function loadData() {
try {
const backupData:Uint8Array = await forageStorage.getItem(`database/dbbackup-${backup}.bin`)
setDatabase(
- JSON.parse(Buffer.from(pako.inflate(Buffer.from(backupData))).toString('utf-8'))
+ decodeRisuSave(backupData)
)
backupLoaded = true
} catch (error) {}
@@ -380,7 +379,11 @@ export async function loadData() {
const knownHostes = ["localhost","127.0.0.1","api.openai.com"]
-export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:string]:string}, rawResponse?:boolean, method?:"POST"|"GET", abortSignal?:AbortSignal} = {}) {
+export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:string]:string}, rawResponse?:boolean, method?:"POST"|"GET", abortSignal?:AbortSignal} = {}): Promise<{
+ ok: boolean;
+ data: any;
+ headers:{[key:string]:string}
+}> {
try {
const db = get(DataBase)
const method = arg.method ?? "POST"
@@ -430,7 +433,8 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
addFetchLog("Uint8Array Response", da.ok && da.status >= 200 && da.status < 300)
return {
ok: da.ok && da.status >= 200 && da.status < 300,
- data: new Uint8Array(await da.arrayBuffer())
+ data: new Uint8Array(await da.arrayBuffer()),
+ headers: Object.fromEntries(da.headers)
}
}
else{
@@ -438,7 +442,8 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
addFetchLog(dat, da.ok && da.status >= 200 && da.status < 300)
return {
ok: da.ok && da.status >= 200 && da.status < 300,
- data: dat
+ data: dat,
+ headers: Object.fromEntries(da.headers)
}
}
@@ -446,6 +451,7 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
return {
ok: false,
data: `${error}`,
+ headers: {}
}
}
}
@@ -469,7 +475,8 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
addFetchLog("Uint8Array Response", da.ok && da.status >= 200 && da.status < 300)
return {
ok: da.ok && da.status >= 200 && da.status < 300,
- data: new Uint8Array(await da.arrayBuffer())
+ data: new Uint8Array(await da.arrayBuffer()),
+ headers: Object.fromEntries(da.headers)
}
}
else{
@@ -477,7 +484,8 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
addFetchLog(dat, da.ok && da.status >= 200 && da.status < 300)
return {
ok: da.ok && da.status >= 200 && da.status < 300,
- data: dat
+ data: dat,
+ headers: Object.fromEntries(da.headers)
}
}
@@ -485,6 +493,7 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
return {
ok: false,
data: `${error}`,
+ headers: {}
}
}
}
@@ -492,20 +501,33 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
if(db.requester === 'new'){
try {
let preHeader = arg.headers ?? {}
- preHeader["Content-Type"] = `application/json`
- const body = JSON.stringify(arg.body)
+ let body:any
+ if(arg.body instanceof URLSearchParams){
+ const argBody = arg.body as URLSearchParams
+ body = argBody.toString()
+ preHeader["Content-Type"] = `application/x-www-form-urlencoded`
+ }
+ else{
+ body = JSON.stringify(arg.body)
+ preHeader["Content-Type"] = `application/json`
+ }
+ console.log(body)
const header = JSON.stringify(preHeader)
const res:string = await invoke('native_request', {url:url, body:body, header:header, method: method})
const d:{
success: boolean
- body:string
+ body:string,
+ headers: {[key:string]:string}
} = JSON.parse(res)
-
+
+ const resHeader = d.headers ?? {}
+
if(!d.success){
addFetchLog(Buffer.from(d.body, 'base64').toString('utf-8'), false)
return {
ok:false,
- data: Buffer.from(d.body, 'base64').toString('utf-8')
+ data: Buffer.from(d.body, 'base64').toString('utf-8'),
+ headers: resHeader
}
}
else{
@@ -513,14 +535,16 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
addFetchLog("Uint8Array Response", true)
return {
ok:true,
- data: new Uint8Array(Buffer.from(d.body, 'base64'))
+ data: new Uint8Array(Buffer.from(d.body, 'base64')),
+ headers: resHeader
}
}
else{
addFetchLog(JSON.parse(Buffer.from(d.body, 'base64').toString('utf-8')), true)
return {
ok:true,
- data: JSON.parse(Buffer.from(d.body, 'base64').toString('utf-8'))
+ data: JSON.parse(Buffer.from(d.body, 'base64').toString('utf-8')),
+ headers: resHeader
}
}
}
@@ -528,6 +552,7 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
return {
ok: false,
data: `${error}`,
+ headers: {}
}
}
}
@@ -549,6 +574,7 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
return {
ok: d.ok,
data: new Uint8Array(d.data as number[]),
+ headers: d.headers
}
}
else{
@@ -556,20 +582,33 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
return {
ok: d.ok,
data: d.data,
+ headers: d.headers
}
}
}
else{
try {
- let headers = arg.headers ?? {}
- if(!headers["Content-Type"]){
- headers["Content-Type"] = `application/json`
+ let body:any
+ if(arg.body instanceof URLSearchParams){
+ const argBody = arg.body as URLSearchParams
+ body = argBody.toString()
+ let headers = arg.headers ?? {}
+ if(!headers["Content-Type"]){
+ headers["Content-Type"] = `application/x-www-form-urlencoded`
+ }
+ }
+ else{
+ body = JSON.stringify(arg.body)
+ let headers = arg.headers ?? {}
+ if(!headers["Content-Type"]){
+ headers["Content-Type"] = `application/json`
+ }
}
if(arg.rawResponse){
const furl = `/proxy?url=${encodeURIComponent(url)}`
const da = await fetch(furl, {
- body: JSON.stringify(arg.body),
+ body: body,
headers: {
"risu-header": encodeURIComponent(JSON.stringify(arg.headers)),
"Content-Type": "application/json"
@@ -581,40 +620,53 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
addFetchLog("Uint8Array Response", da.ok && da.status >= 200 && da.status < 300)
return {
ok: da.ok && da.status >= 200 && da.status < 300,
- data: new Uint8Array(await da.arrayBuffer())
+ data: new Uint8Array(await da.arrayBuffer()),
+ headers: Object.fromEntries(da.headers)
}
}
else{
const furl = `/proxy?url=${encodeURIComponent(url)}`
const da = await fetch(furl, {
- body: JSON.stringify(arg.body),
+ body: body,
headers: {
"risu-header": encodeURIComponent(JSON.stringify(arg.headers)),
"Content-Type": "application/json"
},
method: method
})
-
- const dat = await da.json()
- addFetchLog(dat, da.ok && da.status >= 200 && da.status < 300)
- return {
- ok: da.ok && da.status >= 200 && da.status < 300,
- data: dat
+ const daText = await da.text()
+ try {
+ const dat = JSON.parse(daText)
+ addFetchLog(dat, da.ok && da.status >= 200 && da.status < 300)
+ return {
+ ok: da.ok && da.status >= 200 && da.status < 300,
+ data: dat,
+ headers: Object.fromEntries(da.headers)
+ }
+ } catch (error) {
+ addFetchLog(daText, false)
+ return {
+ ok:false,
+ data: daText,
+ headers: Object.fromEntries(da.headers)
+ }
}
}
} catch (error) {
console.log(error)
return {
ok:false,
- data: `${error}`
+ data: `${error}`,
+ headers: {}
}
}
}
} catch (error) {
return {
ok:false,
- data: `${error}`
+ data: `${error}`,
+ headers: {}
}
}
}
@@ -834,4 +886,14 @@ export function openURL(url:string){
else{
window.open(url, "_blank")
}
-}
\ No newline at end of file
+}
+
+function formDataToString(formData: FormData): string {
+ const params: string[] = [];
+
+ for (const [name, value] of formData.entries()) {
+ params.push(`${encodeURIComponent(name)}=${encodeURIComponent(value.toString())}`);
+ }
+
+ return params.join('&');
+ }
\ No newline at end of file
diff --git a/src/ts/storage/risuSave.ts b/src/ts/storage/risuSave.ts
new file mode 100644
index 00000000..4c56d8d8
--- /dev/null
+++ b/src/ts/storage/risuSave.ts
@@ -0,0 +1,31 @@
+import { decode, encode } from "@msgpack/msgpack";
+import { isEqual } from "lodash";
+import pako from "pako";
+
+
+export function encodeRisuSave(data:any){
+ const risuSaveHeader = new Uint8Array(Buffer.from("\u0000\u0000RISU",'utf-8'))
+ const encoded = encode(data)
+ const mergedArray = new Uint8Array(risuSaveHeader.length + encoded.length);
+ mergedArray.set(risuSaveHeader);
+ mergedArray.set(encoded, risuSaveHeader.length);
+ return mergedArray
+}
+
+export function decodeRisuSave(data:Uint8Array){
+ const risuSaveHeader = new Uint8Array(Buffer.from("\u0000\u0000RISU",'utf-8'))
+ const sub = data.subarray(0, risuSaveHeader.length)
+ if(isEqual(sub, risuSaveHeader)){
+ try {
+ const realData = data.subarray(risuSaveHeader.length)
+ const dec = decode(realData)
+ return dec
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ }
+ else{
+ return JSON.parse(Buffer.from(pako.inflate(Buffer.from(data))).toString('utf-8'))
+ }
+}
\ No newline at end of file
diff --git a/version.json b/version.json
index dbba4485..08b4235c 100644
--- a/version.json
+++ b/version.json
@@ -1 +1 @@
-{"version":"1.26.0"}
\ No newline at end of file
+{"version":"1.27.1"}
\ No newline at end of file