From ea6b1d20e50740fda400d8210b328dd469ea55ed Mon Sep 17 00:00:00 2001 From: kwaroran Date: Thu, 28 Mar 2024 03:02:18 +0900 Subject: [PATCH] Prepare new realm upload --- src/lib/UI/Realm/RealmUpload.svelte | 2 +- src/ts/characterCards.ts | 76 ++++++++++++++++++++++++++--- src/ts/pngChunk.ts | 4 +- src/ts/storage/database.ts | 1 + src/ts/storage/globalApi.ts | 10 ++++ 5 files changed, 83 insertions(+), 10 deletions(-) diff --git a/src/lib/UI/Realm/RealmUpload.svelte b/src/lib/UI/Realm/RealmUpload.svelte index 48794d25..d59c2127 100644 --- a/src/lib/UI/Realm/RealmUpload.svelte +++ b/src/lib/UI/Realm/RealmUpload.svelte @@ -87,7 +87,7 @@ import { CCLicenseData } from "src/ts/creation/license"; import OptionInput from "../GUI/OptionInput.svelte"; import { parseMultilangString } from "src/ts/util"; - import MultiLangInput from "../GUI/MultiLangInput.svelte"; + import MultiLangInput from "../GUI/MultiLangInput.svelte"; export let close = () => {} export let char:character let tags="" diff --git a/src/ts/characterCards.ts b/src/ts/characterCards.ts index d96792d6..53ccc581 100644 --- a/src/ts/characterCards.ts +++ b/src/ts/characterCards.ts @@ -5,9 +5,9 @@ import { checkNullish, decryptBuffer, encryptBuffer, selectFileByDom, selectMult import { language } from "src/lang" import { v4 as uuidv4 } from 'uuid'; import { characterFormatUpdate } from "./characters" -import { AppendableBuffer, checkCharOrder, downloadFile, loadAsset, LocalWriter, readImage, saveAsset } from "./storage/globalApi" +import { AppendableBuffer, checkCharOrder, downloadFile, loadAsset, LocalWriter, readImage, saveAsset, VirtualWriter } from "./storage/globalApi" import { cloneDeep } from "lodash" -import { selectedCharID } from "./stores" +import { CurrentCharacter, selectedCharID } from "./stores" import { convertImage, hasher } from "./parser" import { reencodeImage } from "./process/files/image" @@ -617,15 +617,20 @@ async function createBaseV2(char:character) { } -export async function exportSpecV2(char:character, type:'png'|'json'|'rcc' = 'png', rcc:{password?:string} = {}) { +export async function exportSpecV2(char:character, type:'png'|'json'|'rcc' = 'png', arg:{ + password?:string + writer?:LocalWriter|VirtualWriter +} = {}) { let img = await readImage(char.image) try{ char.image = '' const card = await createBaseV2(char) img = await reencodeImage(img) - const localWriter = new LocalWriter() - await localWriter.init(`Image file`, ['png']) + const localWriter = arg.writer ?? (new LocalWriter()) + if(!arg.writer){ + await (localWriter as LocalWriter).init(`Image file`, ['png']) + } const writer = new PngChunk.streamWriter(img, localWriter) await writer.init() let assetIndex = 0 @@ -689,7 +694,7 @@ export async function exportSpecV2(char:character, type:'png'|'json'|'rcc' = 'pn }) if(type === 'rcc'){ - const password = rcc.password || 'RISU_NONE' + const password = arg.password || 'RISU_NONE' const json = JSON.stringify(card) const encrypted = Buffer.from(await encryptBuffer(Buffer.from(json, 'utf-8'), password)) const hashed = await hasher(encrypted) @@ -708,7 +713,9 @@ export async function exportSpecV2(char:character, type:'png'|'json'|'rcc' = 'pn await sleep(10) - alertNormal(language.successExport) + if(!arg.writer){ + alertNormal(language.successExport) + } } catch(e){ @@ -717,6 +724,61 @@ export async function exportSpecV2(char:character, type:'png'|'json'|'rcc' = 'pn } } +export async function shareRisuHub2(char:character, arg:{ + nsfw: boolean, + tag:string + license: string + anon: boolean +}) { + char = cloneDeep(char) + char.license = arg.license + let tagList = arg.tag.split(',') + + if(arg.nsfw){ + tagList.push("nsfw") + } + + await alertWait("Uploading...") + + + let tags = tagList.filter((v, i) => { + return (!!v) && (tagList.indexOf(v) === i) + }) + char.tags = tags + + + const writer = new VirtualWriter() + await exportSpecV2(char, 'png', {writer: writer}) + + const fetchPromise = fetch(hubURL + '/hub/realm/upload', { + method: "POST", + body: writer.buf.buffer, + headers: { + "Content-Type": 'image/png', + "x-risu-api-version": "4", + "x-risu-token": get(DataBase)?.account?.token, + 'x-risu-username': arg.anon ? '' : (get(DataBase)?.account?.id), + } + }) + + + const res = await fetchPromise + + if(res.status !== 200){ + alertError(await res.text()) + } + else{ + const resJSON = await res.json() + alertNormal(resJSON.message) + const currentChar = get(CurrentCharacter) + if(currentChar.type === 'group'){ + return + } + currentChar.realmId = resJSON.id + } + +} + export async function shareRisuHub(char:character, arg:{ nsfw: boolean, tag:string diff --git a/src/ts/pngChunk.ts b/src/ts/pngChunk.ts index 07a59599..8d6e8bc0 100644 --- a/src/ts/pngChunk.ts +++ b/src/ts/pngChunk.ts @@ -1,10 +1,10 @@ import { Buffer } from 'buffer'; import crc32 from 'crc/crc32'; -import { AppendableBuffer, type LocalWriter } from './storage/globalApi'; +import { AppendableBuffer, VirtualWriter, type LocalWriter } from './storage/globalApi'; import { blobToUint8Array } from './util'; class StreamChunkWriter{ - constructor(private data:Uint8Array, private writer:LocalWriter){ + constructor(private data:Uint8Array, private writer:LocalWriter|WritableStreamDefaultWriter|VirtualWriter){ } async pushData(data:Uint8Array){ diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts index 471e194a..11216505 100644 --- a/src/ts/storage/database.ts +++ b/src/ts/storage/database.ts @@ -727,6 +727,7 @@ export interface character{ language: string }, vits?: OnnxModelFiles + realmId?:string } diff --git a/src/ts/storage/globalApi.ts b/src/ts/storage/globalApi.ts index 21c66bdb..1f6f4a25 100644 --- a/src/ts/storage/globalApi.ts +++ b/src/ts/storage/globalApi.ts @@ -1178,6 +1178,16 @@ export class LocalWriter{ } } +export class VirtualWriter{ + buf = new AppendableBuffer() + async write(data:Uint8Array) { + this.buf.append(data) + } + async close(){ + // do nothing + } +} + let fetchIndex = 0 let nativeFetchData:{[key:string]:StreamedFetchChunk[]} = {}