mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
fix
This commit is contained in:
parent
a56eac0251
commit
2245d0d3de
@ -1,6 +1,6 @@
|
|||||||
# LLOneBot
|
# LLOneBot
|
||||||
|
|
||||||
LiteLoaderQQNT 插件,实现 OneBot 11 协议,用以 QQ 机器人开发
|
LiteLoaderQQNT 插件,实现 OneBot 11 协议,用于 QQ 机器人开发
|
||||||
|
|
||||||
> [!CAUTION]\
|
> [!CAUTION]\
|
||||||
> **请不要在 QQ 官方群聊和任何影响力较大的简中互联网平台(包括但不限于: 哔哩哔哩,微博,知乎,抖音等)发布和讨论*任何*与本插件存在相关性的信息**
|
> **请不要在 QQ 官方群聊和任何影响力较大的简中互联网平台(包括但不限于: 哔哩哔哩,微博,知乎,抖音等)发布和讨论*任何*与本插件存在相关性的信息**
|
||||||
|
@ -6,7 +6,7 @@ const manifest = {
|
|||||||
type: 'extension',
|
type: 'extension',
|
||||||
name: 'LLOneBot',
|
name: 'LLOneBot',
|
||||||
slug: 'LLOneBot',
|
slug: 'LLOneBot',
|
||||||
description: '实现 OneBot 11 协议,用以 QQ 机器人开发',
|
description: '实现 OneBot 11 协议,用于 QQ 机器人开发',
|
||||||
version,
|
version,
|
||||||
icon: './icon.webp',
|
icon: './icon.webp',
|
||||||
authors: [
|
authors: [
|
||||||
|
@ -66,6 +66,7 @@ export async function getGroupMember(groupCode: string | number, memberUinOrUid:
|
|||||||
let member = getMember()
|
let member = getMember()
|
||||||
if (!member) {
|
if (!member) {
|
||||||
members = await NTQQGroupApi.getGroupMembers(groupCodeStr)
|
members = await NTQQGroupApi.getGroupMembers(groupCodeStr)
|
||||||
|
groupMembers.set(groupCodeStr, members)
|
||||||
member = getMember()
|
member = getMember()
|
||||||
}
|
}
|
||||||
return member
|
return member
|
||||||
|
@ -16,7 +16,7 @@ export class RequestUtil {
|
|||||||
const redirectUrl = new URL(res.headers.location, url);
|
const redirectUrl = new URL(res.headers.location, url);
|
||||||
RequestUtil.HttpsGetCookies(redirectUrl.href).then((redirectCookies) => {
|
RequestUtil.HttpsGetCookies(redirectUrl.href).then((redirectCookies) => {
|
||||||
// 合并重定向过程中的cookies
|
// 合并重定向过程中的cookies
|
||||||
log('redirectCookies', redirectCookies)
|
//log('redirectCookies', redirectCookies)
|
||||||
cookies = { ...cookies, ...redirectCookies };
|
cookies = { ...cookies, ...redirectCookies };
|
||||||
resolve(cookies);
|
resolve(cookies);
|
||||||
});
|
});
|
||||||
@ -33,7 +33,7 @@ export class RequestUtil {
|
|||||||
});
|
});
|
||||||
if (res.headers['set-cookie']) {
|
if (res.headers['set-cookie']) {
|
||||||
// console.log(res.headers['set-cookie']);
|
// console.log(res.headers['set-cookie']);
|
||||||
log('set-cookie', url, res.headers['set-cookie']);
|
//log('set-cookie', url, res.headers['set-cookie']);
|
||||||
res.headers['set-cookie'].forEach((cookie) => {
|
res.headers['set-cookie'].forEach((cookie) => {
|
||||||
const parts = cookie.split(';')[0].split('=');
|
const parts = cookie.split(';')[0].split('=');
|
||||||
const key = parts[0];
|
const key = parts[0];
|
||||||
|
@ -138,45 +138,47 @@ export class WebApi {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@CacheClassFuncAsync(3600 * 1000, 'webapi_get_group_members')
|
|
||||||
static async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> {
|
static async getGroupMembers(GroupCode: string, cached: boolean = true): Promise<WebApiGroupMember[]> {
|
||||||
//logDebug('webapi 获取群成员', GroupCode)
|
const memberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>()
|
||||||
let MemberData: Array<WebApiGroupMember> = new Array<WebApiGroupMember>()
|
const cookieObject = await NTQQUserApi.getCookies('qun.qq.com')
|
||||||
try {
|
const cookieStr = Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; ')
|
||||||
const CookiesObject = await NTQQUserApi.getCookies('qun.qq.com')
|
|
||||||
const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; ')
|
|
||||||
const Bkn = WebApi.genBkn(CookiesObject.skey)
|
|
||||||
const retList: Promise<WebApiGroupMemberRet>[] = []
|
const retList: Promise<WebApiGroupMemberRet>[] = []
|
||||||
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=0&end=40&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue });
|
const params = new URLSearchParams({
|
||||||
|
st: '0',
|
||||||
|
end: '40',
|
||||||
|
sort: '1',
|
||||||
|
gc: GroupCode,
|
||||||
|
bkn: WebApi.genBkn(cookieObject.skey)
|
||||||
|
})
|
||||||
|
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${params}`, 'POST', '', { 'Cookie': cookieStr })
|
||||||
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
|
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
|
||||||
return []
|
return []
|
||||||
} else {
|
} else {
|
||||||
for (const key in fastRet.mems) {
|
for (const member of fastRet.mems) {
|
||||||
MemberData.push(fastRet.mems[key])
|
memberData.push(member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//初始化获取PageNum
|
const pageNum = Math.ceil(fastRet.count / 40)
|
||||||
const PageNum = Math.ceil(fastRet.count / 40)
|
|
||||||
//遍历批量请求
|
//遍历批量请求
|
||||||
for (let i = 2; i <= PageNum; i++) {
|
for (let i = 2; i <= pageNum; i++) {
|
||||||
const ret: Promise<WebApiGroupMemberRet> = RequestUtil.HttpGetJson<WebApiGroupMemberRet>('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=' + (i - 1) * 40 + '&end=' + i * 40 + '&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue });
|
params.set('st', String((i - 1) * 40))
|
||||||
|
params.set('end', String(i * 40))
|
||||||
|
const ret = RequestUtil.HttpGetJson<WebApiGroupMemberRet>(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${params}`, 'POST', '', { 'Cookie': cookieStr })
|
||||||
retList.push(ret)
|
retList.push(ret)
|
||||||
}
|
}
|
||||||
//批量等待
|
//批量等待
|
||||||
for (let i = 1; i <= PageNum; i++) {
|
for (let i = 1; i <= pageNum; i++) {
|
||||||
const ret = await (retList[i])
|
const ret = await (retList[i])
|
||||||
if (!ret?.count || ret?.errcode !== 0 || !ret?.mems) {
|
if (!ret?.count || ret?.errcode !== 0 || !ret?.mems) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (const key in ret.mems) {
|
for (const member of ret.mems) {
|
||||||
MemberData.push(ret.mems[key])
|
memberData.push(member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
return memberData
|
||||||
return MemberData
|
|
||||||
}
|
|
||||||
return MemberData
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static async addGroupDigest(groupCode: string, msgSeq: string) {
|
// public static async addGroupDigest(groupCode: string, msgSeq: string) {
|
||||||
// const url = `https://qun.qq.com/cgi-bin/group_digest/cancel_digest?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&msg_seq=${msgSeq}&msg_random=444021292`;
|
// const url = `https://qun.qq.com/cgi-bin/group_digest/cancel_digest?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&msg_seq=${msgSeq}&msg_random=444021292`;
|
||||||
// const res = await this.request(url);
|
// const res = await this.request(url);
|
||||||
|
@ -10,7 +10,7 @@ export class OB11Response {
|
|||||||
data: data,
|
data: data,
|
||||||
message: message,
|
message: message,
|
||||||
wording: message,
|
wording: message,
|
||||||
echo: null,
|
echo: undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,33 +1,45 @@
|
|||||||
import { OB11GroupMember } from '../../types'
|
import { OB11GroupMember } from '../../types'
|
||||||
import { getGroupMember } from '../../../common/data'
|
import { getGroupMember, getSelfUid } from '@/common/data'
|
||||||
import { OB11Constructor } from '../../constructor'
|
import { OB11Constructor } from '../../constructor'
|
||||||
import BaseAction from '../BaseAction'
|
import BaseAction from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { NTQQUserApi } from '../../../ntqqapi/api/user'
|
import { NTQQUserApi, WebApi } from '@/ntqqapi/api'
|
||||||
|
import { isNull } from '@/common/utils/helper'
|
||||||
import { log } from '../../../common/utils/log'
|
import { log } from '../../../common/utils/log'
|
||||||
import { isNull } from '../../../common/utils/helper'
|
|
||||||
|
|
||||||
export interface PayloadType {
|
interface Payload {
|
||||||
group_id: number
|
group_id: number | string
|
||||||
user_id: number
|
user_id: number | string
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetGroupMemberInfo extends BaseAction<PayloadType, OB11GroupMember> {
|
class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
|
||||||
actionName = ActionName.GetGroupMemberInfo
|
actionName = ActionName.GetGroupMemberInfo
|
||||||
|
|
||||||
protected async _handle(payload: PayloadType) {
|
protected async _handle(payload: Payload) {
|
||||||
const member = await getGroupMember(payload.group_id.toString(), payload.user_id.toString())
|
const member = await getGroupMember(payload.group_id.toString(), payload.user_id.toString())
|
||||||
if (member) {
|
if (member) {
|
||||||
if (isNull(member.sex)) {
|
if (isNull(member.sex)) {
|
||||||
log('获取群成员详细信息')
|
//log('获取群成员详细信息')
|
||||||
let info = await NTQQUserApi.getUserDetailInfo(member.uid, true)
|
const info = await NTQQUserApi.getUserDetailInfo(member.uid, true)
|
||||||
log('群成员详细信息结果', info)
|
//log('群成员详细信息结果', info)
|
||||||
Object.assign(member, info)
|
Object.assign(member, info)
|
||||||
}
|
}
|
||||||
const ret = OB11Constructor.groupMember(payload.group_id.toString(), member)
|
const ret = OB11Constructor.groupMember(payload.group_id.toString(), member)
|
||||||
|
const self = await getGroupMember(payload.group_id.toString(), getSelfUid())
|
||||||
|
if (self?.role === 3 || self?.role === 4) {
|
||||||
|
const webGroupMembers = await WebApi.getGroupMembers(payload.group_id.toString())
|
||||||
|
const target = webGroupMembers.find(e => e?.uin && e.uin === ret.user_id)
|
||||||
|
log(target)
|
||||||
|
if (target) {
|
||||||
|
ret.join_time = target.join_time
|
||||||
|
ret.last_sent_time = target.last_speak_time
|
||||||
|
ret.qage = target.qage
|
||||||
|
ret.level = target.lv.level.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
const date = Math.round(Date.now() / 1000)
|
const date = Math.round(Date.now() / 1000)
|
||||||
ret.last_sent_time = Number(member.lastSpeakTime || date)
|
ret.last_sent_time ||= Number(member.lastSpeakTime || date)
|
||||||
ret.join_time = Number(member.joinTime || date)
|
ret.join_time ||= Number(member.joinTime || date)
|
||||||
return ret
|
return ret
|
||||||
} else {
|
} else {
|
||||||
throw `群成员${payload.user_id}不存在`
|
throw `群成员${payload.user_id}不存在`
|
||||||
|
@ -289,12 +289,12 @@ export async function sendMsg(
|
|||||||
log('文件大小计算失败', e, fileElement)
|
log('文件大小计算失败', e, fileElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log('发送消息总大小', totalSize, 'bytes')
|
//log('发送消息总大小', totalSize, 'bytes')
|
||||||
let timeout = ((totalSize / 1024 / 100) * 1000) + 5000 // 100kb/s
|
const timeout = 10000 + (totalSize / 1024 / 256 * 1000) // 10s Basic Timeout + PredictTime( For File 512kb/s )
|
||||||
log('设置消息超时时间', timeout)
|
//log('设置消息超时时间', timeout)
|
||||||
const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, timeout)
|
const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, timeout)
|
||||||
log('消息发送结果', returnMsg)
|
|
||||||
returnMsg.msgShortId = MessageUnique.createMsg(peer, returnMsg.msgId)
|
returnMsg.msgShortId = MessageUnique.createMsg(peer, returnMsg.msgId)
|
||||||
|
log('消息发送', returnMsg.msgShortId)
|
||||||
deleteAfterSentFiles.map(path => fsPromise.unlink(path))
|
deleteAfterSentFiles.map(path => fsPromise.unlink(path))
|
||||||
return returnMsg
|
return returnMsg
|
||||||
}
|
}
|
||||||
|
@ -61,13 +61,15 @@ export function postOb11Event(msg: PostEventType, reportSelf = false, postWs = t
|
|||||||
body: msgStr,
|
body: msgStr,
|
||||||
}).then(
|
}).then(
|
||||||
async (res) => {
|
async (res) => {
|
||||||
log(`新消息事件HTTP上报成功: ${host} `, msgStr)
|
if (msg.post_type) {
|
||||||
|
log(`HTTP 事件上报: ${host} `, msg.post_type)
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const resJson = await res.json()
|
const resJson = await res.json()
|
||||||
log(`新消息事件HTTP上报返回快速操作: `, JSON.stringify(resJson))
|
log(`新消息事件HTTP上报返回快速操作: `, JSON.stringify(resJson))
|
||||||
handleQuickOperation(msg as QuickOperationEvent, resJson).then().catch(log);
|
handleQuickOperation(msg as QuickOperationEvent, resJson).then().catch(log);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(`新消息事件HTTP上报没有返回快速操作,不需要处理`)
|
//log(`新消息事件HTTP上报没有返回快速操作,不需要处理`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
import { WebSocket as WebSocketClass } from 'ws'
|
import { WebSocket as WebSocketClass } from 'ws'
|
||||||
import { OB11Response } from '../../action/OB11Response'
|
|
||||||
import { PostEventType } from '../post-ob11-event'
|
import { PostEventType } from '../post-ob11-event'
|
||||||
import { log } from '../../../common/utils/log'
|
import { log } from '@/common/utils/log'
|
||||||
import { isNull } from '../../../common/utils/helper'
|
import { OB11Return } from '../../types'
|
||||||
|
|
||||||
export function wsReply(wsClient: WebSocketClass, data: OB11Response | PostEventType) {
|
export function wsReply(wsClient: WebSocketClass, data: OB11Return<any> | PostEventType) {
|
||||||
try {
|
try {
|
||||||
const packet = Object.assign({}, data)
|
wsClient.send(JSON.stringify(data))
|
||||||
if (isNull(packet['echo'])) {
|
if (data['post_type']) {
|
||||||
delete packet['echo']
|
log('WebSocket 事件上报', wsClient.url ?? '', data['post_type'])
|
||||||
}
|
}
|
||||||
wsClient.send(JSON.stringify(packet))
|
|
||||||
//log('ws 消息上报', wsClient.url || '', data)
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
log('websocket 回复失败', e.stack, data)
|
log('WebSocket 上报失败', e.stack, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user