[feat] Add support for chat stickers (#178)
# PR Checklist - [x] Did you check if it works normally in all models? *ignore this when it dosen't uses models* - [x] Did you check if it works normally in all of web, local and node hosted versions? if it dosen't, did you blocked it in those versions? - [x] Did you added a type def? # Description - This commit adds support for chat stickers by allowing users to use stickers in chat message window. - The users can toggle show additional asset list using a button. - Added Additional assets file extension data. - Added option for additional assets preview. - Optimized render when use streaming api. (prevent markdown again when message not changed) Added controls to Video/Audio Assets [Video11.webm](https://github.com/kwaroran/RisuAI/assets/11344967/8980282f-d001-4afc-a6d9-6f6369b4cd4c) [Video12.webm](https://github.com/kwaroran/RisuAI/assets/11344967/e0e153b8-eba6-48a5-b47d-d2dd287f32fd)
This commit is contained in:
@@ -329,7 +329,7 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|'
|
||||
let customScripts:customscript[] = []
|
||||
let utilityBot = false
|
||||
let sdData = defaultSdDataFunc()
|
||||
let extAssets:[string,string][] = []
|
||||
let extAssets:[string,string,string][] = []
|
||||
|
||||
if(risuext){
|
||||
if(risuext.emotions){
|
||||
@@ -350,8 +350,11 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|'
|
||||
msg: `Loading... (Getting Assets ${i} / ${risuext.additionalAssets.length})`
|
||||
})
|
||||
await sleep(10)
|
||||
const imgp = await saveAsset(mode === 'hub' ? (await getHubResources(risuext.additionalAssets[i][1])) :Buffer.from(risuext.additionalAssets[i][1], 'base64'))
|
||||
extAssets.push([risuext.additionalAssets[i][0],imgp])
|
||||
let fileName = ''
|
||||
if(risuext.additionalAssets[i].length >= 3)
|
||||
fileName = risuext.additionalAssets[i][2]
|
||||
const imgp = await saveAsset(mode === 'hub' ? (await getHubResources(risuext.additionalAssets[i][1])) :Buffer.from(risuext.additionalAssets[i][1], 'base64'), '', fileName)
|
||||
extAssets.push([risuext.additionalAssets[i][0],imgp,fileName])
|
||||
}
|
||||
}
|
||||
bias = risuext.bias ?? bias
|
||||
@@ -756,7 +759,7 @@ type CharacterCardV2 = {
|
||||
customScripts?:customscript[]
|
||||
utilityBot?: boolean,
|
||||
sdData?:[string,string][],
|
||||
additionalAssets?:[string,string][],
|
||||
additionalAssets?:[string,string,string][],
|
||||
backgroundHTML?:string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,9 +63,9 @@ async function parseAdditionalAssets(data:string, char:character, mode:'normal'|
|
||||
for(const asset of char.additionalAssets){
|
||||
const assetPath = await getFileSrc(asset[1])
|
||||
data = data.replaceAll(`{{raw::${asset[0]}}}`, assetPath).
|
||||
replaceAll(`{{img::${asset[0]}}}`,`<img src="${assetPath}" />`)
|
||||
.replaceAll(`{{video::${asset[0]}}}`,`<video autoplay loop><source src="${assetPath}" type="video/mp4"></video>`)
|
||||
.replaceAll(`{{audio::${asset[0]}}}`,`<audio autoplay loop><source src="${assetPath}" type="audio/mpeg"></audio>`)
|
||||
replaceAll(`{{img::${asset[0]}}}`,`<img src="${assetPath}" alt="${asset[0]}"/>`)
|
||||
.replaceAll(`{{video::${asset[0]}}}`,`<video controls autoplay loop><source src="${assetPath}" type="video/mp4"></video>`)
|
||||
.replaceAll(`{{audio::${asset[0]}}}`,`<audio controls autoplay loop><source src="${assetPath}" type="audio/mpeg"></audio>`)
|
||||
if(mode === 'back'){
|
||||
data = data.replaceAll(`{{bg::${asset[0]}}}`, `<div style="width:100%;height:100%;background: linear-gradient(rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.8)),url(${assetPath}); background-size: cover;"></div>`)
|
||||
}
|
||||
|
||||
@@ -409,6 +409,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
|
||||
else if(req.type === 'streaming'){
|
||||
const reader = req.result.getReader()
|
||||
const msgIndex = db.characters[selectedChar].chats[selectedChat].message.length
|
||||
db.characters[selectedChar].chats[selectedChat].isStreaming = true
|
||||
db.characters[selectedChar].chats[selectedChat].message.push({
|
||||
role: 'char',
|
||||
data: "",
|
||||
@@ -424,6 +425,8 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
|
||||
setDatabase(db)
|
||||
}
|
||||
if(readed.done){
|
||||
db.characters[selectedChar].chats[selectedChat].isStreaming = false
|
||||
setDatabase(db)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ export interface character{
|
||||
VOLUME_SCALE?: number
|
||||
}
|
||||
supaMemory?:boolean
|
||||
additionalAssets?:[string, string][]
|
||||
additionalAssets?:[string, string, string][]
|
||||
ttsReadOnlyQuoted?:boolean
|
||||
replaceGlobalNote:string
|
||||
backgroundHTML?:string
|
||||
@@ -525,7 +525,9 @@ export interface Database{
|
||||
expires_in?: number
|
||||
}
|
||||
},
|
||||
classicMaxWidth: boolean
|
||||
classicMaxWidth: boolean,
|
||||
useChatSticker:boolean,
|
||||
useAdditionalAssetsPreview:boolean,
|
||||
}
|
||||
|
||||
interface hordeConfig{
|
||||
@@ -564,6 +566,7 @@ export interface Chat{
|
||||
supaMemoryData?:string
|
||||
lastMemory?:string
|
||||
suggestMessages?:string[]
|
||||
isStreaming?:boolean
|
||||
}
|
||||
|
||||
export interface Message{
|
||||
|
||||
@@ -170,7 +170,7 @@ export async function readImage(data:string) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveAsset(data:Uint8Array, customId:string = ''){
|
||||
export async function saveAsset(data:Uint8Array, customId:string = '', fileName:string = ''){
|
||||
let id = ''
|
||||
if(customId !== ''){
|
||||
id = customId
|
||||
@@ -182,13 +182,17 @@ export async function saveAsset(data:Uint8Array, customId:string = ''){
|
||||
id = uuidv4()
|
||||
}
|
||||
}
|
||||
let fileExtension:string = 'png'
|
||||
if(fileName && fileName.split('.').length > 0){
|
||||
fileExtension = fileName.split('.').pop()
|
||||
}
|
||||
if(isTauri){
|
||||
await writeBinaryFile(`assets/${id}.png`, data ,{dir: BaseDirectory.AppData})
|
||||
return `assets/${id}.png`
|
||||
await writeBinaryFile(`assets/${id}.${fileExtension}`, data ,{dir: BaseDirectory.AppData})
|
||||
return `assets/${id}.${fileExtension}`
|
||||
}
|
||||
else{
|
||||
await forageStorage.setItem(`assets/${id}.png`, data)
|
||||
return `assets/${id}.png`
|
||||
await forageStorage.setItem(`assets/${id}.${fileExtension}`, data)
|
||||
return `assets/${id}.${fileExtension}`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user