Merge pull request #438 from LLOneBot/dev

release: 3.33.5
This commit is contained in:
idranme 2024-09-22 21:31:55 +08:00 committed by GitHub
commit 24f09d485e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 41 additions and 101 deletions

View File

@ -4,7 +4,7 @@
"name": "LLOneBot",
"slug": "LLOneBot",
"description": "实现 OneBot 11 协议,用于 QQ 机器人开发",
"version": "3.33.4",
"version": "3.33.5",
"icon": "./icon.webp",
"authors": [
{

View File

@ -18,7 +18,6 @@
"license": "MIT",
"dependencies": {
"@minatojs/driver-sqlite": "^4.6.0",
"compressing": "^1.10.1",
"cordis": "^3.18.1",
"cors": "^2.8.5",
"cosmokit": "^1.6.2",

View File

@ -190,26 +190,3 @@ export async function uri2local(uri: string, filename?: string, needExt?: boolea
return { success: false, errMsg: '未知文件类型', fileName: '', path: '', isLocal: false }
}
export async function copyFolder(sourcePath: string, destPath: string) {
try {
const entries = await fsPromise.readdir(sourcePath, { withFileTypes: true })
await fsPromise.mkdir(destPath, { recursive: true })
for (const entry of entries) {
const srcPath = path.join(sourcePath, entry.name)
const dstPath = path.join(destPath, entry.name)
if (entry.isDirectory()) {
await copyFolder(srcPath, dstPath)
} else {
try {
await fsPromise.copyFile(srcPath, dstPath)
} catch (error) {
console.error(`无法复制文件 '${srcPath}' 到 '${dstPath}': ${error}`)
// 这里可以决定是否要继续复制其他文件
}
}
}
} catch (error) {
console.error('复制文件夹时出错:', error)
}
}

View File

@ -1,9 +1,8 @@
import path from 'node:path'
import compressing from 'compressing'
import { writeFile } from 'node:fs/promises'
import { version } from '../../version'
import { copyFolder, log, fetchFile } from '.'
import { PLUGIN_DIR, TEMP_DIR } from '../globalVars'
import { log, fetchFile } from '.'
import { TEMP_DIR } from '../globalVars'
const downloadMirrorHosts = ['https://ghp.ci/']
const releasesMirrorHosts = ['https://kkgithub.com']
@ -27,49 +26,21 @@ export async function checkNewVersion() {
return { result: false, version: version }
}
export async function upgradeLLOneBot() {
export async function upgradeLLOneBot(): Promise<boolean> {
const latestVersion = await getRemoteVersion()
if (latestVersion && latestVersion != '') {
const downloadUrl = `https://github.com/LLOneBot/LLOneBot/releases/download/v${latestVersion}/LLOneBot.zip`
const filePath = path.join(TEMP_DIR, './update-' + latestVersion + '.zip')
let downloadSuccess = false
// 多镜像下载
for (const mirrorGithub of downloadMirrorHosts) {
try {
const res = await fetchFile(mirrorGithub + downloadUrl)
await writeFile(filePath, res.data)
downloadSuccess = true
break
return globalThis.LiteLoader.api.plugin.install(filePath)
} catch (e) {
log('llonebot upgrade error', e)
}
}
if (!downloadSuccess) {
log('llonebot upgrade error', 'download failed')
return false
}
const temp_ver_dir = path.join(TEMP_DIR, 'LLOneBot' + latestVersion)
const uncompressedPromise = async function () {
return new Promise<boolean>(resolve => {
compressing.zip
.uncompress(filePath, temp_ver_dir)
.then(() => {
resolve(true)
})
.catch(reason => {
log('llonebot upgrade failed, ', reason)
if (reason?.errno == -4082) {
resolve(true)
}
resolve(false)
})
})
}
const uncompressedResult = await uncompressedPromise()
// 复制文件
await copyFolder(temp_ver_dir, PLUGIN_DIR)
return uncompressedResult
}
return false
}

View File

@ -267,6 +267,12 @@ export class NTQQMsgApi extends Service {
}
async generateMsgUniqueId(chatType: number) {
return await invoke('nodeIKernelMsgService/generateMsgUniqueId', [{ chatType }])
const uniqueId = await invoke('nodeIKernelMsgService/generateMsgUniqueId', [{ chatType }])
if (typeof uniqueId === 'string') {
return uniqueId
} else {
const random = Math.trunc(Math.random() * 100)
return `${Date.now()}${random}`
}
}
}

View File

@ -1,5 +1,6 @@
import ffmpeg from 'fluent-ffmpeg'
import faceConfig from './helper/face_config.json'
import pathLib from 'node:path'
import {
AtType,
ElementType,
@ -132,7 +133,6 @@ export namespace SendElementEntities {
if (fileSize > 1024 * 1024 * maxMB) {
throw `视频过大,最大支持${maxMB}MB当前文件大小${fileSize}B`
}
const pathLib = require('path')
let thumbDir = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`)
thumbDir = pathLib.dirname(thumbDir)
// log("thumb 目录", thumb)

View File

@ -29,9 +29,8 @@ export class GetGroupMsgHistory extends BaseAction<Payload, Response> {
protected async _handle(payload: Payload): Promise<Response> {
const { count, reverseOrder } = payload
const peer = { chatType: ChatType.group, peerUid: payload.group_id.toString() }
let msgList: RawMessage[] | undefined
// 包含 message_seq 0
if (!payload.message_seq) {
let msgList: RawMessage[]
if (!payload.message_seq || payload.message_seq === '0') {
msgList = (await this.ctx.ntMsgApi.getAioFirstViewLatestMsgs(peer, +count)).msgList
} else {
const startMsgId = (await this.ctx.store.getMsgInfoByShortId(+payload.message_seq))?.msgId
@ -40,12 +39,10 @@ export class GetGroupMsgHistory extends BaseAction<Payload, Response> {
}
if (!msgList?.length) throw new Error('未找到消息')
if (reverseOrder) msgList.reverse()
await Promise.all(
msgList.map(async msg => {
msg.msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
})
)
const ob11MsgList = await Promise.all(msgList.map((msg) => OB11Entities.message(this.ctx, msg)))
for (const msg of msgList) {
msg.msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
}
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Entities.message(this.ctx, msg)))
return { messages: filterNullable(ob11MsgList) }
}
}

View File

@ -12,8 +12,6 @@ import { handleQuickOperation, QuickOperationEvent } from '../helper/quickOperat
import { OB11HeartbeatEvent } from '../event/meta/OB11HeartbeatEvent'
import { Dict } from 'cosmokit'
type RegisterHandler = (res: Response, payload: unknown) => Promise<unknown>
class OB11Http {
private readonly expressAPP: Express
private server?: http.Server
@ -25,7 +23,6 @@ class OB11Http {
this.expressAPP.use(express.urlencoded({ extended: true, limit: '5000mb' }))
this.expressAPP.use((req, res, next) => {
// 兼容处理没有带content-type的请求
// log("req.headers['content-type']", req.headers['content-type'])
req.headers['content-type'] = 'application/json'
const originalJson = express.json({ limit: '5000mb' })
// 调用原始的express.json()处理器
@ -37,12 +34,8 @@ class OB11Http {
next()
})
})
setTimeout(() => {
for (const [actionName, action] of config.actionMap) {
this.registerRouter('post', actionName, (res, payload) => action.handle(payload))
this.registerRouter('get', actionName, (res, payload) => action.handle(payload))
}
}, 0)
this.expressAPP.use((req, res, next) => this.authorize(req, res, next))
this.expressAPP.use((req, res, next) => this.handleRequest(req, res, next))
}
public start() {
@ -85,6 +78,8 @@ class OB11Http {
private authorize(req: Request, res: Response, next: () => void) {
const serverToken = this.config.token
if (!serverToken) return next()
let clientToken = ''
const authHeader = req.get('authorization')
if (authHeader) {
@ -99,36 +94,31 @@ class OB11Http {
this.ctx.logger.info('receive http url token', clientToken)
}
if (serverToken && clientToken !== serverToken) {
return res.status(403).send(JSON.stringify({ message: 'token verify failed!' }))
if (clientToken !== serverToken) {
return res.status(403).json({ message: 'token verify failed!' })
}
next()
}
private registerRouter(method: 'post' | 'get', url: string, handler: RegisterHandler) {
if (!url.startsWith('/')) {
url = '/' + url
private async handleRequest(req: Request, res: Response, next: () => void) {
if (req.path === '/') return next()
let payload = req.body
if (req.method === 'GET') {
payload = req.query
} else if (req.query) {
payload = { ...req.query, ...req.body }
}
if (!this.expressAPP[method]) {
const err = `LLOneBot server register router failed${method} not exist`
this.ctx.logger.error(err)
throw err
}
this.expressAPP[method](url, this.authorize.bind(this), async (req: Request, res: Response) => {
let payload = req.body
if (method == 'get') {
payload = req.query
} else if (req.query) {
payload = { ...req.query, ...req.body }
}
this.ctx.logger.info('收到 HTTP 请求', url, payload)
this.ctx.logger.info('收到 HTTP 请求', req.url, payload)
const action = this.config.actionMap.get(req.path.replaceAll('/', ''))
if (action) {
try {
res.send(await handler(res, payload))
res.json(await action.handle(payload))
} catch (e) {
res.send(OB11Response.error((e as Error).stack!.toString(), 200))
res.json(OB11Response.error((e as Error).stack!.toString(), 200))
}
})
} else {
res.status(404).json(OB11Response.error('API 不存在', 404))
}
}
}

View File

@ -1 +1 @@
export const version = '3.33.4'
export const version = '3.33.5'