mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
refactor: ntqqapi types
This commit is contained in:
parent
d8e31985af
commit
1a6739ffab
7
src/common/utils/qqlevel.ts
Normal file
7
src/common/utils/qqlevel.ts
Normal file
@ -0,0 +1,7 @@
|
||||
// QQ等级换算
|
||||
import {QQLevel} from "../../ntqqapi/types";
|
||||
|
||||
export function calcQQLevel(level: QQLevel) {
|
||||
const {crownNum, sunNum, moonNum, starNum} = level
|
||||
return crownNum * 64 + sunNum * 16 + moonNum * 4 + starNum
|
||||
}
|
@ -131,7 +131,7 @@ function onLoad() {
|
||||
log("report message error: ", e.stack.toString());
|
||||
}
|
||||
})
|
||||
registerReceiveHook<{ msgList: Array<RawMessage> }>([ReceiveCmdS.UPDATE_MSG, ReceiveCmdS.UPDATE_ACTIVE_MSG], async (payload) => {
|
||||
registerReceiveHook<{ msgList: Array<RawMessage> }>([ReceiveCmdS.UPDATE_MSG], async (payload) => {
|
||||
for (const message of payload.msgList) {
|
||||
// log("message update", message.sendStatus, message.msgId, message.msgSeq)
|
||||
if (message.recallTime != "0") { //todo: 这个判断方法不太好,应该使用灰色消息元素来判断
|
||||
|
@ -4,6 +4,7 @@ import {log, sleep} from "../../common/utils";
|
||||
import {dbUtil} from "../../common/db";
|
||||
import {selfInfo} from "../../common/data";
|
||||
import {ReceiveCmdS, registerReceiveHook} from "../hook";
|
||||
|
||||
export let sendMessagePool: Record<string, ((sendSuccessMsg: RawMessage) => void) | null> = {}// peerUid: callbackFunnc
|
||||
|
||||
export interface Peer {
|
||||
@ -13,12 +14,33 @@ export interface Peer {
|
||||
}
|
||||
|
||||
export class NTQQMsgApi {
|
||||
static async activateChat(peer: Peer) {
|
||||
static async activateGroupChat(groupCode: string) {
|
||||
return await callNTQQApi({
|
||||
methodName: NTQQApiMethod.ADD_ACTIVE_CHAT,
|
||||
args: [{peer, cnt: 20}]
|
||||
args: [{peer:{peerUid: groupCode, chatType: ChatType.group}, cnt: 20}]
|
||||
})
|
||||
}
|
||||
static async fetchRecentContact(){
|
||||
await callNTQQApi({
|
||||
methodName: NTQQApiMethod.RECENT_CONTACT,
|
||||
args: [
|
||||
{
|
||||
fetchParam: {
|
||||
anchorPointContact: {
|
||||
contactId: '',
|
||||
sortField: '',
|
||||
pos: 0,
|
||||
},
|
||||
relativeMoveCount: 0,
|
||||
listType: 2, // 1普通消息,2群助手内的消息
|
||||
count: 200,
|
||||
fetchOld: true,
|
||||
},
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
static async recallMsg(peer: Peer, msgIds: string[]) {
|
||||
return await callNTQQApi({
|
||||
methodName: NTQQApiMethod.RECALL_MSG,
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {BrowserWindow} from 'electron';
|
||||
import {getConfigUtil, log, sleep} from "../common/utils";
|
||||
import {NTQQApiClass} from "./ntcall";
|
||||
import {sendMessagePool} from "./api/msg"
|
||||
import {Group, RawMessage, User} from "./types";
|
||||
import {NTQQMsgApi, sendMessagePool} from "./api/msg"
|
||||
import {ChatType, Group, RawMessage, User} from "./types";
|
||||
import {friends, groups, selfInfo, tempGroupCodeMap} from "../common/data";
|
||||
import {OB11GroupDecreaseEvent} from "../onebot11/event/notice/OB11GroupDecreaseEvent";
|
||||
import {v4 as uuidv4} from "uuid"
|
||||
@ -146,6 +146,8 @@ export function removeReceiveHook(id: string) {
|
||||
|
||||
async function updateGroups(_groups: Group[], needUpdate: boolean = true) {
|
||||
for (let group of _groups) {
|
||||
log("update group", group)
|
||||
NTQQMsgApi.activateGroupChat(group.groupCode).then()
|
||||
let existGroup = groups.find(g => g.groupCode == group.groupCode);
|
||||
if (existGroup) {
|
||||
Object.assign(existGroup, group);
|
||||
|
@ -15,6 +15,7 @@ export enum NTQQApiClass {
|
||||
}
|
||||
|
||||
export enum NTQQApiMethod {
|
||||
RECENT_CONTACT = "nodeIKernelRecentContactService/fetchAndSubscribeABatchOfRecentContact",
|
||||
ADD_ACTIVE_CHAT = "nodeIKernelMsgService/getAioFirstViewLatestMsgsAndAddActiveChat", // 激活群助手内的聊天窗口,这样才能收到消息
|
||||
LIKE_FRIEND = "nodeIKernelProfileLikeService/setBuddyProfileLike",
|
||||
SELF_INFO = "fetchAuthData",
|
||||
|
65
src/ntqqapi/types/cache.ts
Normal file
65
src/ntqqapi/types/cache.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import {ChatType} from "./msg";
|
||||
|
||||
export interface CacheScanResult {
|
||||
result: number,
|
||||
size: [ // 单位为字节
|
||||
string, // 系统总存储空间
|
||||
string, // 系统可用存储空间
|
||||
string, // 系统已用存储空间
|
||||
string, // QQ总大小
|
||||
string, // 「聊天与文件」大小
|
||||
string, // 未知
|
||||
string, // 「缓存数据」大小
|
||||
string, // 「其他数据」大小
|
||||
string, // 未知
|
||||
]
|
||||
}
|
||||
|
||||
export interface ChatCacheList {
|
||||
pageCount: number,
|
||||
infos: ChatCacheListItem[]
|
||||
}
|
||||
|
||||
export interface ChatCacheListItem {
|
||||
chatType: ChatType,
|
||||
basicChatCacheInfo: ChatCacheListItemBasic,
|
||||
guildChatCacheInfo: unknown[] // TODO: 没用过频道所以不知道这里边的详细内容
|
||||
}
|
||||
|
||||
export interface ChatCacheListItemBasic {
|
||||
chatSize: string,
|
||||
chatTime: string,
|
||||
uid: string,
|
||||
uin: string,
|
||||
remarkName: string,
|
||||
nickName: string,
|
||||
chatType?: ChatType,
|
||||
isChecked?: boolean
|
||||
}
|
||||
|
||||
export enum CacheFileType {
|
||||
IMAGE = 0,
|
||||
VIDEO = 1,
|
||||
AUDIO = 2,
|
||||
DOCUMENT = 3,
|
||||
OTHER = 4,
|
||||
}
|
||||
|
||||
export interface CacheFileList {
|
||||
infos: CacheFileListItem[],
|
||||
}
|
||||
|
||||
export interface CacheFileListItem {
|
||||
fileSize: string,
|
||||
fileTime: string,
|
||||
fileKey: string,
|
||||
elementId: string,
|
||||
elementIdStr: string,
|
||||
fileType: CacheFileType,
|
||||
path: string,
|
||||
fileName: string,
|
||||
senderId: string,
|
||||
previewPath: string,
|
||||
senderName: string,
|
||||
isChecked?: boolean,
|
||||
}
|
55
src/ntqqapi/types/group.ts
Normal file
55
src/ntqqapi/types/group.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import {QQLevel, Sex} from "./user";
|
||||
|
||||
export interface Group {
|
||||
groupCode: string,
|
||||
maxMember: number,
|
||||
memberCount: number,
|
||||
groupName: string,
|
||||
groupStatus: 0,
|
||||
memberRole: 2,
|
||||
isTop: boolean,
|
||||
toppedTimestamp: "0",
|
||||
privilegeFlag: number, //65760
|
||||
isConf: boolean,
|
||||
hasModifyConfGroupFace: boolean,
|
||||
hasModifyConfGroupName: boolean,
|
||||
remarkName: string,
|
||||
hasMemo: boolean,
|
||||
groupShutupExpireTime: string, //"0",
|
||||
personShutupExpireTime: string, //"0",
|
||||
discussToGroupUin: string, //"0",
|
||||
discussToGroupMaxMsgSeq: number,
|
||||
discussToGroupTime: number,
|
||||
groupFlagExt: number, //1073938496,
|
||||
authGroupType: number, //0,
|
||||
groupCreditLevel: number, //0,
|
||||
groupFlagExt3: number, //0,
|
||||
groupOwnerId: {
|
||||
"memberUin": string, //"0",
|
||||
"memberUid": string, //"u_fbf8N7aeuZEnUiJAbQ9R8Q"
|
||||
},
|
||||
members: GroupMember[] // 原始数据是没有这个的,为了方便自己加了这个字段
|
||||
}
|
||||
|
||||
export enum GroupMemberRole {
|
||||
normal = 2,
|
||||
admin = 3,
|
||||
owner = 4
|
||||
}
|
||||
|
||||
export interface GroupMember {
|
||||
avatarPath: string;
|
||||
cardName: string;
|
||||
cardType: number;
|
||||
isDelete: boolean;
|
||||
nick: string;
|
||||
qid: string;
|
||||
remark: string;
|
||||
role: GroupMemberRole; // 群主:4, 管理员:3,群员:2
|
||||
shutUpTime: number; // 禁言时间,单位是什么暂时不清楚
|
||||
uid: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
isRobot: boolean;
|
||||
sex?: Sex
|
||||
qqLevel?: QQLevel
|
||||
}
|
7
src/ntqqapi/types/index.ts
Normal file
7
src/ntqqapi/types/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
export * from './user';
|
||||
export * from './group';
|
||||
export * from './msg';
|
||||
export * from './notify';
|
||||
export * from './cache';
|
||||
|
@ -1,70 +1,4 @@
|
||||
export interface User {
|
||||
uid: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
nick: string;
|
||||
avatarUrl?: string;
|
||||
longNick?: string; // 签名
|
||||
remark?: string
|
||||
}
|
||||
|
||||
export interface SelfInfo extends User {
|
||||
online?: boolean;
|
||||
}
|
||||
|
||||
export interface Friend extends User {
|
||||
}
|
||||
|
||||
export interface Group {
|
||||
groupCode: string,
|
||||
maxMember: number,
|
||||
memberCount: number,
|
||||
groupName: string,
|
||||
groupStatus: 0,
|
||||
memberRole: 2,
|
||||
isTop: boolean,
|
||||
toppedTimestamp: "0",
|
||||
privilegeFlag: number, //65760
|
||||
isConf: boolean,
|
||||
hasModifyConfGroupFace: boolean,
|
||||
hasModifyConfGroupName: boolean,
|
||||
remarkName: string,
|
||||
hasMemo: boolean,
|
||||
groupShutupExpireTime: string, //"0",
|
||||
personShutupExpireTime: string, //"0",
|
||||
discussToGroupUin: string, //"0",
|
||||
discussToGroupMaxMsgSeq: number,
|
||||
discussToGroupTime: number,
|
||||
groupFlagExt: number, //1073938496,
|
||||
authGroupType: number, //0,
|
||||
groupCreditLevel: number, //0,
|
||||
groupFlagExt3: number, //0,
|
||||
groupOwnerId: {
|
||||
"memberUin": string, //"0",
|
||||
"memberUid": string, //"u_fbf8N7aeuZEnUiJAbQ9R8Q"
|
||||
},
|
||||
members: GroupMember[] // 原始数据是没有这个的,为了方便自己加了这个字段
|
||||
}
|
||||
|
||||
export enum GroupMemberRole {
|
||||
normal = 2,
|
||||
admin = 3,
|
||||
owner = 4
|
||||
}
|
||||
|
||||
export interface GroupMember {
|
||||
avatarPath: string;
|
||||
cardName: string;
|
||||
cardType: number;
|
||||
isDelete: boolean;
|
||||
nick: string;
|
||||
qid: string;
|
||||
remark: string;
|
||||
role: GroupMemberRole; // 群主:4, 管理员:3,群员:2
|
||||
shutUpTime: number; // 禁言时间,单位是什么暂时不清楚
|
||||
uid: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
isRobot: boolean;
|
||||
}
|
||||
import {GroupMemberRole} from "./group";
|
||||
|
||||
export enum ElementType {
|
||||
TEXT = 1,
|
||||
@ -383,132 +317,4 @@ export interface RawMessage {
|
||||
videoElement: VideoElement;
|
||||
fileElement: FileElement;
|
||||
}[];
|
||||
}
|
||||
|
||||
export enum GroupNotifyTypes {
|
||||
INVITE_ME = 1,
|
||||
INVITED_JOIN = 4, // 有人接受了邀请入群
|
||||
JOIN_REQUEST = 7,
|
||||
ADMIN_SET = 8,
|
||||
ADMIN_UNSET = 12,
|
||||
MEMBER_EXIT = 11, // 主动退出?
|
||||
|
||||
}
|
||||
|
||||
export interface GroupNotifies {
|
||||
doubt: boolean,
|
||||
nextStartSeq: string,
|
||||
notifies: GroupNotify[],
|
||||
}
|
||||
|
||||
export enum GroupNotifyStatus {
|
||||
IGNORE = 0,
|
||||
WAIT_HANDLE = 1,
|
||||
APPROVE = 2,
|
||||
REJECT = 3
|
||||
}
|
||||
|
||||
export interface GroupNotify {
|
||||
time: number; // 自己添加的字段,时间戳,毫秒, 用于判断收到短时间内收到重复的notify
|
||||
seq: string, // 唯一标识符,转成数字再除以1000应该就是时间戳?
|
||||
type: GroupNotifyTypes,
|
||||
status: GroupNotifyStatus, // 0是已忽略?,1是未处理,2是已同意
|
||||
group: { groupCode: string, groupName: string },
|
||||
user1: { uid: string, nickName: string }, // 被设置管理员的人
|
||||
user2: { uid: string, nickName: string }, // 操作者
|
||||
actionUser: { uid: string, nickName: string }, //未知
|
||||
actionTime: string,
|
||||
invitationExt: {
|
||||
srcType: number, // 0?未知
|
||||
groupCode: string, waitStatus: number
|
||||
},
|
||||
postscript: string, // 加群用户填写的验证信息
|
||||
repeatSeqs: [],
|
||||
warningTips: string
|
||||
}
|
||||
|
||||
export enum GroupRequestOperateTypes {
|
||||
approve = 1,
|
||||
reject = 2
|
||||
}
|
||||
|
||||
export interface FriendRequest {
|
||||
friendUid: string,
|
||||
reqTime: string, // 时间戳,秒
|
||||
extWords: string, // 申请人填写的验证消息
|
||||
isUnread: boolean,
|
||||
friendNick: string,
|
||||
sourceId: number,
|
||||
groupCode: string
|
||||
}
|
||||
|
||||
export interface FriendRequestNotify {
|
||||
data: {
|
||||
unreadNums: number,
|
||||
buddyReqs: FriendRequest[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface CacheScanResult {
|
||||
result: number,
|
||||
size: [ // 单位为字节
|
||||
string, // 系统总存储空间
|
||||
string, // 系统可用存储空间
|
||||
string, // 系统已用存储空间
|
||||
string, // QQ总大小
|
||||
string, // 「聊天与文件」大小
|
||||
string, // 未知
|
||||
string, // 「缓存数据」大小
|
||||
string, // 「其他数据」大小
|
||||
string, // 未知
|
||||
]
|
||||
}
|
||||
|
||||
export interface ChatCacheList {
|
||||
pageCount: number,
|
||||
infos: ChatCacheListItem[]
|
||||
}
|
||||
|
||||
export interface ChatCacheListItem {
|
||||
chatType: ChatType,
|
||||
basicChatCacheInfo: ChatCacheListItemBasic,
|
||||
guildChatCacheInfo: unknown[] // TODO: 没用过频道所以不知道这里边的详细内容
|
||||
}
|
||||
|
||||
export interface ChatCacheListItemBasic {
|
||||
chatSize: string,
|
||||
chatTime: string,
|
||||
uid: string,
|
||||
uin: string,
|
||||
remarkName: string,
|
||||
nickName: string,
|
||||
chatType?: ChatType,
|
||||
isChecked?: boolean
|
||||
}
|
||||
|
||||
export enum CacheFileType {
|
||||
IMAGE = 0,
|
||||
VIDEO = 1,
|
||||
AUDIO = 2,
|
||||
DOCUMENT = 3,
|
||||
OTHER = 4,
|
||||
}
|
||||
|
||||
export interface CacheFileList {
|
||||
infos: CacheFileListItem[],
|
||||
}
|
||||
|
||||
export interface CacheFileListItem {
|
||||
fileSize: string,
|
||||
fileTime: string,
|
||||
fileKey: string,
|
||||
elementId: string,
|
||||
elementIdStr: string,
|
||||
fileType: CacheFileType,
|
||||
path: string,
|
||||
fileName: string,
|
||||
senderId: string,
|
||||
previewPath: string,
|
||||
senderName: string,
|
||||
isChecked?: boolean,
|
||||
}
|
||||
}
|
64
src/ntqqapi/types/notify.ts
Normal file
64
src/ntqqapi/types/notify.ts
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
export enum GroupNotifyTypes {
|
||||
INVITE_ME = 1,
|
||||
INVITED_JOIN = 4, // 有人接受了邀请入群
|
||||
JOIN_REQUEST = 7,
|
||||
ADMIN_SET = 8,
|
||||
ADMIN_UNSET = 12,
|
||||
MEMBER_EXIT = 11, // 主动退出?
|
||||
|
||||
}
|
||||
|
||||
export interface GroupNotifies {
|
||||
doubt: boolean,
|
||||
nextStartSeq: string,
|
||||
notifies: GroupNotify[],
|
||||
}
|
||||
|
||||
export enum GroupNotifyStatus {
|
||||
IGNORE = 0,
|
||||
WAIT_HANDLE = 1,
|
||||
APPROVE = 2,
|
||||
REJECT = 3
|
||||
}
|
||||
|
||||
export interface GroupNotify {
|
||||
time: number; // 自己添加的字段,时间戳,毫秒, 用于判断收到短时间内收到重复的notify
|
||||
seq: string, // 唯一标识符,转成数字再除以1000应该就是时间戳?
|
||||
type: GroupNotifyTypes,
|
||||
status: GroupNotifyStatus, // 0是已忽略?,1是未处理,2是已同意
|
||||
group: { groupCode: string, groupName: string },
|
||||
user1: { uid: string, nickName: string }, // 被设置管理员的人
|
||||
user2: { uid: string, nickName: string }, // 操作者
|
||||
actionUser: { uid: string, nickName: string }, //未知
|
||||
actionTime: string,
|
||||
invitationExt: {
|
||||
srcType: number, // 0?未知
|
||||
groupCode: string, waitStatus: number
|
||||
},
|
||||
postscript: string, // 加群用户填写的验证信息
|
||||
repeatSeqs: [],
|
||||
warningTips: string
|
||||
}
|
||||
|
||||
export enum GroupRequestOperateTypes {
|
||||
approve = 1,
|
||||
reject = 2
|
||||
}
|
||||
|
||||
export interface FriendRequest {
|
||||
friendUid: string,
|
||||
reqTime: string, // 时间戳,秒
|
||||
extWords: string, // 申请人填写的验证消息
|
||||
isUnread: boolean,
|
||||
friendNick: string,
|
||||
sourceId: number,
|
||||
groupCode: string
|
||||
}
|
||||
|
||||
export interface FriendRequestNotify {
|
||||
data: {
|
||||
unreadNums: number,
|
||||
buddyReqs: FriendRequest[]
|
||||
}
|
||||
}
|
28
src/ntqqapi/types/user.ts
Normal file
28
src/ntqqapi/types/user.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export enum Sex {
|
||||
male = 0,
|
||||
female = 2,
|
||||
unknown = 255,
|
||||
}
|
||||
|
||||
export interface QQLevel {
|
||||
"crownNum": number,
|
||||
"sunNum": number,
|
||||
"moonNum": number,
|
||||
"starNum": number
|
||||
}
|
||||
export interface User {
|
||||
uid: string; // 加密的字符串
|
||||
uin: string; // QQ号
|
||||
nick: string;
|
||||
avatarUrl?: string;
|
||||
longNick?: string; // 签名
|
||||
remark?: string;
|
||||
sex?: Sex;
|
||||
"qqLevel"?: QQLevel
|
||||
}
|
||||
|
||||
export interface SelfInfo extends User {
|
||||
online?: boolean;
|
||||
}
|
||||
|
||||
export interface Friend extends User {}
|
@ -3,6 +3,8 @@ import {getGroupMember} from "../../common/data";
|
||||
import {OB11Constructor} from "../constructor";
|
||||
import BaseAction from "./BaseAction";
|
||||
import {ActionName} from "./types";
|
||||
import {NTQQUserApi} from "../../ntqqapi/api/user";
|
||||
import {isNull, log} from "../../common/utils";
|
||||
|
||||
|
||||
export interface PayloadType {
|
||||
@ -16,6 +18,10 @@ class GetGroupMemberInfo extends BaseAction<PayloadType, OB11GroupMember> {
|
||||
protected async _handle(payload: PayloadType) {
|
||||
const member = await getGroupMember(payload.group_id.toString(), payload.user_id.toString())
|
||||
if (member) {
|
||||
if (isNull(member.sex)){
|
||||
let info = (await NTQQUserApi.getUserDetailInfo(member.uid))
|
||||
Object.assign(member, info);
|
||||
}
|
||||
return OB11Constructor.groupMember(payload.group_id.toString(), member)
|
||||
} else {
|
||||
throw (`群成员${payload.user_id}不存在`)
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
GroupMember,
|
||||
IMAGE_HTTP_HOST,
|
||||
RawMessage,
|
||||
SelfInfo,
|
||||
SelfInfo, Sex,
|
||||
TipGroupElementType,
|
||||
User
|
||||
} from '../ntqqapi/types';
|
||||
@ -31,6 +31,7 @@ import {OB11GroupUploadNoticeEvent} from "./event/notice/OB11GroupUploadNoticeEv
|
||||
import {OB11GroupNoticeEvent} from "./event/notice/OB11GroupNoticeEvent";
|
||||
import {NTQQUserApi} from "../ntqqapi/api/user";
|
||||
import {NTQQFileApi} from "../ntqqapi/api/file";
|
||||
import {calcQQLevel} from "../common/utils/qqlevel";
|
||||
|
||||
|
||||
export class OB11Constructor {
|
||||
@ -225,6 +226,7 @@ export class OB11Constructor {
|
||||
if (msg.chatType !== ChatType.group) {
|
||||
return;
|
||||
}
|
||||
// log("group msg", msg);
|
||||
for (let element of msg.elements) {
|
||||
const grayTipElement = element.grayTipElement
|
||||
const groupElement = grayTipElement?.groupElement
|
||||
@ -325,16 +327,24 @@ export class OB11Constructor {
|
||||
}[role]
|
||||
}
|
||||
|
||||
static sex(sex: Sex): OB11UserSex{
|
||||
const sexMap = {
|
||||
[Sex.male]: OB11UserSex.male,
|
||||
[Sex.female]: OB11UserSex.female,
|
||||
[Sex.unknown]: OB11UserSex.unknown
|
||||
}
|
||||
return sexMap[sex] || OB11UserSex.unknown
|
||||
}
|
||||
static groupMember(group_id: string, member: GroupMember): OB11GroupMember {
|
||||
return {
|
||||
group_id: parseInt(group_id),
|
||||
user_id: parseInt(member.uin),
|
||||
nickname: member.nick,
|
||||
card: member.cardName,
|
||||
sex: OB11UserSex.unknown,
|
||||
sex: OB11Constructor.sex(member.sex),
|
||||
age: 0,
|
||||
area: "",
|
||||
level: 0,
|
||||
level: member.qqLevel && calcQQLevel(member.qqLevel) || 0,
|
||||
join_time: 0, // 暂时没法获取
|
||||
last_sent_time: 0, // 暂时没法获取
|
||||
title_expire_time: 0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user