Compare commits

..

36 Commits

Author SHA1 Message Date
idranme
ac5fe4d275 Merge pull request #485 from LLOneBot/dev
release: 4.1.0
2024-10-24 22:11:38 +08:00
linyuchen
4aadcd5288 Update README.md contributors 2024-10-21 17:14:54 +08:00
idranme
2f74de667e Merge pull request #481 from LLOneBot/dev
release: 4.0.13
2024-10-19 18:21:27 +08:00
idranme
8b89fd7a0b Merge pull request #479 from LLOneBot/dev
release: 4.0.12
2024-10-18 21:16:46 +08:00
idranme
8239e9a243 Merge pull request #477 from LLOneBot/dev
release: 4.0.11
2024-10-16 11:44:43 +08:00
idranme
951afea794 Merge pull request #475 from LLOneBot/dev
release: 4.0.10
2024-10-15 21:09:42 +08:00
idranme
a4beeba528 Merge pull request #474 from LLOneBot/dev
release: 4.0.9
2024-10-13 23:51:30 +08:00
idranme
9b32140f87 Merge pull request #470 from LLOneBot/dev
release: 4.0.8
2024-10-13 16:36:12 +08:00
idranme
e10a67ce05 Merge pull request #468 from LLOneBot/dev
release: 4.0.7
2024-10-13 01:30:01 +08:00
idranme
e07c06f3e9 Merge pull request #467 from LLOneBot/dev
...
2024-10-13 01:17:06 +08:00
idranme
0d8d3ac24f Merge pull request #466 from LLOneBot/dev
release: 4.0.6
2024-10-13 00:48:36 +08:00
idranme
9d0f9e7096 Merge pull request #465 from LLOneBot/dev
release: 4.0.5
2024-10-12 23:58:07 +08:00
idranme
e988908784 Merge pull request #463 from LLOneBot/dev
release: 4.0.4
2024-10-11 18:22:37 +08:00
idranme
b40c81c5cb Merge pull request #462 from LLOneBot/dev
release: 4.0.3
2024-10-11 00:52:33 +08:00
idranme
457ffc0922 Merge pull request #461 from LLOneBot/dev
release: 4.0.2
2024-10-08 21:26:39 +08:00
idranme
41822eb052 Merge pull request #460 from LLOneBot/dev
release: 4.0.1
2024-10-08 20:46:09 +08:00
idranme
0bc6e23343 Merge pull request #459 from LLOneBot/dev
release: 4.0.0
2024-10-07 20:26:59 +08:00
idranme
9ec09c6eee Merge pull request #457 from LLOneBot/dev
release: 3.34.1
2024-10-03 15:18:47 +08:00
idranme
0876e4645f Merge pull request #456 from LLOneBot/dev
release: 3.34.0
2024-10-01 21:32:24 +08:00
idranme
36d990e328 Merge pull request #452 from LLOneBot/dev
release: 3.33.10
2024-09-28 14:40:11 +08:00
idranme
d5875c9e5b Merge pull request #451 from LLOneBot/dev
release: 3.33.9
2024-09-27 16:53:44 +08:00
idranme
a58fb31f8e Merge pull request #448 from LLOneBot/dev
release: 3.33.8
2024-09-26 12:57:16 +08:00
idranme
f9270c38cf Merge pull request #444 from LLOneBot/dev
release: 3.33.7
2024-09-25 14:59:34 +08:00
idranme
e5ab6134cd Merge pull request #441 from LLOneBot/dev
release: 3.33.6
2024-09-23 23:43:50 +08:00
idranme
24f09d485e Merge pull request #438 from LLOneBot/dev
release: 3.33.5
2024-09-22 21:31:55 +08:00
idranme
f400d43b8a Merge pull request #436 from LLOneBot/dev
release: 3.33.4
2024-09-21 23:29:47 +08:00
idranme
1c6364d98f Merge pull request #435 from LLOneBot/dev
release: 3.33.3
2024-09-21 21:52:54 +08:00
idranme
ac07c98ae1 Merge pull request #434 from LLOneBot/dev
release: 3.33.2
2024-09-20 23:00:09 +08:00
idranme
6c66dab3dc Merge pull request #433 from LLOneBot/dev
release: 3.33.1
2024-09-19 18:31:01 +08:00
idranme
936b1d911c Merge pull request #428 from LLOneBot/dev
release: 3.33.0
2024-09-18 20:59:57 +08:00
idranme
1876dd29ac Merge pull request #423 from LLOneBot/dev
release: 3.32.8
2024-09-17 11:59:57 +08:00
idranme
64c5eb6c04 Merge pull request #422 from LLOneBot/dev
release: 3.32.7
2024-09-16 20:48:15 +08:00
idranme
476d498e44 Merge pull request #417 from LLOneBot/dev
release: 3.32.6
2024-09-15 17:48:35 +08:00
idranme
b03bcf9a7c Merge pull request #415 from LLOneBot/dev
release: 3.32.5
2024-09-13 18:59:37 +08:00
idranme
9284fc7e8a Merge pull request #413 from LLOneBot/dev
3.32.4
2024-09-12 18:14:23 +08:00
idranme
1d63473a04 Merge pull request #411 from LLOneBot/dev
3.32.3
2024-09-11 20:52:52 +08:00
20 changed files with 1677 additions and 82 deletions

View File

@@ -23,6 +23,10 @@ TG 群:<https://t.me/+nLZEnpne-pQ1OWFl>
[![Stargazers over time](https://starchart.cc/LLOneBot/LLOneBot.svg?variant=adaptive)](https://starchart.cc/LLOneBot/LLOneBot)
## 贡献者
[![Contributors](https://contributors-img.web.app/image?repo=LLOneBot/LLOneBot)](https://github.com/LOneBot/LLOneBot/graphs/contributors)
## 鸣谢
- [NapCatQQ](https://github.com/NapNeko/NapCatQQ)

View File

@@ -4,16 +4,12 @@
"name": "LLOneBot",
"slug": "LLOneBot",
"description": "实现 OneBot 11 和 Satori 协议,用于 QQ 机器人开发",
"version": "4.1.3",
"version": "4.1.0",
"icon": "./icon.webp",
"authors": [
{
"name": "linyuchen",
"link": "https://github.com/linyuchen"
},
{
"name": "idranme",
"link": "https://github.com/idranme"
}
],
"repository": {
@@ -34,4 +30,4 @@
"main": "./main/main.cjs",
"preload": "./preload/preload.cjs"
}
}
}

View File

@@ -12,7 +12,7 @@
"deploy-win": "cmd /c \"xcopy /C /S /Y dist\\* %LITELOADERQQNT_PROFILE%\\plugins\\LLOneBot\\\"",
"format": "prettier -cw .",
"check": "tsc",
"compile:proto": "pbjs --no-create --no-convert --no-delimited --no-verify -t static-module -w es6 -p src/ntqqapi/proto -o src/ntqqapi/proto/compiled.js profileLikeTip.proto groupNotify.proto message.proto richMedia.proto && pbts -o src/ntqqapi/proto/compiled.d.ts src/ntqqapi/proto/compiled.js"
"compile:proto": "pbjs --no-create --no-convert --no-verify -t static-module -w es6 -p src/ntqqapi/proto -o src/ntqqapi/proto/compiled.js profileLikeTip.proto groupNotify.proto message.proto richMedia.proto && pbts -o src/ntqqapi/proto/compiled.d.ts src/ntqqapi/proto/compiled.js"
},
"author": "",
"license": "MIT",
@@ -28,7 +28,7 @@
"fluent-ffmpeg": "^2.1.3",
"minato": "^3.6.0",
"protobufjs": "^7.4.0",
"silk-wasm": "^3.6.3",
"silk-wasm": "^3.6.1",
"ts-case-convert": "^2.1.0",
"ws": "^8.18.0"
},
@@ -42,7 +42,7 @@
"electron-vite": "^2.3.0",
"protobufjs-cli": "^1.1.3",
"typescript": "^5.6.3",
"vite": "^5.4.10 ",
"vite": "^5.4.9",
"vite-plugin-cp": "^4.0.8"
},
"packageManager": "yarn@4.5.1"

View File

@@ -122,11 +122,8 @@ export async function uri2local(ctx: Context, uri: string, needExt?: boolean): P
const { type } = checkUriType(uri)
if (type === FileUriType.FileURL) {
const fileUri = uri.replace('%', '%25').replace('#', '%23')
const filePath = fileURLToPath(fileUri)
const filePath = fileURLToPath(uri)
const fileName = path.basename(filePath)
// console.log('fileURLToPath', filePath)
// console.log('fileName', fileName)
return { success: true, errMsg: '', fileName, path: filePath, isLocal: true }
}

View File

@@ -185,7 +185,7 @@ function onLoad() {
if (config.enableLLOB && (config.satori.enable || config.ob11.enable)) {
startHook()
await ctx.sleep(600)
await ctx.sleep(350)
} else {
llonebotError.otherError = 'LLOneBot 未启动'
log('LLOneBot 开关设置为关闭,不启动 LLOneBot')
@@ -225,7 +225,7 @@ function onLoad() {
started = true
llonebotError.otherError = ''
}
}, 500)
}, 600)
}
// 创建窗口时触发

View File

@@ -43,7 +43,7 @@ export class NTQQFileApi extends Service {
msgId,
elemId: elementId,
videoCodecFormat: 0,
exParams: {
params: {
downSourceType: 1,
triggerType: 1
}

View File

@@ -110,9 +110,8 @@ export class NTQQGroupApi extends Service {
const groupCode = flagitem[0]
const seq = flagitem[1]
const type = parseInt(flagitem[2])
const doubt = flagitem[3] === '1'
return await invoke(NTMethod.HANDLE_GROUP_REQUEST, [{
doubt,
doubt: false,
operateMsg: {
operateType,
targetMsg: {

View File

@@ -153,17 +153,7 @@ export class NTQQMsgApi extends Service {
afterFirstCmd: false,
cmdCB: payload => {
for (const msgRecord of payload.msgList) {
if (
msgRecord.msgType === 11 &&
msgRecord.subMsgType === 7 &&
msgRecord.peerUid === destPeer.peerUid &&
msgRecord.senderUid === selfUid
) {
const element = msgRecord.elements[0]
const data = JSON.parse(element.arkElement!.bytesData)
if (data.app !== 'com.tencent.multimsg' || !data.meta.detail.resid) {
continue
}
if (msgRecord.peerUid === destPeer.peerUid && msgRecord.senderUid === selfUid) {
return true
}
}
@@ -171,12 +161,20 @@ export class NTQQMsgApi extends Service {
}
}
)
return data.msgList.find(msgRecord => {
const { arkElement } = msgRecord.elements[0]
if (arkElement?.bytesData.includes('com.tencent.multimsg')) {
return true
for (const msg of data.msgList) {
const arkElement = msg.elements.find(ele => ele.arkElement)
if (!arkElement) {
continue
}
})!
const forwardData = JSON.parse(arkElement.arkElement!.bytesData)
if (forwardData.app !== 'com.tencent.multimsg') {
continue
}
if (msg.peerUid === destPeer.peerUid && msg.senderUid === selfUid) {
return msg
}
}
throw new Error('转发消息超时')
}
async getSingleMsg(peer: Peer, msgSeq: string) {

View File

@@ -16,7 +16,7 @@ import {
BuddyReqType,
GrayTipElementSubType
} from './types'
import { selfInfo } from '../common/globalVars'
import { selfInfo, llonebotError } from '../common/globalVars'
import { version } from '../version'
import { invoke } from './ntcall'
import { Native } from './native/index'
@@ -29,7 +29,7 @@ declare module 'cordis' {
'nt/message-created': (input: RawMessage) => void
'nt/message-deleted': (input: RawMessage) => void
'nt/message-sent': (input: RawMessage) => void
'nt/group-notify': (input: { notify: GroupNotify, doubt: boolean }) => void
'nt/group-notify': (input: GroupNotify) => void
'nt/friend-request': (input: FriendRequest) => void
'nt/group-member-info-updated': (input: { groupCode: string, members: GroupMember[] }) => void
'nt/system-message-created': (input: Uint8Array) => void
@@ -228,7 +228,7 @@ class Core extends Service {
continue
}
groupNotifyIgnore.push(notify.seq)
this.ctx.parallel('nt/group-notify', { notify, doubt: payload.doubt })
this.ctx.parallel('nt/group-notify', notify)
}
}
})

View File

@@ -70,12 +70,10 @@ export function startHook() {
delete hookApiCallbacks[callbackId]
}
} else if (args[2]) {
if (['IPC_DOWN_2', 'IPC_DOWN_3'].includes(args[0])) {
for (const receiveData of args[2]) {
for (const hook of receiveHooks.values()) {
if (hook.method.includes(receiveData.cmdName)) {
Promise.resolve(hook.hookFunc(receiveData.payload))
}
for (const receiveData of args[2]) {
for (const hook of receiveHooks.values()) {
if (hook.method.includes(receiveData.cmdName)) {
Promise.resolve(hook.hookFunc(receiveData.payload))
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -23,8 +23,8 @@ interface FileResponse {
export class DownloadFile extends BaseAction<Payload, FileResponse> {
actionName = ActionName.GoCQHTTP_DownloadFile
payloadSchema = Schema.object({
url: Schema.string(),
base64: Schema.string(),
url: String,
base64: String,
headers: Schema.union([String, Schema.array(String)])
})

View File

@@ -19,7 +19,7 @@ interface Payload {
interface Response {
message_id: number
forward_id: string
forward_id?: string
}
export class SendForwardMsg extends BaseAction<Payload, Response> {
@@ -60,11 +60,14 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
}
}
let msg: RawMessage
if (fake && this.ctx.app.native.activated) {
return await this.handleFakeForwardNode(peer, nodes)
msg = await this.handleFakeForwardNode(peer, nodes)
} else {
return await this.handleForwardNode(peer, nodes)
msg = await this.handleForwardNode(peer, nodes)
}
const msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
return { message_id: msgShortId }
}
private parseNodeContent(nodes: OB11MessageNode[]) {
@@ -79,7 +82,7 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
})
}
private async handleFakeForwardNode(peer: Peer, nodes: OB11MessageNode[]): Promise<Response> {
private async handleFakeForwardNode(peer: Peer, nodes: OB11MessageNode[]) {
const encoder = new MessageEncoder(this.ctx, peer)
const raw = await encoder.generate(nodes)
const transmit = Msg.PbMultiMsgTransmit.encode({ pbItemList: raw.multiMsgItems }).finish()
@@ -119,11 +122,7 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
})
}
}], 1800)
const msgShortId = this.ctx.store.createMsgShortId({
chatType: msg!.chatType,
peerUid: msg!.peerUid
}, msg!.msgId)
return { message_id: msgShortId, forward_id: resid }
return msg!
} catch (e) {
this.ctx.logger.error('合并转发失败', e)
throw new Error(`发送伪造合并转发消息失败 (res_id: ${resid} `)
@@ -154,7 +153,7 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
}
// 返回一个合并转发的消息id
private async handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<Response> {
private async handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]) {
const selfPeer = {
chatType: ChatType.C2C,
peerUid: selfInfo.uid,
@@ -246,13 +245,8 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
if (retMsgIds.length === 0) {
throw Error('转发消息失败,节点为空')
}
const msg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds)
const resid = JSON.parse(msg.elements[0].arkElement!.bytesData).meta.detail.resid
const msgShortId = this.ctx.store.createMsgShortId({
chatType: msg.chatType,
peerUid: msg.peerUid
}, msg.msgId)
return { message_id: msgShortId, forward_id: resid }
const returnMsg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds)
return returnMsg
}
}

View File

@@ -15,6 +15,7 @@ import { OB11Config, Config as LLOBConfig } from '../common/types'
import { OB11WebSocket, OB11WebSocketReverseManager } from './connect/ws'
import { OB11Http, OB11HttpPost } from './connect/http'
import { OB11BaseEvent } from './event/OB11BaseEvent'
import { OB11Message } from './types'
import { OB11BaseMetaEvent } from './event/meta/OB11BaseMetaEvent'
import { postHttpEvent } from './helper/eventForHttp'
import { initActionMap } from './action'
@@ -87,9 +88,9 @@ class OneBot11Adapter extends Service {
}
}
private async handleGroupNotify(notify: GroupNotify, doubt: boolean) {
private async handleGroupNotify(notify: GroupNotify) {
try {
const flag = `${notify.group.groupCode}|${notify.seq}|${notify.type}|${doubt === true ? '1' : '0'}`
const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type
if ([GroupNotifyType.MemberLeaveNotifyAdmin, GroupNotifyType.KickMemberNotifyAdmin].includes(notify.type)) {
if (notify.user2.uid) {
this.ctx.logger.info('有群成员被踢', notify.group.groupCode, notify.user1.uid, notify.user2.uid)
@@ -337,8 +338,7 @@ class OneBot11Adapter extends Service {
this.handleMsg(input)
})
this.ctx.on('nt/group-notify', input => {
const { doubt, notify } = input
this.handleGroupNotify(notify, doubt)
this.handleGroupNotify(input)
})
this.ctx.on('nt/friend-request', input => {
this.handleFriendRequest(input)
@@ -370,6 +370,12 @@ class OneBot11Adapter extends Service {
const userId = Number(memberUin)
const event = new OB11GroupDecreaseEvent(tip.groupCode, userId, userId)
this.dispatch(event)
} else if (msgType === 87) {
const tip = SysMsg.GroupInvite.decode(sysMsg.body!.msgContent!)
this.ctx.logger.info('群成员增加', tip)
const operatorUin = await this.ctx.ntUserApi.getUinByUid(tip.operatorUid)
const event = new OB11GroupIncreaseEvent(tip.groupCode, +selfInfo.uin, +operatorUin, 'invite')
this.dispatch(event)
}
})
}

View File

@@ -478,13 +478,6 @@ export namespace OB11Entities {
)
}
}
else if (groupElement.type === TipGroupElementType.MemberIncrease) {
const { memberUid, adminUid } = groupElement
if (memberUid !== selfInfo.uid) return
ctx.logger.info('收到群成员增加消息', groupElement)
const adminUin = adminUid ? await ctx.ntUserApi.getUinByUid(adminUid) : selfInfo.uin
return new OB11GroupIncreaseEvent(+msg.peerUid, +selfInfo.uin, +adminUin)
}
}
else if (element.fileElement) {
return new OB11GroupUploadNoticeEvent(+msg.peerUid, +msg.senderUin!, {
@@ -527,6 +520,7 @@ export namespace OB11Entities {
ctx.logger.info('收到新人被邀请进群消息', xmlElement)
const invitor = xmlElement.templParam.get('invitor')
const invitee = xmlElement.templParam.get('invitee')
if (invitee === selfInfo.uin) return
if (invitor && invitee) {
return new OB11GroupIncreaseEvent(+msg.peerUid, +invitee, +invitor, 'invite')
}

View File

@@ -174,7 +174,7 @@ export class MessageEncoder {
const { type, data } = segment
if (type === OB11MessageDataType.Node) {
await this.render(data.content as OB11MessageData[])
const id = data.uin ?? data.user_id
const id = data.id ?? data.user_id
this.uin = id ? +id : undefined
this.name = data.name ?? data.nickname
await this.flush()

View File

@@ -99,7 +99,7 @@ class SatoriAdapter extends Service {
}
}
async handleGroupNotify(input: NT.GroupNotify, doubt: boolean) {
async handleGroupNotify(input: NT.GroupNotify) {
if (
input.type === NT.GroupNotifyType.InvitedByMember &&
input.status === NT.GroupNotifyStatus.Unhandle
@@ -119,14 +119,14 @@ class SatoriAdapter extends Service {
input.status === NT.GroupNotifyStatus.Unhandle
) {
// 他人主动申请,需管理员同意
return await parseGuildMemberRequest(this, input, doubt)
return await parseGuildMemberRequest(this, input)
}
else if (
input.type === NT.GroupNotifyType.InvitedNeedAdminiStratorPass &&
input.status === NT.GroupNotifyStatus.Unhandle
) {
// 他人被邀请,需管理员同意
return await parseGuildMemberRequest(this, input, doubt)
return await parseGuildMemberRequest(this, input)
}
}
@@ -140,8 +140,7 @@ class SatoriAdapter extends Service {
})
this.ctx.on('nt/group-notify', async input => {
const { doubt, notify } = input
const event = await this.handleGroupNotify(notify, doubt)
const event = await this.handleGroupNotify(input)
.catch(e => this.ctx.logger.error(e))
event && this.server.dispatch(event)
})

View File

@@ -46,9 +46,9 @@ export async function parseGuildMemberRemoved(bot: SatoriAdapter, input: GroupNo
})
}
export async function parseGuildMemberRequest(bot: SatoriAdapter, input: GroupNotify, doubt: boolean) {
export async function parseGuildMemberRequest(bot: SatoriAdapter, input: GroupNotify) {
const groupCode = input.group.groupCode
const flag = `${groupCode}|${input.seq}|${input.type}|${doubt === true ? '1' : '0'}`
const flag = groupCode + '|' + input.seq + '|' + input.type
return bot.event('guild-member-request', {
guild: decodeGuild(input.group),

View File

@@ -1 +1 @@
export const version = '4.1.3'
export const version = '4.1.0'