Compare commits

..

13 Commits

Author SHA1 Message Date
idranme
36d990e328 Merge pull request #452 from LLOneBot/dev
release: 3.33.10
2024-09-28 14:40:11 +08:00
idranme
0ceef4d4c0 chore: v3.33.10 2024-09-28 14:37:44 +08:00
idranme
35bf4f001b feat: _get_group_notice API 2024-09-28 14:35:06 +08:00
idranme
544682fe41 fix 2024-09-28 12:54:02 +08:00
idranme
3da49fbfba optimize 2024-09-27 18:37:47 +08:00
idranme
d5875c9e5b Merge pull request #451 from LLOneBot/dev
release: 3.33.9
2024-09-27 16:53:44 +08:00
idranme
7895644156 chore: v3.33.9 2024-09-27 16:51:49 +08:00
idranme
f092626ede fix 2024-09-27 16:22:50 +08:00
idranme
a58fb31f8e Merge pull request #448 from LLOneBot/dev
release: 3.33.8
2024-09-26 12:57:16 +08:00
idranme
fe85e277f1 chore: v3.33.8 2024-09-26 12:54:30 +08:00
idranme
5217638b46 feat 2024-09-26 01:52:47 +08:00
idranme
f68b707e1c optimize 2024-09-25 22:34:59 +08:00
idranme
c24ce6ec65 adjustment of get_friends_with_category API returns 2024-09-25 22:04:52 +08:00
27 changed files with 368 additions and 154 deletions

View File

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

View File

@@ -32,7 +32,7 @@
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/express": "^5.0.0",
"@types/fluent-ffmpeg": "^2.1.26",
"@types/node": "^20.14.15",
"@types/ws": "^8.5.12",
@@ -40,7 +40,7 @@
"electron-vite": "^2.3.0",
"protobufjs-cli": "^1.1.3",
"typescript": "^5.6.2",
"vite": "^5.4.7",
"vite": "^5.4.8",
"vite-plugin-cp": "^4.0.8"
},
"packageManager": "yarn@4.5.0"

View File

@@ -236,7 +236,7 @@ export class NTQQFileCacheApi extends Service {
}
scanCache() {
invoke<GeneralCallResult>(ReceiveCmdS.CACHE_SCAN_FINISH, [], { classNameIsRegister: true })
invoke<GeneralCallResult>(ReceiveCmdS.CACHE_SCAN_FINISH, [], { registerEvent: true })
return invoke<CacheScanResult>(NTMethod.CACHE_SCAN, [null, null], { timeout: 300 * Time.second })
}

View File

@@ -101,52 +101,20 @@ export class NTQQFriendApi extends Service {
return retMap
}
async getBuddyV2ExWithCate(refresh = false) {
const session = getSession()
if (session) {
const uids: string[] = []
const categoryMap: Map<string, Dict> = new Map()
const buddyService = session.getBuddyService()
const buddyListV2 = (await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL)).data
uids.push(
...buddyListV2.flatMap(item => {
item.buddyUids.forEach(uid => {
categoryMap.set(uid, { categoryId: item.categoryId, categroyName: item.categroyName })
})
return item.buddyUids
}))
const data = await session.getProfileService().getCoreAndBaseInfo('nodeStore', uids)
return Array.from(data).map(([key, value]) => {
const category = categoryMap.get(key)
return category ? { ...value, categoryId: category.categoryId, categroyName: category.categroyName } : value
})
} else {
const data = await invoke<{
buddyCategory: CategoryFriend[]
userSimpleInfos: Record<string, SimpleInfo>
}>(
'getBuddyList',
[refresh],
{
className: NTClass.NODE_STORE_API,
cbCmd: ReceiveCmdS.FRIENDS,
afterFirstCmd: false,
}
)
const category: Map<number, Pick<CategoryFriend, 'buddyUids' | 'categroyName'>> = new Map()
for (const item of data.buddyCategory) {
category.set(item.categoryId, pick(item, ['buddyUids', 'categroyName']))
async getBuddyV2WithCate(refresh = false) {
const data = await invoke<{
buddyCategory: CategoryFriend[]
userSimpleInfos: Record<string, SimpleInfo>
}>(
'getBuddyList',
[refresh],
{
className: NTClass.NODE_STORE_API,
cbCmd: ReceiveCmdS.FRIENDS,
afterFirstCmd: false,
}
return Object.values(data.userSimpleInfos)
.filter(v => v.baseInfo && category.get(v.baseInfo.categoryId)?.buddyUids.includes(v.uid!))
.map(value => {
return {
...value,
categoryId: value.baseInfo.categoryId,
categroyName: category.get(value.baseInfo.categoryId)?.categroyName
}
})
}
)
return data
}
async isBuddy(uid: string): Promise<boolean> {

View File

@@ -6,8 +6,10 @@ import {
GroupNotifies,
GroupRequestOperateTypes,
GetFileListParam,
OnGroupFileInfoUpdateParams,
PublishGroupBulletinReq
PublishGroupBulletinReq,
GroupAllInfo,
GroupFileInfo,
GroupBulletinListResult
} from '../types'
import { invoke, NTClass, NTMethod } from '../ntcall'
import { GeneralCallResult } from '../services'
@@ -104,7 +106,7 @@ export class NTQQGroupApi extends Service {
}
async getSingleScreenNotifies(num: number) {
invoke(ReceiveCmdS.GROUP_NOTIFY, [], { classNameIsRegister: true })
invoke(ReceiveCmdS.GROUP_NOTIFY, [], { registerEvent: true })
return (await invoke<GroupNotifies>(
'nodeIKernelGroupService/getSingleScreenNotifies',
[{ doubt: false, startSeq: '', number: num }, null],
@@ -272,8 +274,8 @@ export class NTQQGroupApi extends Service {
}
async getGroupFileList(groupId: string, fileListForm: GetFileListParam) {
invoke('nodeIKernelMsgListener/onGroupFileInfoUpdate', [], { classNameIsRegister: true })
const data = await invoke<{ fileInfo: OnGroupFileInfoUpdateParams }>(
invoke('nodeIKernelMsgListener/onGroupFileInfoUpdate', [], { registerEvent: true })
const data = await invoke<{ fileInfo: GroupFileInfo }>(
'nodeIKernelRichMediaService/getGroupFileList',
[
{
@@ -326,4 +328,53 @@ export class NTQQGroupApi extends Service {
}
}, null])
}
async getGroupAllInfo(groupCode: string, timeout = 1000) {
invoke('nodeIKernelGroupListener/onGroupAllInfoChange', [], { registerEvent: true })
return await invoke<{ groupAll: GroupAllInfo }>(
'nodeIKernelGroupService/getGroupAllInfo',
[
{
groupCode,
source: 4
},
null
],
{
cbCmd: 'nodeIKernelGroupListener/onGroupAllInfoChange',
afterFirstCmd: false,
cmdCB: payload => payload.groupAll.groupCode === groupCode,
timeout
}
)
}
async getGroupBulletinList(groupCode: string) {
invoke('nodeIKernelGroupListener/onGetGroupBulletinListResult', [], { registerEvent: true })
const ntUserApi = this.ctx.get('ntUserApi')!
const psKey = (await ntUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!
return await invoke<{
groupCode: string
context: string
result: GroupBulletinListResult
}>(
'nodeIKernelGroupService/getGroupBulletinList',
[{
groupCode,
psKey,
context: '',
req: {
startIndex: -1,
num: 20,
needInstructionsForJoinGroup: 1,
needPublisherInfo: 1
}
}],
{
cbCmd: 'nodeIKernelGroupListener/onGetGroupBulletinListResult',
cmdCB: payload => payload.groupCode === groupCode,
afterFirstCmd: false
}
)
}
}

View File

@@ -215,7 +215,7 @@ class Core extends Service {
this.ctx.parallel('nt/friend-request', payload.data.buddyReqs)
})
invoke('nodeIKernelMsgListener/onRecvSysMsg', [], { classNameIsRegister: true })
invoke('nodeIKernelMsgListener/onRecvSysMsg', [], { registerEvent: true })
registerReceiveHook<{
msgBuf: number[]

View File

@@ -98,7 +98,7 @@ interface NTService {
interface InvokeOptions<ReturnType> {
className?: NTClass
channel?: NTChannel
classNameIsRegister?: boolean
registerEvent?: boolean
cbCmd?: string | string[]
cmdCB?: (payload: ReturnType, result: unknown) => boolean
afterFirstCmd?: boolean // 是否在methodName调用完之后再去hook cbCmd
@@ -115,7 +115,7 @@ export function invoke<
const timeout = options.timeout ?? 5000
const afterFirstCmd = options.afterFirstCmd ?? true
let eventName = className + '-' + channel[channel.length - 1]
if (options.classNameIsRegister) {
if (options.registerEvent) {
eventName += '-register'
}
return new Promise<R>((resolve, reject) => {
@@ -159,9 +159,9 @@ export function invoke<
afterFirstCmd && secondCallback()
}
else {
log('ntqq api call failed,', method, res)
log('ntqq api call failed,', method, args, res)
clearTimeout(timeoutId)
reject(`ntqq api call failed, ${method}, ${res.errMsg}`)
reject(`ntqq api call failed, ${method}, ${res?.errMsg}`)
}
}
}

View File

@@ -22,9 +22,9 @@ export interface Group {
hasModifyConfGroupName: boolean
remarkName: string
hasMemo: boolean
groupShutupExpireTime: string //"0",
personShutupExpireTime: string //"0",
discussToGroupUin: string //"0",
groupShutupExpireTime: string
personShutupExpireTime: string
discussToGroupUin: string
discussToGroupMaxMsgSeq: number
discussToGroupTime: number
groupFlagExt: number //1073938496,
@@ -32,8 +32,8 @@ export interface Group {
groupCreditLevel: number //0,
groupFlagExt3: number //0,
groupOwnerId: {
memberUin: string //"0",
memberUid: string //"u_fbf8N7aeuZEnUiJAbQ9R8Q"
memberUin: string
memberUid: string
}
members: GroupMember[] // 原始数据是没有这个的,为了方便自己加了这个字段
createTime: string
@@ -78,3 +78,97 @@ export interface PublishGroupBulletinReq {
pinned: number
confirmRequired: number
}
export interface GroupAllInfo {
groupCode: string
ownerUid: string
groupFlag: number
groupFlagExt: number
maxMemberNum: number
memberNum: number
groupOption: number
classExt: number
groupName: string
fingerMemo: string
groupQuestion: string
certType: number
shutUpAllTimestamp: number
shutUpMeTimestamp: number //解除禁言时间
groupTypeFlag: number
privilegeFlag: number
groupSecLevel: number
groupFlagExt3: number
isConfGroup: number
isModifyConfGroupFace: number
isModifyConfGroupName: number
noFigerOpenFlag: number
noCodeFingerOpenFlag: number
groupFlagExt4: number
groupMemo: string
cmdUinMsgSeq: number
cmdUinJoinTime: number
cmdUinUinFlag: number
cmdUinMsgMask: number
groupSecLevelInfo: number
cmdUinPrivilege: number
cmdUinFlagEx2: number
appealDeadline: number
remarkName: number
isTop: boolean
richFingerMemo: string
groupAnswer: string
joinGroupAuth: string
isAllowModifyConfGroupName: number
}
export interface GroupBulletinListResult {
groupCode: string
srvCode: number
readOnly: number
role: number
inst: unknown[]
feeds: {
uin: string
feedId: string
publishTime: string
msg: {
text: string
textFace: string
pics: {
id: string
width: number
height: number
}[]
title: string
}
type: number
fn: number
cn: number
vn: number
settings: {
isShowEditCard: number
remindTs: number
tipWindowType: number
confirmRequired: number
}
pinned: number
readNum: number
is_read: number
is_all_confirm: number
}[]
groupInfo: {
groupCode: string
classId: number
}
gln: number
tst: number
publisherInfos: {
uin: string
nick: string
avatar: string
}[]
server_time: string
svrt: string
nextIndex: number
jointime: string
}

View File

@@ -478,7 +478,7 @@ export interface OnRichMediaDownloadCompleteParams {
userUsedSpacePerDay: unknown
}
export interface OnGroupFileInfoUpdateParams {
export interface GroupFileInfo {
retCode: number
retMsg: string
clientWording: string

View File

@@ -34,25 +34,23 @@ export class GetForwardMsg extends BaseAction<Payload, Response> {
if (data?.result !== 0) {
throw Error('找不到相关的聊天记录' + data?.errMsg)
}
const msgList = data.msgList
const messages = await Promise.all(
msgList.map(async (msg) => {
const resMsg = await OB11Entities.message(this.ctx, msg)
if (!resMsg) return
resMsg.message_id = this.ctx.store.createMsgShortId({
chatType: msg.chatType,
peerUid: msg.peerUid,
}, msg.msgId)
return resMsg
const messages: (OB11ForwardMessage | undefined)[] = await Promise.all(
data.msgList.map(async (msg) => {
const res = await OB11Entities.message(this.ctx, msg)
if (res) {
return {
content: res.message,
sender: {
nickname: res.sender.nickname,
user_id: res.sender.user_id
},
time: res.time,
message_format: res.message_format,
message_type: res.message_type
}
}
})
)
const forwardMessages = filterNullable(messages)
.map(v => {
const msg = v as Partial<OB11ForwardMessage>
msg.content = msg.message
delete msg.message
return msg as OB11ForwardMessage
})
return { messages: forwardMessages }
return { messages: filterNullable(messages) }
}
}

View File

@@ -2,6 +2,7 @@ import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
import { pathToFileURL } from 'node:url'
import { ChatType } from '@/ntqqapi/types'
import { GroupFileInfo } from '@/ntqqapi/types'
export interface Payload {
group_id: number | string
@@ -30,23 +31,7 @@ export class GetGroupFileUrl extends BaseAction<Payload, Response> {
}
} else {
const groupId = payload.group_id.toString()
let modelId: string | undefined
let nextIndex: number | undefined
while (nextIndex !== 0) {
const res = await this.ctx.ntGroupApi.getGroupFileList(groupId, {
sortType: 1,
fileCount: 50,
startIndex: nextIndex ?? 0,
sortOrder: 2,
showOnlinedocFolder: 0,
})
const file = res.item.find(item => item.fileInfo?.fileId === payload.file_id)
if (file) {
modelId = file.fileInfo?.fileModelId
break
}
nextIndex = res.nextIndex
}
const modelId = await this.search(groupId, payload.file_id)
if (modelId) {
const peer = {
chatType: ChatType.Group,
@@ -61,4 +46,37 @@ export class GetGroupFileUrl extends BaseAction<Payload, Response> {
throw new Error('file not found')
}
}
private async search(groupId: string, fileId: string, folderId?: string) {
let modelId: string | undefined
let nextIndex: number | undefined
let folders: GroupFileInfo['item'] = []
while (nextIndex !== 0) {
const res = await this.ctx.ntGroupApi.getGroupFileList(groupId, {
sortType: 1,
fileCount: 100,
startIndex: nextIndex ?? 0,
sortOrder: 2,
showOnlinedocFolder: 0,
folderId
})
const file = res.item.find(item => item.fileInfo?.fileId === fileId)
if (file) {
modelId = file.fileInfo?.fileModelId
break
}
folders.push(...res.item.filter(item => item.folderInfo?.totalFileCount))
nextIndex = res.nextIndex
}
if (!modelId) {
for (const item of folders) {
const res = await this.search(groupId, fileId, item.folderInfo?.folderId)
if (res) {
modelId = res
break
}
}
}
return modelId
}
}

View File

@@ -1,7 +1,7 @@
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
import { OB11GroupFile, OB11GroupFileFolder } from '@/onebot11/types'
import { OnGroupFileInfoUpdateParams } from '@/ntqqapi/types'
import { GroupFileInfo } from '@/ntqqapi/types'
interface Payload {
group_id: number | string
@@ -22,7 +22,7 @@ export class GetGroupFilesByFolder extends BaseAction<Payload, Response> {
async _handle(payload: Payload) {
const groupId = payload.group_id.toString()
const data: OnGroupFileInfoUpdateParams['item'] = []
const data: GroupFileInfo['item'] = []
let nextIndex: number | undefined
while (nextIndex !== 0) {

View File

@@ -0,0 +1,48 @@
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {
group_id: number | string
}
interface Notice {
sender_id: number
publish_time: number
message: {
text: string
images: {
height: string
width: string
id: string
}[]
}
}
export class GetGroupNotice extends BaseAction<Payload, Notice[]> {
actionName = ActionName.GoCQHTTP_GetGroupNotice
payloadSchema = Schema.object({
group_id: Schema.union([Number, String]).required()
})
protected async _handle(payload: Payload) {
const data = await this.ctx.ntGroupApi.getGroupBulletinList(payload.group_id.toString())
const result: Notice[] = []
for (const feed of data.result.feeds) {
result.push({
sender_id: +feed.uin,
publish_time: +feed.publishTime,
message: {
text: feed.msg.text,
images: feed.msg.pics.map(image => {
return {
height: String(image.height),
width: String(image.width),
id: image.id
}
})
}
})
}
return result
}
}

View File

@@ -1,7 +1,7 @@
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
import { OB11GroupFile, OB11GroupFileFolder } from '../../types'
import { OnGroupFileInfoUpdateParams } from '@/ntqqapi/types'
import { GroupFileInfo } from '@/ntqqapi/types'
interface Payload {
group_id: number | string
@@ -20,7 +20,7 @@ export class GetGroupRootFiles extends BaseAction<Payload, Response> {
async _handle(payload: Payload) {
const groupId = payload.group_id.toString()
const data: OnGroupFileInfoUpdateParams['item'] = []
const data: GroupFileInfo['item'] = []
let nextIndex: number | undefined
while (nextIndex !== 0) {

View File

@@ -10,7 +10,8 @@ import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePee
interface Payload {
user_id?: string | number
group_id?: string | number
messages: OB11MessageNode[]
messages?: OB11MessageNode[]
message?: OB11MessageNode[]
message_type?: 'group' | 'private'
}
@@ -20,15 +21,20 @@ interface Response {
}
export class SendForwardMsg extends BaseAction<Payload, Response> {
actionName = ActionName.GoCQHTTP_SendForwardMsg
actionName = ActionName.SendForwardMsg
payloadSchema = Schema.object({
user_id: Schema.union([Number, String]),
group_id: Schema.union([Number, String]),
messages: Schema.array(Schema.any()).required(),
messages: Schema.array(Schema.any()),
message: Schema.array(Schema.any()),
message_type: Schema.union(['group', 'private'])
})
protected async _handle(payload: Payload) {
const messages = payload.messages ?? payload.message
if (!messages) {
throw new Error('未指定消息内容')
}
let contextMode = CreatePeerMode.Normal
if (payload.message_type === 'group') {
contextMode = CreatePeerMode.Group
@@ -36,7 +42,7 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
contextMode = CreatePeerMode.Private
}
const peer = await createPeer(this.ctx, payload, contextMode)
const msg = await this.handleForwardNode(peer, payload.messages)
const msg = await this.handleForwardNode(peer, messages)
const msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
return { message_id: msgShortId }
}

View File

@@ -4,7 +4,7 @@ import { ActionName } from '../types'
interface Payload {
group_id: number | string
user_id: number | string
duration: number
duration: number | string
}
export default class SetGroupBan extends BaseAction<Payload, null> {
@@ -12,7 +12,7 @@ export default class SetGroupBan extends BaseAction<Payload, null> {
payloadSchema = Schema.object({
group_id: Schema.union([Number, String]).required(),
user_id: Schema.union([Number, String]).required(),
duration: Schema.number().default(30 * 60)
duration: Schema.union([Number, String]).default(30 * 60)
})
protected async _handle(payload: Payload): Promise<null> {
@@ -21,7 +21,7 @@ export default class SetGroupBan extends BaseAction<Payload, null> {
const uid = await this.ctx.ntUserApi.getUidByUin(uin, groupCode)
if (!uid) throw new Error('无法获取用户信息')
await this.ctx.ntGroupApi.banMember(groupCode, [
{ uid, timeStamp: payload.duration },
{ uid, timeStamp: +payload.duration },
])
return null
}

View File

@@ -70,6 +70,7 @@ import { GetFriendWithCategory } from './llonebot/GetFriendWithCategory'
import { UploadGroupFile } from './go-cqhttp/UploadGroupFile'
import { UploadPrivateFile } from './go-cqhttp/UploadPrivateFile'
import { GetGroupFileUrl } from './go-cqhttp/GetGroupFileUrl'
import { GetGroupNotice } from './go-cqhttp/GetGroupNotice'
export function initActionMap(adapter: Adapter) {
const actionHandlers = [
@@ -144,7 +145,8 @@ export function initActionMap(adapter: Adapter) {
new GetGroupRootFiles(adapter),
new SendGroupNotice(adapter),
new GetGroupFilesByFolder(adapter),
new GetGroupFileUrl(adapter)
new GetGroupFileUrl(adapter),
new GetGroupNotice(adapter),
]
const actionMap = new Map<string, BaseAction<any, unknown>>()
for (const action of actionHandlers) {

View File

@@ -4,14 +4,35 @@ import { OB11Entities } from '../../entities'
import { ActionName } from '../types'
import { getBuildVersion } from '@/common/utils'
export class GetFriendWithCategory extends BaseAction<void, OB11User[]> {
interface Category {
categoryId: number
categorySortId: number
categoryName: string
categoryMbCount: number
onlineCount: number
buddyList: OB11User[]
}
export class GetFriendWithCategory extends BaseAction<void, Category[]> {
actionName = ActionName.GetFriendsWithCategory
protected async _handle() {
if (getBuildVersion() >= 26702) {
return OB11Entities.friendsV2(await this.ctx.ntFriendApi.getBuddyV2ExWithCate(true))
} else {
if (getBuildVersion() < 26702) {
throw new Error('this ntqq version not support, must be 26702 or later')
}
const data = await this.ctx.ntFriendApi.getBuddyV2WithCate(true)
return data.buddyCategory.map(item => {
return {
categoryId: item.categoryId,
categorySortId: item.categorySortId,
categoryName: item.categroyName,
categoryMbCount: item.categroyMbCount,
onlineCount: item.onlineCount,
buddyList: item.buddyUids.map(uid => {
const info = data.userSimpleInfos[uid]
return OB11Entities.friendV2(info)
})
}
})
}
}

View File

@@ -24,6 +24,7 @@ export enum ActionName {
FetchEmojiLike = 'fetch_emoji_like',
FetchCustomFace = 'fetch_custom_face',
GetFriendMsgHistory = 'get_friend_msg_history',
SendForwardMsg = 'send_forward_msg',
// onebot 11
SendLike = 'send_like',
GetLoginInfo = 'get_login_info',
@@ -58,7 +59,6 @@ export enum ActionName {
ForwardFriendSingleMsg = 'forward_friend_single_msg',
ForwardGroupSingleMsg = 'forward_group_single_msg',
// 以下为go-cqhttp api
GoCQHTTP_SendForwardMsg = 'send_forward_msg',
GoCQHTTP_SendGroupForwardMsg = 'send_group_forward_msg',
GoCQHTTP_SendPrivateForwardMsg = 'send_private_forward_msg',
GoCQHTTP_GetStrangerInfo = 'get_stranger_info',
@@ -82,5 +82,6 @@ export enum ActionName {
GoCQHTTP_GetGroupRootFiles = 'get_group_root_files',
GoCQHTTP_SendGroupNotice = '_send_group_notice',
GoCQHTTP_GetGroupFilesByFolder = 'get_group_files_by_folder',
GoCQHTTP_GetGroupFileUrl = 'get_group_file_url'
GoCQHTTP_GetGroupFileUrl = 'get_group_file_url',
GoCQHTTP_GetGroupNotice = '_get_group_notice',
}

View File

@@ -5,7 +5,6 @@ import {
GroupNotifyType,
RawMessage,
BuddyReqType,
Peer,
FriendRequest,
GroupMember,
GroupMemberRole,

View File

@@ -1,7 +1,7 @@
import http from 'node:http'
import cors from 'cors'
import crypto from 'node:crypto'
import express, { Express, Request, Response } from 'express'
import express, { Express, Request, Response, NextFunction } from 'express'
import { BaseAction } from '../action/BaseAction'
import { Context } from 'cordis'
import { llonebotError, selfInfo } from '@/common/globalVars'
@@ -76,7 +76,7 @@ class OB11Http {
Object.assign(this.config, config)
}
private authorize(req: Request, res: Response, next: () => void) {
private authorize(req: Request, res: Response, next: NextFunction) {
const serverToken = this.config.token
if (!serverToken) return next()
@@ -95,12 +95,13 @@ class OB11Http {
}
if (clientToken !== serverToken) {
return res.status(403).json({ message: 'token verify failed!' })
res.status(403).json({ message: 'token verify failed!' })
} else {
next()
}
next()
}
private async handleRequest(req: Request, res: Response, next: () => void) {
private async handleRequest(req: Request, res: Response, next: NextFunction) {
if (req.path === '/') return next()
let payload = req.body
if (req.method === 'GET') {

View File

@@ -72,7 +72,3 @@ export function encodeCQCode(input: OB11MessageData) {
result += ']'
return result
}
// const result = parseCQCode("[CQ:at,qq=114514]早上好啊[CQ:image,file=http://baidu.com/1.jpg,type=show,id=40004]")
// const result = parseCQCode("好好好")
// console.log(JSON.stringify(result))

View File

@@ -129,7 +129,7 @@ export namespace OB11Entities {
}
else if (element.textElement) {
const text = element.textElement.content
if (!text.trim()) {
if (!text) {
continue
}
messageSegment = {
@@ -359,15 +359,15 @@ export namespace OB11Entities {
}
if (messageSegment) {
const cqCode = encodeCQCode(messageSegment)
if (messagePostFormat === 'string') {
(resMsg.message as string) += cqCode
} else {
if (messagePostFormat === 'array') {
(resMsg.message as OB11MessageData[]).push(messageSegment)
}
resMsg.raw_message += cqCode
}
}
resMsg.raw_message = resMsg.raw_message.trim()
if (messagePostFormat === 'string') {
resMsg.message = resMsg.raw_message
}
return resMsg
}
@@ -436,7 +436,7 @@ export namespace OB11Entities {
}
}
else if (groupElement.type === TipGroupElementType.Ban) {
ctx.logger.info('收到群员禁言提示', groupElement)
ctx.logger.info('收到群员禁言提示', groupElement)
const memberUid = groupElement.shutUp?.member.uid
const adminUid = groupElement.shutUp?.admin.uid
let memberUin: string = ''
@@ -649,23 +649,20 @@ export namespace OB11Entities {
return friends.map(friend)
}
export function friendsV2(friends: FriendV2[]): OB11User[] {
const data: OB11User[] = []
for (const friend of friends) {
const sexValue = sex(friend.baseInfo.sex!)
data.push({
...omit(friend.baseInfo, ['richBuffer']),
...friend.coreInfo,
user_id: parseInt(friend.coreInfo.uin),
nickname: friend.coreInfo.nick,
remark: friend.coreInfo.nick,
sex: sexValue,
level: 0,
categroyName: friend.categroyName,
categoryId: friend.categoryId
})
export function friendV2(raw: FriendV2): OB11User {
return {
...omit(raw.baseInfo, ['richBuffer', 'phoneNum']),
...omit(raw.coreInfo, ['nick']),
user_id: parseInt(raw.coreInfo.uin),
nickname: raw.coreInfo.nick,
remark: raw.coreInfo.remark || raw.coreInfo.nick,
sex: sex(raw.baseInfo.sex),
level: 0
}
return data
}
export function friendsV2(raw: FriendV2[]): OB11User[] {
return raw.map(friendV2)
}
export function groupMemberRole(role: number): OB11GroupMemberRole | undefined {

View File

@@ -248,8 +248,16 @@ export async function sendMsg(
sendElements: SendMessageElement[],
deleteAfterSentFiles: string[]
) {
if (peer.chatType === ChatType.Group) {
const info = await ctx.ntGroupApi.getGroupAllInfo(peer.peerUid)
.catch(() => undefined)
const shutUpMeTimestamp = info?.groupAll.shutUpMeTimestamp
if (shutUpMeTimestamp && shutUpMeTimestamp * 1000 > Date.now()) {
throw new Error('当前处于被禁言状态')
}
}
if (!sendElements.length) {
throw '消息体无法解析,请检查是否发送了不支持的消息类型'
throw new Error('消息体无法解析,请检查是否发送了不支持的消息类型')
}
// 计算发送的文件大小
let totalSize = 0

View File

@@ -98,8 +98,15 @@ export interface OB11Message {
temp_source?: 0 | 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9
}
export interface OB11ForwardMessage extends OB11Message {
export interface OB11ForwardMessage {
content: OB11MessageData[] | string
sender: {
nickname: string
user_id: number
}
time: number
message_format: string //扩展
message_type: string //扩展
}
export interface OB11Return<DataType> {

View File

@@ -1 +1 @@
export const version = '3.33.7'
export const version = '3.33.10'

View File

@@ -4,7 +4,6 @@
"module": "CommonJS",
"outDir": "./dist",
"strict": true,
"isolatedModules": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,