mirror of
https://github.com/chrononeko/chronocat.git
synced 2024-11-21 22:58:10 +00:00
feat: support marketface
This commit is contained in:
parent
60fa49ae01
commit
72cdae235e
@ -1,31 +1,63 @@
|
||||
import type { Media } from '@chronocat/red'
|
||||
import type { AssetRequest } from '@chronocat/red'
|
||||
import { ChatType } from '@chronocat/red'
|
||||
import type { ChronocatContext } from '@chronocat/shell'
|
||||
import { downloadRichMedia } from '../../../definitions/msgService'
|
||||
import { richMediaDownloadMap } from '../../../globalVars'
|
||||
import {
|
||||
downloadRichMedia,
|
||||
fetchMarketEmoticonAioImage,
|
||||
} from '../../../definitions/msgService'
|
||||
import { emojiDownloadMap, richMediaDownloadMap } from '../../../globalVars'
|
||||
|
||||
export const buildAssetsGet =
|
||||
(ctx: ChronocatContext) => async (raw: string) => {
|
||||
const data = JSON.parse(
|
||||
Buffer.from(raw, 'base64url').toString('utf-8'),
|
||||
) as Media
|
||||
) as AssetRequest
|
||||
|
||||
const downloadId = data.msgId + '::' + data.elementId
|
||||
if ('type' in data) {
|
||||
switch (data.type) {
|
||||
case 'marketface': {
|
||||
const downloadId = data.tabId + '::' + data.faceId
|
||||
|
||||
const downloadCompletePromise = new Promise<string>((res, rej) => {
|
||||
richMediaDownloadMap[downloadId] = res
|
||||
void ctx.chronocat.sleep(1000).then(rej)
|
||||
})
|
||||
const downloadCompletePromise = new Promise<string>((res, rej) => {
|
||||
emojiDownloadMap[downloadId] = res
|
||||
void ctx.chronocat.sleep(5000).then(rej)
|
||||
})
|
||||
|
||||
if (data.chatType === ChatType.Private && !data.peerUid.startsWith('u_'))
|
||||
data.peerUid = ctx.chronocat.uix.getUid(data.peerUid)!
|
||||
await fetchMarketEmoticonAioImage({
|
||||
marketEmoticonAioImageReq: {
|
||||
eId: data.faceId,
|
||||
epId: data.tabId,
|
||||
name: data.name,
|
||||
width: 200,
|
||||
height: 200,
|
||||
jobType: 0,
|
||||
encryptKey: data.key,
|
||||
filePath: data.filePath,
|
||||
downloadType: 3,
|
||||
},
|
||||
})
|
||||
|
||||
await downloadRichMedia({
|
||||
getReq: {
|
||||
...data,
|
||||
downloadType: 1,
|
||||
},
|
||||
})
|
||||
return await downloadCompletePromise
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const downloadId = data.msgId + '::' + data.elementId
|
||||
|
||||
return await downloadCompletePromise
|
||||
const downloadCompletePromise = new Promise<string>((res, rej) => {
|
||||
richMediaDownloadMap[downloadId] = res
|
||||
void ctx.chronocat.sleep(1000).then(rej)
|
||||
})
|
||||
|
||||
if (data.chatType === ChatType.Private && !data.peerUid.startsWith('u_'))
|
||||
data.peerUid = ctx.chronocat.uix.getUid(data.peerUid)!
|
||||
|
||||
await downloadRichMedia({
|
||||
getReq: {
|
||||
...data,
|
||||
downloadType: 1,
|
||||
},
|
||||
})
|
||||
|
||||
return await downloadCompletePromise
|
||||
}
|
||||
}
|
||||
|
@ -277,6 +277,19 @@ export class Messager {
|
||||
return
|
||||
}
|
||||
|
||||
case `${this.ctx.chronocat.platform}:marketface`: {
|
||||
this.children.push(
|
||||
r.marketFace(
|
||||
Number(attrs['tabId']),
|
||||
attrs['faceId'] as string,
|
||||
attrs['key'] as string,
|
||||
),
|
||||
)
|
||||
|
||||
this.isEndLine = false
|
||||
return
|
||||
}
|
||||
|
||||
case 'quote': {
|
||||
const [author] = this.ctx.chronocat.h.select(children, 'author')
|
||||
|
||||
|
@ -114,6 +114,28 @@ const b = () => {
|
||||
},
|
||||
}),
|
||||
|
||||
marketFace: (
|
||||
tabId: number,
|
||||
faceId: string,
|
||||
key: string,
|
||||
): O.Partial<Element, 'deep'> => ({
|
||||
elementType: 11,
|
||||
elementId: '',
|
||||
marketFaceElement: {
|
||||
itemType: 6,
|
||||
faceInfo: 1,
|
||||
emojiPackageId: tabId,
|
||||
subType: 3,
|
||||
mediaType: 0,
|
||||
imageWidth: 200,
|
||||
imageHeight: 200,
|
||||
faceName: '[动画表情]',
|
||||
emojiId: faceId,
|
||||
key: key,
|
||||
emojiType: 1,
|
||||
},
|
||||
}),
|
||||
|
||||
pcPoke: (pokeType: number): O.Partial<Element, 'deep'> => ({
|
||||
elementId: '0',
|
||||
elementType: 6,
|
||||
|
@ -151,3 +151,22 @@ export const deleteActiveChatByUid = define<Record<string, never>, [string]>(
|
||||
'ns-ntApi-2',
|
||||
'nodeIKernelMsgService/deleteActiveChatByUid',
|
||||
)
|
||||
|
||||
export const fetchMarketEmoticonAioImage = define<
|
||||
never,
|
||||
[
|
||||
{
|
||||
marketEmoticonAioImageReq: {
|
||||
eId: string // '94c8ffa6977fd17e8b180b312cdddc28'
|
||||
epId: number // 235125
|
||||
name: string // '[抱抱]'
|
||||
width: 200
|
||||
height: 200
|
||||
jobType: 0
|
||||
encryptKey: string // 'ea4dc6c26b6f9c31'
|
||||
filePath: string
|
||||
downloadType: 3 | 4
|
||||
}
|
||||
},
|
||||
]
|
||||
>('ns-ntApi-2', 'nodeIKernelMsgService/fetchMarketEmoticonAioImage')
|
||||
|
@ -11,6 +11,7 @@ export const groupMap: Record<string, Group> = {}
|
||||
export const roleMap: Record<string, Record<string, number>> = {}
|
||||
export const friendMap: Record<string, Profile> = {}
|
||||
export const richMediaDownloadMap: Record<string, (path: string) => void> = {}
|
||||
export const emojiDownloadMap: Record<string, (path: string) => void> = {}
|
||||
|
||||
export const sendQueue: ((msg: RedMessage) => void)[] = []
|
||||
export const sendCallbackMap: Record<string, (msg: RedMessage) => void> = {}
|
||||
|
@ -3,6 +3,7 @@ import type {
|
||||
MsgsIncludeSelf,
|
||||
OnAddSendMsg,
|
||||
OnBuddyListChange,
|
||||
OnEmojiDownloadComplete,
|
||||
OnGroupListUpdate,
|
||||
OnMemberInfoChange,
|
||||
OnMemberListChange,
|
||||
@ -20,6 +21,7 @@ import type { ChronocatContext } from '@chronocat/shell'
|
||||
import type { IpcManData } from 'ipcman'
|
||||
import {
|
||||
chronoEventEmitter,
|
||||
emojiDownloadMap,
|
||||
friendMap,
|
||||
groupMap,
|
||||
requestCallbackMap,
|
||||
@ -131,6 +133,19 @@ const responseDispatcher = async (
|
||||
return
|
||||
}
|
||||
|
||||
case 'nodeIKernelMsgListener/onEmojiDownloadComplete': {
|
||||
const { notifyInfo } = payload as OnEmojiDownloadComplete
|
||||
|
||||
const downloadId = `${notifyInfo.emojiPackageId}::${notifyInfo.emojiId}`
|
||||
|
||||
if (notifyInfo.downloadType === 0 && emojiDownloadMap[downloadId]) {
|
||||
emojiDownloadMap[downloadId]!(notifyInfo.path)
|
||||
delete emojiDownloadMap[downloadId]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
case 'nodeIKernelProfileListener/onProfileSimpleChanged':
|
||||
case 'nodeIKernelProfileListener/onProfileDetailInfoChanged':
|
||||
case 'nodeIKernelGroupListener/onSearchMemberChange':
|
||||
|
@ -552,6 +552,34 @@ async function parseElements(
|
||||
break
|
||||
}
|
||||
|
||||
case 11: {
|
||||
elements.push(
|
||||
ctx.chronocat.h(
|
||||
`${ctx.chronocat.platform}:marketface`,
|
||||
{
|
||||
tabId: m.marketFaceElement!.emojiPackageId,
|
||||
faceId: m.marketFaceElement!.emojiId,
|
||||
key: m.marketFaceElement!.key,
|
||||
},
|
||||
[
|
||||
ctx.chronocat.h('img', {
|
||||
src: `${config.self_url}/v1/assets/${Buffer.from(
|
||||
JSON.stringify({
|
||||
type: 'marketface',
|
||||
tabId: m.marketFaceElement!.emojiPackageId,
|
||||
faceId: m.marketFaceElement!.emojiId,
|
||||
key: m.marketFaceElement!.key,
|
||||
name: m.marketFaceElement!.faceName,
|
||||
filePath: m.marketFaceElement!.staticFacePath,
|
||||
}),
|
||||
).toString('base64url')}`,
|
||||
}),
|
||||
],
|
||||
),
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ export interface Element {
|
||||
inlineKeyboardElement?: InlineKeyboardElement
|
||||
liveGiftElement?: unknown
|
||||
markdownElement?: MarkdownElement
|
||||
marketFaceElement?: unknown
|
||||
marketFaceElement?: MarketFaceElement
|
||||
multiForwardMsgElement?: unknown
|
||||
pttElement?: PttElement
|
||||
replyElement?: ReplyElement
|
||||
@ -653,6 +653,17 @@ export interface Media {
|
||||
downloadType: number
|
||||
}
|
||||
|
||||
export interface MarketFaceAssetRequest {
|
||||
type: 'marketface'
|
||||
tabId: number
|
||||
faceId: string
|
||||
key: string
|
||||
name: string
|
||||
filePath: string
|
||||
}
|
||||
|
||||
export type AssetRequest = MarketFaceAssetRequest | Media
|
||||
|
||||
export interface InlineKeyboardElement {
|
||||
rows: InlineKeyboardRow[]
|
||||
}
|
||||
@ -762,6 +773,41 @@ export interface MarkdownElement {
|
||||
content: string
|
||||
}
|
||||
|
||||
export interface MarketFaceElement {
|
||||
itemType: 6
|
||||
faceInfo: 1
|
||||
emojiPackageId: number // 235125
|
||||
subType: 3
|
||||
mediaType: 0
|
||||
imageWidth: number // 200
|
||||
imageHeight: number // 200
|
||||
faceName: string // '[好耶]'
|
||||
emojiId: string // 'e6e7817c449efdea0be5ceeef3a40c06'
|
||||
key: string // 'ea4dc6c26b6f9c31'
|
||||
param: unknown
|
||||
mobileParam: unknown
|
||||
sourceType: 0
|
||||
startTime: 0
|
||||
endTime: 0
|
||||
emojiType: 1
|
||||
hasIpProduct: 0
|
||||
voiceItemHeightArr: unknown
|
||||
sourceName: unknown
|
||||
sourceJumpUrl: unknown
|
||||
sourceTypeName: string // ''
|
||||
backColor: unknown
|
||||
volumeColor: unknown
|
||||
staticFacePath: string
|
||||
dynamicFacePath: string
|
||||
supportSize: MarketFaceElementSupportSize[]
|
||||
apngSupportSize: unknown
|
||||
}
|
||||
|
||||
export interface MarketFaceElementSupportSize {
|
||||
width: number // 300
|
||||
height: number // 300
|
||||
}
|
||||
|
||||
export interface ArkElement {
|
||||
bytesData: string
|
||||
linkInfo: never
|
||||
|
@ -75,6 +75,27 @@ export interface OnRichMediaDownloadComplete {
|
||||
}
|
||||
}
|
||||
|
||||
export interface OnEmojiDownloadComplete {
|
||||
notifyInfo: {
|
||||
result: 0
|
||||
errMsg: string // ''
|
||||
emojiType: 0
|
||||
md5: string // ''
|
||||
resId: string // ''
|
||||
path: string
|
||||
extraData: Record<string, never>
|
||||
emojiId: string // '94c8ffa6977fd17e8b180b312cdddc28'
|
||||
emojiPackageId: string // '235125'
|
||||
|
||||
/**
|
||||
* 下载富媒体的类型。发送时 3 为 PNG,4 为动图;接收时 0 为 PNG,4 为动图。
|
||||
*/
|
||||
downloadType: 0 | 4
|
||||
|
||||
dynamicFacePath: string // ''
|
||||
}
|
||||
}
|
||||
|
||||
export interface OnGroupListUpdate {
|
||||
updateType: 1
|
||||
groupList: Group[]
|
||||
|
Loading…
Reference in New Issue
Block a user