This commit is contained in:
idranme 2024-10-09 02:55:12 +08:00
parent e3a2303e45
commit 91d78f22f7
11 changed files with 82 additions and 65 deletions

View File

@ -73,7 +73,7 @@ export class NTQQGroupApi extends Service {
cbCmd: 'nodeIKernelGroupListener/onMemberInfoChange', cbCmd: 'nodeIKernelGroupListener/onMemberInfoChange',
afterFirstCmd: false, afterFirstCmd: false,
cmdCB: payload => payload.members.has(uid), cmdCB: payload => payload.members.has(uid),
timeout: 2000 timeout: 3000
} }
) )
return data.members.get(uid)! return data.members.get(uid)!

View File

@ -123,8 +123,8 @@ export function invoke<
const apiArgs = [method, ...args] const apiArgs = [method, ...args]
const callbackId = randomUUID() const callbackId = randomUUID()
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
log(`ntqq api timeout ${channel}, ${eventName}, ${method}`, apiArgs) log(`ntqq api timeout ${channel}, ${eventName}, ${method}`, args)
reject(`ntqq api timeout ${channel}, ${eventName}, ${method}, ${apiArgs}`) reject(`ntqq api timeout ${channel}, ${eventName}, ${method}, ${JSON.stringify(args)}`)
}, timeout) }, timeout)
if (!options.cbCmd) { if (!options.cbCmd) {

View File

@ -1,5 +1,3 @@
import { QQLevel, Sex } from './user'
export enum GroupListUpdateType { export enum GroupListUpdateType {
REFRESHALL, REFRESHALL,
GETALL, GETALL,
@ -35,36 +33,54 @@ export interface Group {
memberUin: string memberUin: string
memberUid: string memberUid: string
} }
members: GroupMember[] // 原始数据是没有这个的,为了方便自己加了这个字段
createTime: string createTime: string
} }
export enum GroupMemberRole { export enum GroupMemberRole {
normal = 2, Normal = 2,
admin = 3, Admin = 3,
owner = 4, Owner = 4,
} }
export interface GroupMember { export interface GroupMember {
memberSpecialTitle?: string uid: string
avatarPath: string
cardName: string
cardType: number
isDelete: boolean
nick: string
qid: string qid: string
uin: string
nick: string
remark: string remark: string
role: GroupMemberRole // 群主:4, 管理员:3群员:2 cardType: number
shutUpTime: number // 禁言时间,单位是什么暂时不清楚 cardName: string
uid: string // 加密的字符串 role: GroupMemberRole
uin: string // QQ号 avatarPath: string
shutUpTime: number
isDelete: boolean
isSpecialConcerned: boolean
isSpecialShield: boolean
isRobot: boolean isRobot: boolean
sex?: Sex groupHonor: Uint8Array
qqLevel?: QQLevel memberRealLevel: number
isChangeRole: boolean memberLevel: number
globalGroupLevel: number
globalGroupPoint: number
memberTitleId: number
memberSpecialTitle: string
specialTitleExpireTime: string
userShowFlag: number
userShowFlagNew: number
richFlag: number
mssVipType: number
bigClubLevel: number
bigClubFlag: number
autoRemark: string
creditLevel: number
joinTime: number joinTime: number
lastSpeakTime: number lastSpeakTime: number
memberLevel: number memberFlag: number
memberFlagExt: number
memberMobileFlag: number
memberFlagExt2: number
isSpecialShielded: boolean
cardNameId: number
} }
export interface PublishGroupBulletinReq { export interface PublishGroupBulletinReq {

View File

@ -67,6 +67,7 @@ export interface User {
recommendImgFlag?: number recommendImgFlag?: number
disableEmojiShortCuts?: number disableEmojiShortCuts?: number
pendantId?: string pendantId?: string
age?: number
} }
export interface SelfInfo extends User { export interface SelfInfo extends User {

View File

@ -26,7 +26,7 @@ export class GetStrangerInfo extends BaseAction<Payload, OB11User> {
...extendData, ...extendData,
user_id: parseInt(extendData.info.uin) || 0, user_id: parseInt(extendData.info.uin) || 0,
nickname: extendData.info.nick, nickname: extendData.info.nick,
sex: OB11UserSex.unknown, sex: OB11UserSex.Unknown,
age: (extendData.info.birthday_year == 0) ? 0 : new Date().getFullYear() - extendData.info.birthday_year, age: (extendData.info.birthday_year == 0) ? 0 : new Date().getFullYear() - extendData.info.birthday_year,
qid: extendData.info.qid, qid: extendData.info.qid,
level: extendData.info.qqLevel && calcQQLevel(extendData.info.qqLevel) || 0, level: extendData.info.qqLevel && calcQQLevel(extendData.info.qqLevel) || 0,
@ -46,7 +46,7 @@ export class GetStrangerInfo extends BaseAction<Payload, OB11User> {
...extendData, ...extendData,
user_id: parseInt(extendData.detail.uin) || 0, user_id: parseInt(extendData.detail.uin) || 0,
nickname: extendData.detail.simpleInfo.coreInfo.nick, nickname: extendData.detail.simpleInfo.coreInfo.nick,
sex: OB11UserSex.unknown, sex: OB11UserSex.Unknown,
age: 0, age: 0,
level: extendData.detail.commonExt.qqLevel && calcQQLevel(extendData.detail.commonExt.qqLevel) || 0, level: extendData.detail.commonExt.qqLevel && calcQQLevel(extendData.detail.commonExt.qqLevel) || 0,
login_days: 0, login_days: 0,

View File

@ -2,7 +2,7 @@ import { BaseAction, Schema } from '../BaseAction'
import { OB11GroupMember } from '../../types' import { OB11GroupMember } from '../../types'
import { OB11Entities } from '../../entities' import { OB11Entities } from '../../entities'
import { ActionName } from '../types' import { ActionName } from '../types'
import { isNullable } from 'cosmokit' import { calcQQLevel } from '@/common/utils/misc'
interface Payload { interface Payload {
group_id: number | string group_id: number | string
@ -22,14 +22,14 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
if (!uid) throw new Error('无法获取用户信息') if (!uid) throw new Error('无法获取用户信息')
const member = await this.ctx.ntGroupApi.getGroupMember(groupCode, uid) const member = await this.ctx.ntGroupApi.getGroupMember(groupCode, uid)
if (member) { if (member) {
if (isNullable(member.sex)) {
const info = await this.ctx.ntUserApi.getUserDetailInfo(member.uid)
Object.assign(member, info)
}
const ret = OB11Entities.groupMember(groupCode, member) const ret = OB11Entities.groupMember(groupCode, member)
const date = Math.round(Date.now() / 1000) const date = Math.round(Date.now() / 1000)
ret.last_sent_time ??= date ret.last_sent_time ??= date
ret.join_time ??= date ret.join_time ??= date
const info = await this.ctx.ntUserApi.getUserDetailInfo(member.uid)
ret.sex = OB11Entities.sex(info.sex!)
ret.qq_level = (info.qqLevel && calcQQLevel(info.qqLevel)) || 0
ret.age = info.age ?? 0
return ret return ret
} }
throw new Error(`群成员${payload.user_id}不存在`) throw new Error(`群成员${payload.user_id}不存在`)

View File

@ -25,7 +25,7 @@ export default class SetGroupAdmin extends BaseAction<Payload, null> {
await this.ctx.ntGroupApi.setMemberRole( await this.ctx.ntGroupApi.setMemberRole(
groupCode, groupCode,
uid, uid,
payload.enable ? GroupMemberRole.admin : GroupMemberRole.normal payload.enable ? GroupMemberRole.Admin : GroupMemberRole.Normal
) )
return null return null
} }

View File

@ -647,21 +647,21 @@ export namespace OB11Entities {
return raw.map(friendV2) return raw.map(friendV2)
} }
export function groupMemberRole(role: number): OB11GroupMemberRole | undefined { export function groupMemberRole(role: number): OB11GroupMemberRole {
return { return {
4: OB11GroupMemberRole.owner, 4: OB11GroupMemberRole.Owner,
3: OB11GroupMemberRole.admin, 3: OB11GroupMemberRole.Admin,
2: OB11GroupMemberRole.member, 2: OB11GroupMemberRole.Member,
}[role] }[role] ?? OB11GroupMemberRole.Member
} }
export function sex(sex: Sex): OB11UserSex { export function sex(sex: Sex): OB11UserSex {
const sexMap = { const sexMap = {
[Sex.male]: OB11UserSex.male, [Sex.male]: OB11UserSex.Male,
[Sex.female]: OB11UserSex.female, [Sex.female]: OB11UserSex.Female,
[Sex.unknown]: OB11UserSex.unknown, [Sex.unknown]: OB11UserSex.Unknown,
} }
return sexMap[sex] || OB11UserSex.unknown return sexMap[sex] || OB11UserSex.Unknown
} }
export function groupMember(group_id: string, member: GroupMember): OB11GroupMember { export function groupMember(group_id: string, member: GroupMember): OB11GroupMember {
@ -670,20 +670,20 @@ export namespace OB11Entities {
user_id: parseInt(member.uin), user_id: parseInt(member.uin),
nickname: member.nick, nickname: member.nick,
card: member.cardName, card: member.cardName,
sex: sex(member.sex!), sex: OB11UserSex.Unknown,
age: 0, age: 0,
area: '', area: '',
level: String(member.memberLevel ?? 0), level: String(member.memberLevel ?? 0),
qq_level: (member.qqLevel && calcQQLevel(member.qqLevel)) || 0, qq_level: 0,
join_time: member.joinTime, join_time: member.joinTime,
last_sent_time: member.lastSpeakTime, last_sent_time: member.lastSpeakTime,
title_expire_time: 0, title_expire_time: +member.specialTitleExpireTime,
unfriendly: false, unfriendly: false,
card_changeable: true, card_changeable: true,
is_robot: member.isRobot, is_robot: member.isRobot,
shut_up_timestamp: member.shutUpTime, shut_up_timestamp: member.shutUpTime,
role: groupMemberRole(member.role), role: groupMemberRole(member.role),
title: member.memberSpecialTitle || '', title: member.memberSpecialTitle,
} }
} }

View File

@ -57,7 +57,7 @@ export async function createSendElements(
.RemainAtAllCountForUin .RemainAtAllCountForUin
ctx.logger.info(`${groupCode}剩余at全体次数`, remainAtAllCount) ctx.logger.info(`${groupCode}剩余at全体次数`, remainAtAllCount)
const self = await ctx.ntGroupApi.getGroupMember(groupCode, selfInfo.uid) const self = await ctx.ntGroupApi.getGroupMember(groupCode, selfInfo.uid)
isAdmin = self?.role === GroupMemberRole.admin || self?.role === GroupMemberRole.owner isAdmin = self?.role === GroupMemberRole.Admin || self?.role === GroupMemberRole.Owner
} catch (e) { } catch (e) {
} }
} }

View File

@ -16,36 +16,36 @@ export interface OB11User {
} }
export enum OB11UserSex { export enum OB11UserSex {
male = 'male', Male = 'male',
female = 'female', Female = 'female',
unknown = 'unknown', Unknown = 'unknown',
} }
export enum OB11GroupMemberRole { export enum OB11GroupMemberRole {
owner = 'owner', Owner = 'owner',
admin = 'admin', Admin = 'admin',
member = 'member', Member = 'member',
} }
export interface OB11GroupMember { export interface OB11GroupMember {
group_id: number group_id: number
user_id: number user_id: number
nickname: string nickname: string
card?: string card: string
sex?: OB11UserSex sex: OB11UserSex
age?: number age: number
join_time?: number join_time: number
last_sent_time?: number last_sent_time: number
level?: string level: string
qq_level?: number qq_level?: number
role?: OB11GroupMemberRole role: OB11GroupMemberRole
title?: string title: string
area?: string area: string
unfriendly?: boolean unfriendly: boolean
title_expire_time?: number title_expire_time: number
card_changeable?: boolean card_changeable: boolean
// 以下为gocq字段 // 以下为gocq字段
shut_up_timestamp?: number shut_up_timestamp: number
// 以下为扩展字段 // 以下为扩展字段
is_robot?: boolean is_robot?: boolean
qage?: number qage?: number

View File

@ -65,7 +65,7 @@ export class SatoriServer {
this.wsServer.on('connection', (socket, req) => { this.wsServer.on('connection', (socket, req) => {
const url = req.url?.split('?').shift() const url = req.url?.split('?').shift()
if (!['/v1/events', '/v1/events/'].includes(url!)) { if (!['/v1/events', '/v1/events/'].includes(url!)) {
return socket.close() return socket.close(1008, 'invalid address')
} }
socket.addEventListener('message', async (event) => { socket.addEventListener('message', async (event) => {