refactor: 获取rkey后进行检查rkey是否正确

This commit is contained in:
linyuchen 2024-04-30 19:26:51 +08:00
parent 297c495df9
commit de4d901412
4 changed files with 108 additions and 126 deletions

View File

@ -82,12 +82,9 @@ export class ConfigUtil {
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8') fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8')
} }
private checkOldConfig( private checkOldConfig(currentConfig: Config | OB11Config,
currentConfig: Config | OB11Config,
oldConfig: Config | OB11Config, oldConfig: Config | OB11Config,
currentKey: string, currentKey: string, oldKey: string) {
oldKey: string,
) {
// 迁移旧的配置到新配置,避免用户重新填写配置 // 迁移旧的配置到新配置,避免用户重新填写配置
const oldValue = oldConfig[oldKey] const oldValue = oldConfig[oldKey]
if (oldValue) { if (oldValue) {

View File

@ -12,11 +12,10 @@ export interface OB11Config {
enableHttpHeart?: boolean enableHttpHeart?: boolean
} }
export interface CheckVersion { export interface CheckVersion {
result: boolean result: boolean,
version: string version: string
} }
export interface Config { export interface Config {
imageRKey?: string
ob11: OB11Config ob11: OB11Config
token?: string token?: string
heartInterval?: number // ms heartInterval?: number // ms
@ -29,6 +28,7 @@ export interface Config {
ffmpeg?: string // ffmpeg路径 ffmpeg?: string // ffmpeg路径
enablePoke?: boolean enablePoke?: boolean
musicSignUrl?: string musicSignUrl?: string
ignoreBeforeLoginMsg?: boolean
} }
export interface LLOneBotError { export interface LLOneBotError {

View File

@ -7,30 +7,26 @@ import {
ChatCacheList, ChatCacheList,
ChatCacheListItemBasic, ChatCacheListItemBasic,
ChatType, ChatType,
ElementType, ElementType, IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, RawMessage,
IMAGE_HTTP_HOST,
IMAGE_HTTP_HOST_NT,
RawMessage,
} from '../types' } from '../types'
import path from 'path' import path from 'path'
import fs from 'fs' import fs from 'fs'
import { ReceiveCmdS } from '../hook' import { ReceiveCmdS } from '../hook'
import { log } from '../../common/utils' import { log } from '../../common/utils'
import http from 'http' import https from 'https'
import { sleep } from '../../common/utils' import { sleep } from '../../common/utils'
import { hookApi } from '../external/moehook/hook' import { hookApi } from '../external/moehook/hook'
let privateImageRKey = '' let privateImageRKey = ''
let groupImageRKey = '' let groupImageRKey = ''
let lastGetRKeyTime = 0 let lastGetPrivateRKeyTime = 0
let lastGetGroupRKeyTime = 0
const rkeyExpireTime = 1000 * 60 * 30 const rkeyExpireTime = 1000 * 60 * 30
export class NTQQFileApi { export class NTQQFileApi {
static async getFileType(filePath: string) { static async getFileType(filePath: string) {
return await callNTQQApi<{ ext: string }>({ return await callNTQQApi<{ ext: string }>({
className: NTQQApiClass.FS_API, className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_TYPE, args: [filePath],
methodName: NTQQApiMethod.FILE_TYPE,
args: [filePath],
}) })
} }
@ -46,20 +42,16 @@ export class NTQQFileApi {
return await callNTQQApi<string>({ return await callNTQQApi<string>({
className: NTQQApiClass.FS_API, className: NTQQApiClass.FS_API,
methodName: NTQQApiMethod.FILE_COPY, methodName: NTQQApiMethod.FILE_COPY,
args: [ args: [{
{
fromPath: filePath, fromPath: filePath,
toPath: destPath, toPath: destPath,
}, }],
],
}) })
} }
static async getFileSize(filePath: string) { static async getFileSize(filePath: string) {
return await callNTQQApi<number>({ return await callNTQQApi<number>({
className: NTQQApiClass.FS_API, className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.FILE_SIZE, args: [filePath],
methodName: NTQQApiMethod.FILE_SIZE,
args: [filePath],
}) })
} }
@ -78,8 +70,7 @@ export class NTQQFileApi {
} }
const mediaPath = await callNTQQApi<string>({ const mediaPath = await callNTQQApi<string>({
methodName: NTQQApiMethod.MEDIA_FILE_PATH, methodName: NTQQApiMethod.MEDIA_FILE_PATH,
args: [ args: [{
{
path_info: { path_info: {
md5HexStr: md5, md5HexStr: md5,
fileName: fileName, fileName: fileName,
@ -90,8 +81,7 @@ export class NTQQFileApi {
downloadType: 1, downloadType: 1,
file_uuid: '', file_uuid: '',
}, },
}, }],
],
}) })
log('media path', mediaPath) log('media path', mediaPath)
await NTQQFileApi.copyFile(filePath, mediaPath) await NTQQFileApi.copyFile(filePath, mediaPath)
@ -105,15 +95,7 @@ export class NTQQFileApi {
} }
} }
static async downloadMedia( static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, force: boolean = false) {
msgId: string,
chatType: ChatType,
peerUid: string,
elementId: string,
thumbPath: string,
sourcePath: string,
force: boolean = false,
) {
// 用于下载收到的消息中的图片等 // 用于下载收到的消息中的图片等
if (sourcePath && fs.existsSync(sourcePath)) { if (sourcePath && fs.existsSync(sourcePath)) {
if (force) { if (force) {
@ -144,7 +126,7 @@ export class NTQQFileApi {
methodName: NTQQApiMethod.DOWNLOAD_MEDIA, methodName: NTQQApiMethod.DOWNLOAD_MEDIA,
args: apiParams, args: apiParams,
cbCmd: ReceiveCmdS.MEDIA_DOWNLOAD_COMPLETE, cbCmd: ReceiveCmdS.MEDIA_DOWNLOAD_COMPLETE,
cmdCB: (payload: { notifyInfo: { filePath: string; msgId: string } }) => { cmdCB: (payload: { notifyInfo: { filePath: string, msgId: string } }) => {
log('media 下载完成判断', payload.notifyInfo.msgId, msgId) log('media 下载完成判断', payload.notifyInfo.msgId, msgId)
return payload.notifyInfo.msgId == msgId return payload.notifyInfo.msgId == msgId
}, },
@ -153,16 +135,14 @@ export class NTQQFileApi {
} }
static async getImageSize(filePath: string) { static async getImageSize(filePath: string) {
return await callNTQQApi<{ width: number; height: number }>({ return await callNTQQApi<{ width: number, height: number }>({
className: NTQQApiClass.FS_API, className: NTQQApiClass.FS_API, methodName: NTQQApiMethod.IMAGE_SIZE, args: [filePath],
methodName: NTQQApiMethod.IMAGE_SIZE,
args: [filePath],
}) })
} }
static async getImageUrl(msg: RawMessage) { static async getImageUrl(msg: RawMessage) {
const isPrivateImage = msg.chatType !== ChatType.group const isPrivateImage = msg.chatType !== ChatType.group
const msgElement = msg.elements.find((e) => !!e.picElement) const msgElement = msg.elements.find(e => !!e.picElement)
if (!msgElement) { if (!msgElement) {
return '' return ''
} }
@ -185,42 +165,55 @@ export class NTQQFileApi {
const saveRKey = (rkey: string) => { const saveRKey = (rkey: string) => {
if (isPrivateImage) { if (isPrivateImage) {
privateImageRKey = rkey privateImageRKey = rkey
lastGetPrivateRKeyTime = Date.now()
} else { } else {
groupImageRKey = rkey groupImageRKey = rkey
lastGetGroupRKeyTime = Date.now()
} }
lastGetRKeyTime = Date.now()
} }
const refreshRKey = async () => { const refreshRKey = async () => {
log('获取图片rkey...') log('获取图片rkey...')
NTQQFileApi.downloadMedia( NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid, msgElement.elementId, '', msgElement.picElement.sourcePath, false).then().catch(() => {
msg.msgId, })
msg.chatType,
msg.peerUid,
msgElement.elementId,
'',
msgElement.picElement.sourcePath,
true,
)
.then()
.catch(() => {})
await sleep(1000) await sleep(1000)
const _rkey = hookApi.getRKey() const _rkey = hookApi.getRKey()
if (_rkey) { if (_rkey) {
const imageUrl = IMAGE_HTTP_HOST_NT + url + _rkey
// 验证_rkey是否有效
try {
await new Promise((res, rej) => {
https.get(imageUrl, response => {
if (response.statusCode !== 200) {
rej('图片rkey获取失败')
} else {
res(response)
}
}).on('error', e => {
rej(e)
})
})
log('图片rkey获取成功', _rkey) log('图片rkey获取成功', _rkey)
saveRKey(_rkey) saveRKey(_rkey)
return _rkey return _rkey
}catch (e) {
log('图片rkey有误', imageUrl)
}
} }
} }
const existsRKey = isPrivateImage ? privateImageRKey : groupImageRKey const existsRKey = isPrivateImage ? privateImageRKey : groupImageRKey
if (Date.now() - lastGetRKeyTime > rkeyExpireTime || !existsRKey) { const lastGetRKeyTime = isPrivateImage ? lastGetPrivateRKeyTime : lastGetGroupRKeyTime
if ((Date.now() - lastGetRKeyTime > rkeyExpireTime)) {
// rkey过期 // rkey过期
const newRKey = await refreshRKey() const newRKey = await refreshRKey()
if (newRKey) { if (newRKey) {
return IMAGE_HTTP_HOST_NT + url + `${newRKey}` return IMAGE_HTTP_HOST_NT + url + `${newRKey}`
} else { } else {
log('图片rkey获取失败', url) log('图片rkey获取失败', url)
if(existsRKey){
return IMAGE_HTTP_HOST_NT + url + `${existsRKey}`
}
return '' return ''
} }
} }
@ -239,55 +232,44 @@ export class NTQQFileApi {
log('图片url获取失败', msg) log('图片url获取失败', msg)
return '' return ''
} }
} }
export class NTQQFileCacheApi { export class NTQQFileCacheApi {
static async setCacheSilentScan(isSilent: boolean = true) { static async setCacheSilentScan(isSilent: boolean = true) {
return await callNTQQApi<GeneralCallResult>({ return await callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.CACHE_SET_SILENCE, methodName: NTQQApiMethod.CACHE_SET_SILENCE,
args: [ args: [{
{
isSilent, isSilent,
}, }, null],
null,
],
}) })
} }
static getCacheSessionPathList() { static getCacheSessionPathList() {
return callNTQQApi< return callNTQQApi<{
{ key: string,
key: string
value: string value: string
}[] }[]>({
>({
className: NTQQApiClass.OS_API, className: NTQQApiClass.OS_API,
methodName: NTQQApiMethod.CACHE_PATH_SESSION, methodName: NTQQApiMethod.CACHE_PATH_SESSION,
}) })
} }
static clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) { static clearCache(cacheKeys: Array<string> = ['tmp', 'hotUpdate']) {
return callNTQQApi<any>({ return callNTQQApi<any>({ // TODO: 目前还不知道真正的返回值是什么
// TODO: 目前还不知道真正的返回值是什么
methodName: NTQQApiMethod.CACHE_CLEAR, methodName: NTQQApiMethod.CACHE_CLEAR,
args: [ args: [{
{
keys: cacheKeys, keys: cacheKeys,
}, }, null],
null,
],
}) })
} }
static addCacheScannedPaths(pathMap: object = {}) { static addCacheScannedPaths(pathMap: object = {}) {
return callNTQQApi<GeneralCallResult>({ return callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.CACHE_ADD_SCANNED_PATH, methodName: NTQQApiMethod.CACHE_ADD_SCANNED_PATH,
args: [ args: [{
{
pathMap: { ...pathMap }, pathMap: { ...pathMap },
}, }, null],
null,
],
}) })
} }
@ -321,18 +303,14 @@ export class NTQQFileCacheApi {
return new Promise<ChatCacheList>((res, rej) => { return new Promise<ChatCacheList>((res, rej) => {
callNTQQApi<ChatCacheList>({ callNTQQApi<ChatCacheList>({
methodName: NTQQApiMethod.CACHE_CHAT_GET, methodName: NTQQApiMethod.CACHE_CHAT_GET,
args: [ args: [{
{
chatType: type, chatType: type,
pageSize, pageSize,
order: 1, order: 1,
pageIndex, pageIndex,
}, }, null],
null, }).then(list => res(list))
], .catch(e => rej(e))
})
.then((list) => res(list))
.catch((e) => rej(e))
}) })
} }
@ -341,29 +319,24 @@ export class NTQQFileCacheApi {
return callNTQQApi<CacheFileList>({ return callNTQQApi<CacheFileList>({
methodName: NTQQApiMethod.CACHE_FILE_GET, methodName: NTQQApiMethod.CACHE_FILE_GET,
args: [ args: [{
{
fileType: fileType, fileType: fileType,
restart: true, restart: true,
pageSize: pageSize, pageSize: pageSize,
order: 1, order: 1,
lastRecord: _lastRecord, lastRecord: _lastRecord,
}, }, null],
null,
],
}) })
} }
static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) { static async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {
return await callNTQQApi<GeneralCallResult>({ return await callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.CACHE_CHAT_CLEAR, methodName: NTQQApiMethod.CACHE_CHAT_CLEAR,
args: [ args: [{
{
chats, chats,
fileKeys, fileKeys,
}, }, null],
null,
],
}) })
} }
} }

12
test/check_image_url.js Normal file
View File

@ -0,0 +1,12 @@
import http from 'https'
function checkUrl(imageUrl) {
http.get(imageUrl, response => {
console.log(response.statusCode)
}).on('error', e => {
console.log(e)
})
}
checkUrl('https://gchat.qpic.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64')
checkUrl('https://multimedia.nt.qq.com.cn/download?appid=1407&fileid=CgoxMzMyNTI0MjIxEhRrdaUgQP5MjweWa4uR8pviUDaGQhjcxQUg_wooiYTj39fphQNQgL2jAQ&spec=0&rkey=CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64')