mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
fix: send empty forward msg
fix: ignore post history msg before login fix: quit group not sync to groups of data feat: support post url params feat: support port http heart
This commit is contained in:
parent
f8890b309b
commit
c2b3316603
@ -39,6 +39,7 @@ export class ConfigUtil {
|
|||||||
enableWs: true,
|
enableWs: true,
|
||||||
enableWsReverse: false,
|
enableWsReverse: false,
|
||||||
messagePostFormat: "array",
|
messagePostFormat: "array",
|
||||||
|
enableHttpHeart: false
|
||||||
}
|
}
|
||||||
let defaultConfig: Config = {
|
let defaultConfig: Config = {
|
||||||
ob11: ob11Default,
|
ob11: ob11Default,
|
||||||
|
@ -58,6 +58,15 @@ export async function getGroup(qq: string): Promise<Group | undefined> {
|
|||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deleteGroup(groupCode: string) {
|
||||||
|
const groupIndex = groups.findIndex(group => group.groupCode === groupCode.toString())
|
||||||
|
// log(groups, groupCode, groupIndex);
|
||||||
|
if (groupIndex !== -1) {
|
||||||
|
log("删除群", groupCode);
|
||||||
|
groups.splice(groupIndex, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number) {
|
export async function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number) {
|
||||||
groupQQ = groupQQ.toString()
|
groupQQ = groupQQ.toString()
|
||||||
memberUinOrUid = memberUinOrUid.toString()
|
memberUinOrUid = memberUinOrUid.toString()
|
||||||
|
@ -95,6 +95,9 @@ export abstract class HttpServerBase {
|
|||||||
if (method == "get") {
|
if (method == "get") {
|
||||||
payload = req.query
|
payload = req.query
|
||||||
}
|
}
|
||||||
|
else if (req.query){
|
||||||
|
payload = {...req.query, ...req.body}
|
||||||
|
}
|
||||||
log("收到http请求", url, payload);
|
log("收到http请求", url, payload);
|
||||||
try {
|
try {
|
||||||
res.send(await handler(res, payload))
|
res.send(await handler(res, payload))
|
||||||
|
@ -9,6 +9,7 @@ export interface OB11Config {
|
|||||||
enableWs?: boolean
|
enableWs?: boolean
|
||||||
enableWsReverse?: boolean
|
enableWsReverse?: boolean
|
||||||
messagePostFormat?: 'array' | 'string'
|
messagePostFormat?: 'array' | 'string'
|
||||||
|
enableHttpHeart?: boolean
|
||||||
}
|
}
|
||||||
export interface CheckVersion {
|
export interface CheckVersion {
|
||||||
result: boolean,
|
result: boolean,
|
||||||
|
@ -34,7 +34,7 @@ import {
|
|||||||
GroupNotifyTypes,
|
GroupNotifyTypes,
|
||||||
RawMessage
|
RawMessage
|
||||||
} from "../ntqqapi/types";
|
} from "../ntqqapi/types";
|
||||||
import {ob11HTTPServer} from "../onebot11/server/http";
|
import {httpHeart, ob11HTTPServer} from "../onebot11/server/http";
|
||||||
import {OB11FriendRecallNoticeEvent} from "../onebot11/event/notice/OB11FriendRecallNoticeEvent";
|
import {OB11FriendRecallNoticeEvent} from "../onebot11/event/notice/OB11FriendRecallNoticeEvent";
|
||||||
import {OB11GroupRecallNoticeEvent} from "../onebot11/event/notice/OB11GroupRecallNoticeEvent";
|
import {OB11GroupRecallNoticeEvent} from "../onebot11/event/notice/OB11GroupRecallNoticeEvent";
|
||||||
import {postOB11Event} from "../onebot11/server/postOB11Event";
|
import {postOB11Event} from "../onebot11/server/postOB11Event";
|
||||||
@ -148,7 +148,10 @@ function onLoad() {
|
|||||||
async function postReceiveMsg(msgList: RawMessage[]) {
|
async function postReceiveMsg(msgList: RawMessage[]) {
|
||||||
const {debug, reportSelfMessage} = getConfigUtil().getConfig();
|
const {debug, reportSelfMessage} = getConfigUtil().getConfig();
|
||||||
for (let message of msgList) {
|
for (let message of msgList) {
|
||||||
|
// 过滤启动之前的消息
|
||||||
|
if (parseInt(message.msgTime) < startTime / 1000) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// log("收到新消息", message.msgId, message.msgSeq)
|
// log("收到新消息", message.msgId, message.msgSeq)
|
||||||
// if (message.senderUin !== selfInfo.uin){
|
// if (message.senderUin !== selfInfo.uin){
|
||||||
message.msgShortId = await dbUtil.addMsg(message);
|
message.msgShortId = await dbUtil.addMsg(message);
|
||||||
@ -379,7 +382,7 @@ function onLoad() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let startTime = 0;
|
let startTime = 0; // 毫秒
|
||||||
|
|
||||||
async function start() {
|
async function start() {
|
||||||
log("llonebot pid", process.pid)
|
log("llonebot pid", process.pid)
|
||||||
@ -402,6 +405,9 @@ function onLoad() {
|
|||||||
if (config.ob11.enableWsReverse) {
|
if (config.ob11.enableWsReverse) {
|
||||||
ob11ReverseWebsockets.start();
|
ob11ReverseWebsockets.start();
|
||||||
}
|
}
|
||||||
|
if (config.ob11.enableHttpHeart){
|
||||||
|
httpHeart.start();
|
||||||
|
}
|
||||||
|
|
||||||
log("LLOneBot start")
|
log("LLOneBot start")
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {Config} from "../common/types";
|
import {Config} from "../common/types";
|
||||||
import {ob11HTTPServer} from "../onebot11/server/http";
|
import {httpHeart, ob11HTTPServer} from "../onebot11/server/http";
|
||||||
import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer";
|
import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer";
|
||||||
import {ob11ReverseWebsockets} from "../onebot11/server/ws/ReverseWebsocket";
|
import {ob11ReverseWebsockets} from "../onebot11/server/ws/ReverseWebsocket";
|
||||||
import {llonebotError} from "../common/data";
|
import {llonebotError} from "../common/data";
|
||||||
@ -54,6 +54,14 @@ export async function setConfig(config: Config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (config.ob11.enableHttpHeart){
|
||||||
|
// 启动http心跳
|
||||||
|
httpHeart.start();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// 关闭http心跳
|
||||||
|
httpHeart.stop();
|
||||||
|
}
|
||||||
log("old config", oldConfig)
|
log("old config", oldConfig)
|
||||||
log("配置已更新", config)
|
log("配置已更新", config)
|
||||||
checkFfmpeg(config.ffmpeg).then()
|
checkFfmpeg(config.ffmpeg).then()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {ReceiveCmdS} from "../hook";
|
import {ReceiveCmdS} from "../hook";
|
||||||
import {Group, GroupMember, GroupMemberRole, GroupNotifies, GroupNotify, GroupRequestOperateTypes} from "../types";
|
import {Group, GroupMember, GroupMemberRole, GroupNotifies, GroupNotify, GroupRequestOperateTypes} from "../types";
|
||||||
import {callNTQQApi, GeneralCallResult, NTQQApiClass, NTQQApiMethod} from "../ntcall";
|
import {callNTQQApi, GeneralCallResult, NTQQApiClass, NTQQApiMethod} from "../ntcall";
|
||||||
import {uidMaps} from "../../common/data";
|
import {deleteGroup, uidMaps} from "../../common/data";
|
||||||
import {dbUtil} from "../../common/db";
|
import {dbUtil} from "../../common/db";
|
||||||
import {log} from "../../common/utils/log";
|
import {log} from "../../common/utils/log";
|
||||||
import {NTQQWindowApi, NTQQWindows} from "./window";
|
import {NTQQWindowApi, NTQQWindows} from "./window";
|
||||||
@ -102,13 +102,17 @@ export class NTQQGroupApi{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
static async quitGroup(groupQQ: string) {
|
static async quitGroup(groupQQ: string) {
|
||||||
await callNTQQApi<GeneralCallResult>({
|
const result = await callNTQQApi<GeneralCallResult>({
|
||||||
methodName: NTQQApiMethod.QUIT_GROUP,
|
methodName: NTQQApiMethod.QUIT_GROUP,
|
||||||
args: [
|
args: [
|
||||||
{"groupCode": groupQQ},
|
{"groupCode": groupQQ},
|
||||||
null
|
null
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
if (result.result === 0){
|
||||||
|
deleteGroup(groupQQ);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
static async kickMember(groupQQ: string, kickUids: string[], refuseForever: boolean = false, kickReason: string = '') {
|
static async kickMember(groupQQ: string, kickUids: string[], refuseForever: boolean = false, kickReason: string = '') {
|
||||||
return await callNTQQApi<GeneralCallResult>(
|
return await callNTQQApi<GeneralCallResult>(
|
||||||
|
@ -2,7 +2,16 @@ import {BrowserWindow} from 'electron';
|
|||||||
import {NTQQApiClass, NTQQApiMethod} from "./ntcall";
|
import {NTQQApiClass, NTQQApiMethod} from "./ntcall";
|
||||||
import {NTQQMsgApi, sendMessagePool} from "./api/msg"
|
import {NTQQMsgApi, sendMessagePool} from "./api/msg"
|
||||||
import {ChatType, Group, GroupMember, GroupMemberRole, RawMessage, User} from "./types";
|
import {ChatType, Group, GroupMember, GroupMemberRole, RawMessage, User} from "./types";
|
||||||
import {friends, getFriend, getGroupMember, groups, selfInfo, tempGroupCodeMap, uidMaps} from "../common/data";
|
import {
|
||||||
|
deleteGroup,
|
||||||
|
friends,
|
||||||
|
getFriend,
|
||||||
|
getGroupMember,
|
||||||
|
groups,
|
||||||
|
selfInfo,
|
||||||
|
tempGroupCodeMap,
|
||||||
|
uidMaps
|
||||||
|
} from "../common/data";
|
||||||
import {OB11GroupDecreaseEvent} from "../onebot11/event/notice/OB11GroupDecreaseEvent";
|
import {OB11GroupDecreaseEvent} from "../onebot11/event/notice/OB11GroupDecreaseEvent";
|
||||||
import {v4 as uuidv4} from "uuid"
|
import {v4 as uuidv4} from "uuid"
|
||||||
import {postOB11Event} from "../onebot11/server/postOB11Event";
|
import {postOB11Event} from "../onebot11/server/postOB11Event";
|
||||||
@ -233,6 +242,11 @@ let activatedGroups: string[] = [];
|
|||||||
|
|
||||||
async function updateGroups(_groups: Group[], needUpdate: boolean = true) {
|
async function updateGroups(_groups: Group[], needUpdate: boolean = true) {
|
||||||
for (let group of _groups) {
|
for (let group of _groups) {
|
||||||
|
log("update group", group);
|
||||||
|
if (group.privilegeFlag === 0){
|
||||||
|
deleteGroup(group.groupCode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
log("update group", group)
|
log("update group", group)
|
||||||
// if (!activatedGroups.includes(group.groupCode)) {
|
// if (!activatedGroups.includes(group.groupCode)) {
|
||||||
NTQQMsgApi.activateChat({peerUid: group.groupCode, chatType: ChatType.group}).then((r) => {
|
NTQQMsgApi.activateChat({peerUid: group.groupCode, chatType: ChatType.group}).then((r) => {
|
||||||
@ -294,7 +308,9 @@ async function processGroupEvent(payload: { groupList: Group[] }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (group.privilegeFlag === 0){
|
||||||
|
deleteGroup(group.groupCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,17 +6,27 @@ import {ActionName} from "../types";
|
|||||||
import {NTQQGroupApi} from "../../../ntqqapi/api";
|
import {NTQQGroupApi} from "../../../ntqqapi/api";
|
||||||
import {log} from "../../../common/utils";
|
import {log} from "../../../common/utils";
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
no_cache: boolean
|
||||||
|
}
|
||||||
|
|
||||||
class GetGroupList extends BaseAction<null, OB11Group[]> {
|
class GetGroupList extends BaseAction<Payload, OB11Group[]> {
|
||||||
actionName = ActionName.GetGroupList
|
actionName = ActionName.GetGroupList
|
||||||
|
|
||||||
protected async _handle(payload: null) {
|
protected async _handle(payload: Payload) {
|
||||||
// if (groups.length === 0) {
|
if (groups.length === 0
|
||||||
// const groups = await NTQQGroupApi.getGroups(true)
|
// || payload.no_cache === true
|
||||||
// log("get groups", groups)
|
) {
|
||||||
// }
|
try {
|
||||||
|
const groups = await NTQQGroupApi.getGroups(true)
|
||||||
|
// log("get groups", groups)
|
||||||
return OB11Constructor.groups(groups);
|
return OB11Constructor.groups(groups);
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return OB11Constructor.groups(groups);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GetGroupList
|
export default GetGroupList
|
@ -91,6 +91,8 @@ function initActionMap() {
|
|||||||
const actionMap = new Map<string, BaseAction<any, any>>();
|
const actionMap = new Map<string, BaseAction<any, any>>();
|
||||||
for (const action of actionHandlers) {
|
for (const action of actionHandlers) {
|
||||||
actionMap.set(action.actionName, action);
|
actionMap.set(action.actionName, action);
|
||||||
|
actionMap.set(action.actionName + '_async', action);
|
||||||
|
actionMap.set(action.actionName + '_rate_limited', action);
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionMap
|
return actionMap
|
||||||
|
@ -74,15 +74,15 @@ export interface ReturnDataType {
|
|||||||
|
|
||||||
export function convertMessage2List(message: OB11MessageMixType, autoEscape = false) {
|
export function convertMessage2List(message: OB11MessageMixType, autoEscape = false) {
|
||||||
if (typeof message === "string") {
|
if (typeof message === "string") {
|
||||||
if (!autoEscape) {
|
if (autoEscape === true) {
|
||||||
message = decodeCQCode(message.toString())
|
|
||||||
} else {
|
|
||||||
message = [{
|
message = [{
|
||||||
type: OB11MessageDataType.text,
|
type: OB11MessageDataType.text,
|
||||||
data: {
|
data: {
|
||||||
text: message
|
text: message
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
|
} else {
|
||||||
|
message = decodeCQCode(message.toString())
|
||||||
}
|
}
|
||||||
} else if (!Array.isArray(message)) {
|
} else if (!Array.isArray(message)) {
|
||||||
message = [message]
|
message = [message]
|
||||||
@ -329,7 +329,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
} else {
|
} else {
|
||||||
throw ("发送消息参数错误, 请指定group_id或user_id")
|
throw ("发送消息参数错误, 请指定group_id或user_id")
|
||||||
}
|
}
|
||||||
const messages = convertMessage2List(payload.message, !!payload.auto_escape);
|
const messages = convertMessage2List(payload.message, payload.auto_escape);
|
||||||
if (this.getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
if (this.getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
||||||
try {
|
try {
|
||||||
const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[], group)
|
const returnMsg = await this.handleForwardNode(peer, messages as OB11MessageNode[], group)
|
||||||
@ -508,6 +508,9 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
// nodeIds.push(nodeMsg.msgId)
|
// nodeIds.push(nodeMsg.msgId)
|
||||||
// await sleep(500);
|
// await sleep(500);
|
||||||
// 开发转发
|
// 开发转发
|
||||||
|
if (nodeMsgIds.length === 0) {
|
||||||
|
throw Error("转发消息失败,节点为空")
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
log("开发转发", nodeMsgIds)
|
log("开发转发", nodeMsgIds)
|
||||||
return await NTQQMsgApi.multiForwardMsg(srcPeer, destPeer, nodeMsgIds)
|
return await NTQQMsgApi.multiForwardMsg(srcPeer, destPeer, nodeMsgIds)
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
OB11Group,
|
OB11Group,
|
||||||
OB11GroupMember,
|
OB11GroupMember,
|
||||||
OB11GroupMemberRole,
|
OB11GroupMemberRole,
|
||||||
OB11Message,
|
OB11Message,
|
||||||
OB11MessageData,
|
OB11MessageData,
|
||||||
OB11MessageDataType,
|
OB11MessageDataType,
|
||||||
OB11User,
|
OB11User,
|
||||||
OB11UserSex
|
OB11UserSex
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import {
|
import {
|
||||||
AtType,
|
AtType,
|
||||||
ChatType, FaceIndex,
|
ChatType, FaceIndex,
|
||||||
GrayTipElementSubType,
|
GrayTipElementSubType,
|
||||||
Group,
|
Group,
|
||||||
GroupMember,
|
GroupMember,
|
||||||
IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT,
|
IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT,
|
||||||
RawMessage,
|
RawMessage,
|
||||||
SelfInfo,
|
SelfInfo,
|
||||||
Sex,
|
Sex,
|
||||||
TipGroupElementType,
|
TipGroupElementType,
|
||||||
User,
|
User,
|
||||||
VideoElement
|
VideoElement
|
||||||
} from '../ntqqapi/types';
|
} from '../ntqqapi/types';
|
||||||
import {getFriend, getGroupMember, selfInfo, tempGroupCodeMap} from '../common/data';
|
import {deleteGroup, getFriend, getGroupMember, groups, selfInfo, tempGroupCodeMap} from '../common/data';
|
||||||
import {EventType} from "./event/OB11BaseEvent";
|
import {EventType} from "./event/OB11BaseEvent";
|
||||||
import {encodeCQCode} from "./cqcode";
|
import {encodeCQCode} from "./cqcode";
|
||||||
import {dbUtil} from "../common/db";
|
import {dbUtil} from "../common/db";
|
||||||
@ -39,447 +39,450 @@ import {getConfigUtil} from "../common/config";
|
|||||||
import {OB11GroupTitleEvent} from "./event/notice/OB11GroupTitleEvent";
|
import {OB11GroupTitleEvent} from "./event/notice/OB11GroupTitleEvent";
|
||||||
import {OB11GroupCardEvent} from "./event/notice/OB11GroupCardEvent";
|
import {OB11GroupCardEvent} from "./event/notice/OB11GroupCardEvent";
|
||||||
import {OB11GroupDecreaseEvent} from "./event/notice/OB11GroupDecreaseEvent";
|
import {OB11GroupDecreaseEvent} from "./event/notice/OB11GroupDecreaseEvent";
|
||||||
|
import {NTQQGroupApi} from "../ntqqapi/api";
|
||||||
|
|
||||||
let lastRKeyUpdateTime = 0;
|
let lastRKeyUpdateTime = 0;
|
||||||
|
|
||||||
export class OB11Constructor {
|
export class OB11Constructor {
|
||||||
static async message(msg: RawMessage): Promise<OB11Message> {
|
static async message(msg: RawMessage): Promise<OB11Message> {
|
||||||
let config = getConfigUtil().getConfig();
|
let config = getConfigUtil().getConfig();
|
||||||
const {enableLocalFile2Url, ob11: {messagePostFormat}} = config;
|
const {enableLocalFile2Url, ob11: {messagePostFormat}} = config;
|
||||||
const message_type = msg.chatType == ChatType.group ? "group" : "private";
|
const message_type = msg.chatType == ChatType.group ? "group" : "private";
|
||||||
const resMsg: OB11Message = {
|
const resMsg: OB11Message = {
|
||||||
self_id: parseInt(selfInfo.uin),
|
self_id: parseInt(selfInfo.uin),
|
||||||
user_id: parseInt(msg.senderUin),
|
user_id: parseInt(msg.senderUin),
|
||||||
time: parseInt(msg.msgTime) || Date.now(),
|
time: parseInt(msg.msgTime) || Date.now(),
|
||||||
message_id: msg.msgShortId,
|
message_id: msg.msgShortId,
|
||||||
real_id: msg.msgShortId,
|
real_id: msg.msgShortId,
|
||||||
message_type: msg.chatType == ChatType.group ? "group" : "private",
|
message_type: msg.chatType == ChatType.group ? "group" : "private",
|
||||||
sender: {
|
sender: {
|
||||||
user_id: parseInt(msg.senderUin),
|
user_id: parseInt(msg.senderUin),
|
||||||
nickname: msg.sendNickName,
|
nickname: msg.sendNickName,
|
||||||
card: msg.sendMemberName || "",
|
card: msg.sendMemberName || "",
|
||||||
},
|
},
|
||||||
raw_message: "",
|
raw_message: "",
|
||||||
font: 14,
|
font: 14,
|
||||||
sub_type: "friend",
|
sub_type: "friend",
|
||||||
message: messagePostFormat === 'string' ? '' : [],
|
message: messagePostFormat === 'string' ? '' : [],
|
||||||
message_format: messagePostFormat === 'string' ? 'string' : 'array',
|
message_format: messagePostFormat === 'string' ? 'string' : 'array',
|
||||||
post_type: selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE,
|
post_type: selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE,
|
||||||
}
|
}
|
||||||
if (msg.chatType == ChatType.group) {
|
if (msg.chatType == ChatType.group) {
|
||||||
resMsg.sub_type = "normal" // 这里go-cqhttp是group,而onebot11标准是normal, 蛋疼
|
resMsg.sub_type = "normal" // 这里go-cqhttp是group,而onebot11标准是normal, 蛋疼
|
||||||
resMsg.group_id = parseInt(msg.peerUin)
|
resMsg.group_id = parseInt(msg.peerUin)
|
||||||
const member = await getGroupMember(msg.peerUin, msg.senderUin);
|
const member = await getGroupMember(msg.peerUin, msg.senderUin);
|
||||||
if (member) {
|
if (member) {
|
||||||
resMsg.sender.role = OB11Constructor.groupMemberRole(member.role);
|
resMsg.sender.role = OB11Constructor.groupMemberRole(member.role);
|
||||||
resMsg.sender.nickname = member.nick
|
resMsg.sender.nickname = member.nick
|
||||||
|
}
|
||||||
|
} else if (msg.chatType == ChatType.friend) {
|
||||||
|
resMsg.sub_type = "friend"
|
||||||
|
const friend = await getFriend(msg.senderUin);
|
||||||
|
if (friend) {
|
||||||
|
resMsg.sender.nickname = friend.nick;
|
||||||
|
}
|
||||||
|
} else if (msg.chatType == ChatType.temp) {
|
||||||
|
resMsg.sub_type = "group"
|
||||||
|
const tempGroupCode = tempGroupCodeMap[msg.peerUin]
|
||||||
|
if (tempGroupCode) {
|
||||||
|
resMsg.group_id = parseInt(tempGroupCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let element of msg.elements) {
|
||||||
|
let message_data: OB11MessageData | any = {
|
||||||
|
data: {},
|
||||||
|
type: "unknown"
|
||||||
|
}
|
||||||
|
if (element.textElement && element.textElement?.atType !== AtType.notAt) {
|
||||||
|
message_data["type"] = OB11MessageDataType.at
|
||||||
|
if (element.textElement.atType == AtType.atAll) {
|
||||||
|
// message_data["data"]["mention"] = "all"
|
||||||
|
message_data["data"]["qq"] = "all"
|
||||||
|
} else {
|
||||||
|
let atUid = element.textElement.atNtUid
|
||||||
|
let atQQ = element.textElement.atUid
|
||||||
|
if (!atQQ || atQQ === "0") {
|
||||||
|
const atMember = await getGroupMember(msg.peerUin, atUid)
|
||||||
|
if (atMember) {
|
||||||
|
atQQ = atMember.uin
|
||||||
}
|
}
|
||||||
} else if (msg.chatType == ChatType.friend) {
|
}
|
||||||
resMsg.sub_type = "friend"
|
if (atQQ) {
|
||||||
const friend = await getFriend(msg.senderUin);
|
// message_data["data"]["mention"] = atQQ
|
||||||
if (friend) {
|
message_data["data"]["qq"] = atQQ
|
||||||
resMsg.sender.nickname = friend.nick;
|
}
|
||||||
|
}
|
||||||
|
} else if (element.textElement) {
|
||||||
|
message_data["type"] = "text"
|
||||||
|
let text = element.textElement.content
|
||||||
|
if (!text.trim()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
message_data["data"]["text"] = text
|
||||||
|
} else if (element.replyElement) {
|
||||||
|
message_data["type"] = "reply"
|
||||||
|
// log("收到回复消息", element.replyElement.replayMsgSeq)
|
||||||
|
try {
|
||||||
|
const replyMsg = await dbUtil.getMsgBySeqId(element.replyElement.replayMsgSeq)
|
||||||
|
// log("找到回复消息", replyMsg.msgShortId, replyMsg.msgId)
|
||||||
|
if (replyMsg) {
|
||||||
|
message_data["data"]["id"] = replyMsg.msgShortId.toString()
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log("获取不到引用的消息", e.stack, element.replyElement.replayMsgSeq)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (element.picElement) {
|
||||||
|
message_data["type"] = "image"
|
||||||
|
// message_data["data"]["file"] = element.picElement.sourcePath
|
||||||
|
message_data["data"]["file"] = element.picElement.fileName
|
||||||
|
// message_data["data"]["path"] = element.picElement.sourcePath
|
||||||
|
const url = element.picElement.originImageUrl
|
||||||
|
const fileMd5 = element.picElement.md5HexStr
|
||||||
|
const fileUuid = element.picElement.fileUuid
|
||||||
|
// let currentRKey = config.imageRKey || "CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64"
|
||||||
|
let currentRKey = "CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64"
|
||||||
|
if (url) {
|
||||||
|
if (url.startsWith("/download")) {
|
||||||
|
if (url.includes("&rkey=")) {
|
||||||
|
// 正则提取rkey
|
||||||
|
// const rkey = url.match(/&rkey=([^&]+)/)[1]
|
||||||
|
// // log("图片url已有rkey", rkey)
|
||||||
|
// if (rkey != currentRKey){
|
||||||
|
// config.imageRKey = rkey
|
||||||
|
// if (Date.now() - lastRKeyUpdateTime > 1000 * 60) {
|
||||||
|
// lastRKeyUpdateTime = Date.now()
|
||||||
|
// getConfigUtil().setConfig(config)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
message_data["data"]["url"] = IMAGE_HTTP_HOST + url
|
||||||
|
} else {
|
||||||
|
// 有可能会碰到appid为1406的,这个不能使用新的NT域名,并且需要把appid改为1407才可访问
|
||||||
|
message_data["data"]["url"] = `${IMAGE_HTTP_HOST}/download?appid=1407&fileid=${fileUuid}&rkey=${currentRKey}&spec=0`
|
||||||
}
|
}
|
||||||
} else if (msg.chatType == ChatType.temp) {
|
} else {
|
||||||
resMsg.sub_type = "group"
|
message_data["data"]["url"] = IMAGE_HTTP_HOST + url
|
||||||
const tempGroupCode = tempGroupCodeMap[msg.peerUin]
|
}
|
||||||
if (tempGroupCode) {
|
} else if (fileMd5) {
|
||||||
resMsg.group_id = parseInt(tempGroupCode)
|
message_data["data"]["url"] = `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${fileMd5.toUpperCase()}/0`
|
||||||
|
}
|
||||||
|
// message_data["data"]["file_id"] = element.picElement.fileUuid
|
||||||
|
message_data["data"]["file_size"] = element.picElement.fileSize
|
||||||
|
dbUtil.addFileCache(element.picElement.fileName, {
|
||||||
|
fileName: element.picElement.fileName,
|
||||||
|
filePath: element.picElement.sourcePath,
|
||||||
|
fileSize: element.picElement.fileSize.toString(),
|
||||||
|
url: message_data["data"]["url"],
|
||||||
|
downloadFunc: async () => {
|
||||||
|
await NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
||||||
|
element.elementId, element.picElement.thumbPath?.get(0) || "", element.picElement.sourcePath)
|
||||||
|
}
|
||||||
|
}).then()
|
||||||
|
// 不在自动下载图片
|
||||||
|
|
||||||
|
} else if (element.videoElement || element.fileElement) {
|
||||||
|
const videoOrFileElement = element.videoElement || element.fileElement
|
||||||
|
const ob11MessageDataType = element.videoElement ? OB11MessageDataType.video : OB11MessageDataType.file
|
||||||
|
message_data["type"] = ob11MessageDataType;
|
||||||
|
message_data["data"]["file"] = videoOrFileElement.fileName
|
||||||
|
message_data["data"]["path"] = videoOrFileElement.filePath
|
||||||
|
message_data["data"]["file_id"] = videoOrFileElement.fileUuid
|
||||||
|
message_data["data"]["file_size"] = videoOrFileElement.fileSize
|
||||||
|
dbUtil.addFileCache(videoOrFileElement.fileUuid, {
|
||||||
|
msgId: msg.msgId,
|
||||||
|
fileName: videoOrFileElement.fileName,
|
||||||
|
filePath: videoOrFileElement.filePath,
|
||||||
|
fileSize: videoOrFileElement.fileSize,
|
||||||
|
downloadFunc: async () => {
|
||||||
|
await NTQQFileApi.downloadMedia(
|
||||||
|
msg.msgId, msg.chatType, msg.peerUid,
|
||||||
|
element.elementId,
|
||||||
|
ob11MessageDataType == OB11MessageDataType.video ? (videoOrFileElement as VideoElement).thumbPath.get(0) : null,
|
||||||
|
videoOrFileElement.filePath)
|
||||||
|
}
|
||||||
|
}).then()
|
||||||
|
// 怎么拿到url呢
|
||||||
|
} else if (element.pttElement) {
|
||||||
|
message_data["type"] = OB11MessageDataType.voice;
|
||||||
|
message_data["data"]["file"] = element.pttElement.fileName
|
||||||
|
message_data["data"]["path"] = element.pttElement.filePath
|
||||||
|
// message_data["data"]["file_id"] = element.pttElement.fileUuid
|
||||||
|
message_data["data"]["file_size"] = element.pttElement.fileSize
|
||||||
|
dbUtil.addFileCache(element.pttElement.fileName, {
|
||||||
|
fileName: element.pttElement.fileName,
|
||||||
|
filePath: element.pttElement.filePath,
|
||||||
|
fileSize: element.pttElement.fileSize,
|
||||||
|
}).then()
|
||||||
|
|
||||||
|
// log("收到语音消息", msg)
|
||||||
|
// window.LLAPI.Ptt2Text(message.raw.msgId, message.peer, messages).then(text => {
|
||||||
|
// console.log("语音转文字结果", text);
|
||||||
|
// }).catch(err => {
|
||||||
|
// console.log("语音转文字失败", err);
|
||||||
|
// })
|
||||||
|
} else if (element.arkElement) {
|
||||||
|
message_data["type"] = OB11MessageDataType.json;
|
||||||
|
message_data["data"]["data"] = element.arkElement.bytesData;
|
||||||
|
} else if (element.faceElement) {
|
||||||
|
const faceId = element.faceElement.faceIndex;
|
||||||
|
if (faceId === FaceIndex.dice) {
|
||||||
|
message_data["type"] = OB11MessageDataType.dice
|
||||||
|
message_data["data"]["result"] = element.faceElement.resultId;
|
||||||
|
} else if (faceId === FaceIndex.RPS) {
|
||||||
|
message_data["type"] = OB11MessageDataType.RPS
|
||||||
|
message_data["data"]["result"] = element.faceElement.resultId;
|
||||||
|
} else {
|
||||||
|
message_data["type"] = OB11MessageDataType.face;
|
||||||
|
message_data["data"]["id"] = element.faceElement.faceIndex.toString();
|
||||||
|
}
|
||||||
|
} else if (element.marketFaceElement) {
|
||||||
|
message_data["type"] = OB11MessageDataType.mface;
|
||||||
|
message_data["data"]["text"] = element.marketFaceElement.faceName;
|
||||||
|
} else if (element.markdownElement) {
|
||||||
|
message_data["type"] = OB11MessageDataType.markdown;
|
||||||
|
message_data["data"]["data"] = element.markdownElement.content;
|
||||||
|
} else if (element.multiForwardMsgElement) {
|
||||||
|
message_data["type"] = OB11MessageDataType.forward;
|
||||||
|
message_data["data"]["id"] = msg.msgId
|
||||||
|
}
|
||||||
|
if (message_data.type !== "unknown" && message_data.data) {
|
||||||
|
const cqCode = encodeCQCode(message_data);
|
||||||
|
if (messagePostFormat === 'string') {
|
||||||
|
(resMsg.message as string) += cqCode;
|
||||||
|
} else (resMsg.message as OB11MessageData[]).push(message_data);
|
||||||
|
|
||||||
|
resMsg.raw_message += cqCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resMsg.raw_message = resMsg.raw_message.trim();
|
||||||
|
return resMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async GroupEvent(msg: RawMessage): Promise<OB11GroupNoticeEvent> {
|
||||||
|
if (msg.chatType !== ChatType.group) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg.senderUin) {
|
||||||
|
let member = await getGroupMember(msg.peerUid, msg.senderUin);
|
||||||
|
if (member && member.cardName !== msg.sendMemberName) {
|
||||||
|
const event = new OB11GroupCardEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), msg.sendMemberName, member.cardName)
|
||||||
|
member.cardName = msg.sendMemberName;
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// log("group msg", msg);
|
||||||
|
for (let element of msg.elements) {
|
||||||
|
const grayTipElement = element.grayTipElement
|
||||||
|
const groupElement = grayTipElement?.groupElement
|
||||||
|
if (groupElement) {
|
||||||
|
// log("收到群提示消息", groupElement)
|
||||||
|
if (groupElement.type == TipGroupElementType.memberIncrease) {
|
||||||
|
log("收到群成员增加消息", groupElement)
|
||||||
|
await sleep(1000);
|
||||||
|
const member = await getGroupMember(msg.peerUid, groupElement.memberUid);
|
||||||
|
let memberUin = member?.uin;
|
||||||
|
if (!memberUin) {
|
||||||
|
memberUin = (await NTQQUserApi.getUserDetailInfo(groupElement.memberUid)).uin
|
||||||
|
}
|
||||||
|
// log("获取新群成员QQ", memberUin)
|
||||||
|
const adminMember = await getGroupMember(msg.peerUid, groupElement.adminUid);
|
||||||
|
// log("获取同意新成员入群的管理员", adminMember)
|
||||||
|
if (memberUin) {
|
||||||
|
const operatorUin = adminMember?.uin || memberUin
|
||||||
|
let event = new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(memberUin), parseInt(operatorUin));
|
||||||
|
// log("构造群增加事件", event)
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
} else if (groupElement.type === TipGroupElementType.ban) {
|
||||||
|
log("收到群群员禁言提示", groupElement)
|
||||||
|
const memberUid = groupElement.shutUp.member.uid
|
||||||
|
const adminUid = groupElement.shutUp.admin.uid
|
||||||
|
let memberUin: string = ""
|
||||||
|
let duration = parseInt(groupElement.shutUp.duration)
|
||||||
|
let sub_type: "ban" | "lift_ban" = duration > 0 ? "ban" : "lift_ban"
|
||||||
|
if (memberUid) {
|
||||||
|
memberUin = (await getGroupMember(msg.peerUid, memberUid))?.uin || (await NTQQUserApi.getUserDetailInfo(memberUid))?.uin
|
||||||
|
} else {
|
||||||
|
memberUin = "0"; // 0表示全员禁言
|
||||||
|
if (duration > 0) {
|
||||||
|
duration = -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const adminUin = (await getGroupMember(msg.peerUid, adminUid))?.uin || (await NTQQUserApi.getUserDetailInfo(adminUid))?.uin
|
||||||
for (let element of msg.elements) {
|
if (memberUin && adminUin) {
|
||||||
let message_data: OB11MessageData | any = {
|
return new OB11GroupBanEvent(parseInt(msg.peerUid), parseInt(memberUin), parseInt(adminUin), duration, sub_type);
|
||||||
data: {},
|
}
|
||||||
type: "unknown"
|
} else if (groupElement.type == TipGroupElementType.kicked) {
|
||||||
|
log(`收到我被踢出或退群提示, 群${msg.peerUid}`, groupElement)
|
||||||
|
deleteGroup(msg.peerUid);
|
||||||
|
NTQQGroupApi.quitGroup(msg.peerUid).then()
|
||||||
|
try {
|
||||||
|
const adminUin = (await getGroupMember(msg.peerUid, groupElement.adminUid))?.uin || (await NTQQUserApi.getUserDetailInfo(groupElement.adminUid))?.uin
|
||||||
|
if (adminUin) {
|
||||||
|
return new OB11GroupDecreaseEvent(parseInt(msg.peerUid), parseInt(selfInfo.uin), parseInt(adminUin), "kick_me");
|
||||||
}
|
}
|
||||||
if (element.textElement && element.textElement?.atType !== AtType.notAt) {
|
} catch (e) {
|
||||||
message_data["type"] = OB11MessageDataType.at
|
return new OB11GroupDecreaseEvent(parseInt(msg.peerUid), parseInt(selfInfo.uin), 0, "leave");
|
||||||
if (element.textElement.atType == AtType.atAll) {
|
}
|
||||||
// message_data["data"]["mention"] = "all"
|
}
|
||||||
message_data["data"]["qq"] = "all"
|
} else if (element.fileElement) {
|
||||||
} else {
|
return new OB11GroupUploadNoticeEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), {
|
||||||
let atUid = element.textElement.atNtUid
|
id: element.fileElement.fileUuid,
|
||||||
let atQQ = element.textElement.atUid
|
name: element.fileElement.fileName,
|
||||||
if (!atQQ || atQQ === "0") {
|
size: parseInt(element.fileElement.fileSize),
|
||||||
const atMember = await getGroupMember(msg.peerUin, atUid)
|
busid: element.fileElement.fileBizId || 0
|
||||||
if (atMember) {
|
})
|
||||||
atQQ = atMember.uin
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if (atQQ) {
|
|
||||||
// message_data["data"]["mention"] = atQQ
|
|
||||||
message_data["data"]["qq"] = atQQ
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (element.textElement) {
|
|
||||||
message_data["type"] = "text"
|
|
||||||
let text = element.textElement.content
|
|
||||||
if (!text.trim()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
message_data["data"]["text"] = text
|
|
||||||
} else if (element.replyElement) {
|
|
||||||
message_data["type"] = "reply"
|
|
||||||
// log("收到回复消息", element.replyElement.replayMsgSeq)
|
|
||||||
try {
|
|
||||||
const replyMsg = await dbUtil.getMsgBySeqId(element.replyElement.replayMsgSeq)
|
|
||||||
// log("找到回复消息", replyMsg.msgShortId, replyMsg.msgId)
|
|
||||||
if (replyMsg) {
|
|
||||||
message_data["data"]["id"] = replyMsg.msgShortId.toString()
|
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log("获取不到引用的消息", e.stack, element.replyElement.replayMsgSeq)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (element.picElement) {
|
if (grayTipElement) {
|
||||||
message_data["type"] = "image"
|
if (grayTipElement.subElementType == GrayTipElementSubType.INVITE_NEW_MEMBER) {
|
||||||
// message_data["data"]["file"] = element.picElement.sourcePath
|
log("收到新人被邀请进群消息", grayTipElement)
|
||||||
message_data["data"]["file"] = element.picElement.fileName
|
const xmlElement = grayTipElement.xmlElement
|
||||||
// message_data["data"]["path"] = element.picElement.sourcePath
|
if (xmlElement?.content) {
|
||||||
const url = element.picElement.originImageUrl
|
const regex = /jp="(\d+)"/g;
|
||||||
const fileMd5 = element.picElement.md5HexStr
|
|
||||||
const fileUuid = element.picElement.fileUuid
|
|
||||||
// let currentRKey = config.imageRKey || "CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64"
|
|
||||||
let currentRKey = "CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64"
|
|
||||||
if (url) {
|
|
||||||
if (url.startsWith("/download")) {
|
|
||||||
if (url.includes("&rkey=")) {
|
|
||||||
// 正则提取rkey
|
|
||||||
// const rkey = url.match(/&rkey=([^&]+)/)[1]
|
|
||||||
// // log("图片url已有rkey", rkey)
|
|
||||||
// if (rkey != currentRKey){
|
|
||||||
// config.imageRKey = rkey
|
|
||||||
// if (Date.now() - lastRKeyUpdateTime > 1000 * 60) {
|
|
||||||
// lastRKeyUpdateTime = Date.now()
|
|
||||||
// getConfigUtil().setConfig(config)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
message_data["data"]["url"] = IMAGE_HTTP_HOST + url
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// 有可能会碰到appid为1406的,这个不能使用新的NT域名,并且需要把appid改为1407才可访问
|
|
||||||
message_data["data"]["url"] = `${IMAGE_HTTP_HOST}/download?appid=1407&fileid=${fileUuid}&rkey=${currentRKey}&spec=0`
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message_data["data"]["url"] = IMAGE_HTTP_HOST + url
|
|
||||||
}
|
|
||||||
} else if (fileMd5) {
|
|
||||||
message_data["data"]["url"] = `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${fileMd5.toUpperCase()}/0`
|
|
||||||
}
|
|
||||||
// message_data["data"]["file_id"] = element.picElement.fileUuid
|
|
||||||
message_data["data"]["file_size"] = element.picElement.fileSize
|
|
||||||
dbUtil.addFileCache(element.picElement.fileName, {
|
|
||||||
fileName: element.picElement.fileName,
|
|
||||||
filePath: element.picElement.sourcePath,
|
|
||||||
fileSize: element.picElement.fileSize.toString(),
|
|
||||||
url: message_data["data"]["url"],
|
|
||||||
downloadFunc: async () => {
|
|
||||||
await NTQQFileApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
|
||||||
element.elementId, element.picElement.thumbPath?.get(0) || "", element.picElement.sourcePath)
|
|
||||||
}
|
|
||||||
}).then()
|
|
||||||
// 不在自动下载图片
|
|
||||||
|
|
||||||
} else if (element.videoElement || element.fileElement) {
|
let matches = [];
|
||||||
const videoOrFileElement = element.videoElement || element.fileElement
|
let match = null
|
||||||
const ob11MessageDataType = element.videoElement ? OB11MessageDataType.video : OB11MessageDataType.file
|
|
||||||
message_data["type"] = ob11MessageDataType;
|
|
||||||
message_data["data"]["file"] = videoOrFileElement.fileName
|
|
||||||
message_data["data"]["path"] = videoOrFileElement.filePath
|
|
||||||
message_data["data"]["file_id"] = videoOrFileElement.fileUuid
|
|
||||||
message_data["data"]["file_size"] = videoOrFileElement.fileSize
|
|
||||||
dbUtil.addFileCache(videoOrFileElement.fileUuid, {
|
|
||||||
msgId: msg.msgId,
|
|
||||||
fileName: videoOrFileElement.fileName,
|
|
||||||
filePath: videoOrFileElement.filePath,
|
|
||||||
fileSize: videoOrFileElement.fileSize,
|
|
||||||
downloadFunc: async () => {
|
|
||||||
await NTQQFileApi.downloadMedia(
|
|
||||||
msg.msgId, msg.chatType, msg.peerUid,
|
|
||||||
element.elementId,
|
|
||||||
ob11MessageDataType == OB11MessageDataType.video ? (videoOrFileElement as VideoElement).thumbPath.get(0) : null,
|
|
||||||
videoOrFileElement.filePath)
|
|
||||||
}
|
|
||||||
}).then()
|
|
||||||
// 怎么拿到url呢
|
|
||||||
} else if (element.pttElement) {
|
|
||||||
message_data["type"] = OB11MessageDataType.voice;
|
|
||||||
message_data["data"]["file"] = element.pttElement.fileName
|
|
||||||
message_data["data"]["path"] = element.pttElement.filePath
|
|
||||||
// message_data["data"]["file_id"] = element.pttElement.fileUuid
|
|
||||||
message_data["data"]["file_size"] = element.pttElement.fileSize
|
|
||||||
dbUtil.addFileCache(element.pttElement.fileName, {
|
|
||||||
fileName: element.pttElement.fileName,
|
|
||||||
filePath: element.pttElement.filePath,
|
|
||||||
fileSize: element.pttElement.fileSize,
|
|
||||||
}).then()
|
|
||||||
|
|
||||||
// log("收到语音消息", msg)
|
while ((match = regex.exec(xmlElement.content)) !== null) {
|
||||||
// window.LLAPI.Ptt2Text(message.raw.msgId, message.peer, messages).then(text => {
|
matches.push(match[1]);
|
||||||
// console.log("语音转文字结果", text);
|
|
||||||
// }).catch(err => {
|
|
||||||
// console.log("语音转文字失败", err);
|
|
||||||
// })
|
|
||||||
} else if (element.arkElement) {
|
|
||||||
message_data["type"] = OB11MessageDataType.json;
|
|
||||||
message_data["data"]["data"] = element.arkElement.bytesData;
|
|
||||||
} else if (element.faceElement) {
|
|
||||||
const faceId = element.faceElement.faceIndex;
|
|
||||||
if (faceId === FaceIndex.dice){
|
|
||||||
message_data["type"] = OB11MessageDataType.dice
|
|
||||||
message_data["data"]["result"] = element.faceElement.resultId;
|
|
||||||
}
|
|
||||||
else if (faceId === FaceIndex.RPS){
|
|
||||||
message_data["type"] = OB11MessageDataType.RPS
|
|
||||||
message_data["data"]["result"] = element.faceElement.resultId;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
message_data["type"] = OB11MessageDataType.face;
|
|
||||||
message_data["data"]["id"] = element.faceElement.faceIndex.toString();
|
|
||||||
}
|
|
||||||
} else if (element.marketFaceElement) {
|
|
||||||
message_data["type"] = OB11MessageDataType.mface;
|
|
||||||
message_data["data"]["text"] = element.marketFaceElement.faceName;
|
|
||||||
} else if (element.markdownElement){
|
|
||||||
message_data["type"] = OB11MessageDataType.markdown;
|
|
||||||
message_data["data"]["data"] = element.markdownElement.content;
|
|
||||||
} else if (element.multiForwardMsgElement){
|
|
||||||
message_data["type"] = OB11MessageDataType.forward;
|
|
||||||
message_data["data"]["id"] = msg.msgId
|
|
||||||
}
|
}
|
||||||
if (message_data.type !== "unknown" && message_data.data) {
|
// log("新人进群匹配到的QQ号", matches)
|
||||||
const cqCode = encodeCQCode(message_data);
|
if (matches.length === 2) {
|
||||||
if (messagePostFormat === 'string') {
|
const [inviter, invitee] = matches;
|
||||||
(resMsg.message as string) += cqCode;
|
return new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(invitee), parseInt(inviter), "invite");
|
||||||
} else (resMsg.message as OB11MessageData[]).push(message_data);
|
|
||||||
|
|
||||||
resMsg.raw_message += cqCode;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else if (grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
|
||||||
|
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr)
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
align: 'center',
|
||||||
|
items: [
|
||||||
|
{ txt: '恭喜', type: 'nor' },
|
||||||
|
{
|
||||||
|
col: '3',
|
||||||
|
jp: '5',
|
||||||
|
param: ["QQ号"],
|
||||||
|
txt: '林雨辰',
|
||||||
|
type: 'url'
|
||||||
|
},
|
||||||
|
{ txt: '获得群主授予的', type: 'nor' },
|
||||||
|
{
|
||||||
|
col: '3',
|
||||||
|
jp: '',
|
||||||
|
txt: '好好好',
|
||||||
|
type: 'url'
|
||||||
|
},
|
||||||
|
{ txt: '头衔', type: 'nor' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
* */
|
||||||
|
const memberUin = json.items[1].param[0]
|
||||||
|
const title = json.items[3].txt
|
||||||
|
log("收到群成员新头衔消息", json)
|
||||||
|
getGroupMember(msg.peerUid, memberUin).then(member => {
|
||||||
|
member.memberSpecialTitle = title
|
||||||
|
})
|
||||||
|
return new OB11GroupTitleEvent(parseInt(msg.peerUid), parseInt(memberUin), title)
|
||||||
}
|
}
|
||||||
resMsg.raw_message = resMsg.raw_message.trim();
|
}
|
||||||
return resMsg;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static async GroupEvent(msg: RawMessage): Promise<OB11GroupNoticeEvent> {
|
static friend(friend: User): OB11User {
|
||||||
if (msg.chatType !== ChatType.group) {
|
return {
|
||||||
return;
|
user_id: parseInt(friend.uin),
|
||||||
}
|
nickname: friend.nick,
|
||||||
if (msg.senderUin){
|
remark: friend.remark,
|
||||||
let member = await getGroupMember(msg.peerUid, msg.senderUin);
|
sex: OB11Constructor.sex(friend.sex),
|
||||||
if (member && member.cardName !== msg.sendMemberName) {
|
level: friend.qqLevel && calcQQLevel(friend.qqLevel) || 0
|
||||||
const event = new OB11GroupCardEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), msg.sendMemberName, member.cardName)
|
|
||||||
member.cardName = msg.sendMemberName;
|
|
||||||
return event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// log("group msg", msg);
|
|
||||||
for (let element of msg.elements) {
|
|
||||||
const grayTipElement = element.grayTipElement
|
|
||||||
const groupElement = grayTipElement?.groupElement
|
|
||||||
if (groupElement) {
|
|
||||||
// log("收到群提示消息", groupElement)
|
|
||||||
if (groupElement.type == TipGroupElementType.memberIncrease) {
|
|
||||||
log("收到群成员增加消息", groupElement)
|
|
||||||
await sleep(1000);
|
|
||||||
const member = await getGroupMember(msg.peerUid, groupElement.memberUid);
|
|
||||||
let memberUin = member?.uin;
|
|
||||||
if (!memberUin) {
|
|
||||||
memberUin = (await NTQQUserApi.getUserDetailInfo(groupElement.memberUid)).uin
|
|
||||||
}
|
|
||||||
// log("获取新群成员QQ", memberUin)
|
|
||||||
const adminMember = await getGroupMember(msg.peerUid, groupElement.adminUid);
|
|
||||||
// log("获取同意新成员入群的管理员", adminMember)
|
|
||||||
if (memberUin) {
|
|
||||||
const operatorUin = adminMember?.uin || memberUin
|
|
||||||
let event = new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(memberUin), parseInt(operatorUin));
|
|
||||||
// log("构造群增加事件", event)
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
} else if (groupElement.type === TipGroupElementType.ban) {
|
|
||||||
log("收到群群员禁言提示", groupElement)
|
|
||||||
const memberUid = groupElement.shutUp.member.uid
|
|
||||||
const adminUid = groupElement.shutUp.admin.uid
|
|
||||||
let memberUin: string = ""
|
|
||||||
let duration = parseInt(groupElement.shutUp.duration)
|
|
||||||
let sub_type: "ban" | "lift_ban" = duration > 0 ? "ban" : "lift_ban"
|
|
||||||
if (memberUid) {
|
|
||||||
memberUin = (await getGroupMember(msg.peerUid, memberUid))?.uin || (await NTQQUserApi.getUserDetailInfo(memberUid))?.uin
|
|
||||||
} else {
|
|
||||||
memberUin = "0"; // 0表示全员禁言
|
|
||||||
if (duration > 0) {
|
|
||||||
duration = -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const adminUin = (await getGroupMember(msg.peerUid, adminUid))?.uin || (await NTQQUserApi.getUserDetailInfo(adminUid))?.uin
|
|
||||||
if (memberUin && adminUin) {
|
|
||||||
return new OB11GroupBanEvent(parseInt(msg.peerUid), parseInt(memberUin), parseInt(adminUin), duration, sub_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (groupElement.type == TipGroupElementType.kicked){
|
|
||||||
log("收到我被踢出提示", groupElement)
|
|
||||||
const adminUin = (await getGroupMember(msg.peerUid, groupElement.adminUid))?.uin || (await NTQQUserApi.getUserDetailInfo(groupElement.adminUid))?.uin
|
|
||||||
if (adminUin) {
|
|
||||||
return new OB11GroupDecreaseEvent(parseInt(msg.peerUid), parseInt(selfInfo.uin), parseInt(adminUin), "kick_me");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (element.fileElement) {
|
|
||||||
return new OB11GroupUploadNoticeEvent(parseInt(msg.peerUid), parseInt(msg.senderUin), {
|
|
||||||
id: element.fileElement.fileUuid,
|
|
||||||
name: element.fileElement.fileName,
|
|
||||||
size: parseInt(element.fileElement.fileSize),
|
|
||||||
busid: element.fileElement.fileBizId || 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grayTipElement) {
|
|
||||||
if (grayTipElement.subElementType == GrayTipElementSubType.INVITE_NEW_MEMBER) {
|
|
||||||
log("收到新人被邀请进群消息", grayTipElement)
|
|
||||||
const xmlElement = grayTipElement.xmlElement
|
|
||||||
if (xmlElement?.content) {
|
|
||||||
const regex = /jp="(\d+)"/g;
|
|
||||||
|
|
||||||
let matches = [];
|
|
||||||
let match = null
|
|
||||||
|
|
||||||
while ((match = regex.exec(xmlElement.content)) !== null) {
|
|
||||||
matches.push(match[1]);
|
|
||||||
}
|
|
||||||
// log("新人进群匹配到的QQ号", matches)
|
|
||||||
if (matches.length === 2) {
|
|
||||||
const [inviter, invitee] = matches;
|
|
||||||
return new OB11GroupIncreaseEvent(parseInt(msg.peerUid), parseInt(invitee), parseInt(inviter), "invite");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (grayTipElement.subElementType == GrayTipElementSubType.MEMBER_NEW_TITLE) {
|
|
||||||
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr)
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
align: 'center',
|
|
||||||
items: [
|
|
||||||
{ txt: '恭喜', type: 'nor' },
|
|
||||||
{
|
|
||||||
col: '3',
|
|
||||||
jp: '5',
|
|
||||||
param: ["QQ号"],
|
|
||||||
txt: '林雨辰',
|
|
||||||
type: 'url'
|
|
||||||
},
|
|
||||||
{ txt: '获得群主授予的', type: 'nor' },
|
|
||||||
{
|
|
||||||
col: '3',
|
|
||||||
jp: '',
|
|
||||||
txt: '好好好',
|
|
||||||
type: 'url'
|
|
||||||
},
|
|
||||||
{ txt: '头衔', type: 'nor' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
* */
|
|
||||||
const memberUin = json.items[1].param[0]
|
|
||||||
const title = json.items[3].txt
|
|
||||||
log("收到群成员新头衔消息", json)
|
|
||||||
getGroupMember(msg.peerUid, memberUin).then(member => {
|
|
||||||
member.memberSpecialTitle = title
|
|
||||||
})
|
|
||||||
return new OB11GroupTitleEvent(parseInt(msg.peerUid), parseInt(memberUin), title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static friend(friend: User): OB11User {
|
static selfInfo(selfInfo: SelfInfo): OB11User {
|
||||||
return {
|
return {
|
||||||
user_id: parseInt(friend.uin),
|
user_id: parseInt(selfInfo.uin),
|
||||||
nickname: friend.nick,
|
nickname: selfInfo.nick,
|
||||||
remark: friend.remark,
|
|
||||||
sex: OB11Constructor.sex(friend.sex),
|
|
||||||
level: friend.qqLevel && calcQQLevel(friend.qqLevel) || 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static selfInfo(selfInfo: SelfInfo): OB11User {
|
static friends(friends: User[]): OB11User[] {
|
||||||
return {
|
return friends.map(OB11Constructor.friend)
|
||||||
user_id: parseInt(selfInfo.uin),
|
}
|
||||||
nickname: selfInfo.nick,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static friends(friends: User[]): OB11User[] {
|
static groupMemberRole(role: number): OB11GroupMemberRole | undefined {
|
||||||
return friends.map(OB11Constructor.friend)
|
return {
|
||||||
}
|
4: OB11GroupMemberRole.owner,
|
||||||
|
3: OB11GroupMemberRole.admin,
|
||||||
|
2: OB11GroupMemberRole.member
|
||||||
|
}[role]
|
||||||
|
}
|
||||||
|
|
||||||
static groupMemberRole(role: number): OB11GroupMemberRole | undefined {
|
static sex(sex: Sex): OB11UserSex {
|
||||||
return {
|
const sexMap = {
|
||||||
4: OB11GroupMemberRole.owner,
|
[Sex.male]: OB11UserSex.male,
|
||||||
3: OB11GroupMemberRole.admin,
|
[Sex.female]: OB11UserSex.female,
|
||||||
2: OB11GroupMemberRole.member
|
[Sex.unknown]: OB11UserSex.unknown
|
||||||
}[role]
|
|
||||||
}
|
}
|
||||||
|
return sexMap[sex] || OB11UserSex.unknown
|
||||||
|
}
|
||||||
|
|
||||||
static sex(sex: Sex): OB11UserSex {
|
static groupMember(group_id: string, member: GroupMember): OB11GroupMember {
|
||||||
const sexMap = {
|
return {
|
||||||
[Sex.male]: OB11UserSex.male,
|
group_id: parseInt(group_id),
|
||||||
[Sex.female]: OB11UserSex.female,
|
user_id: parseInt(member.uin),
|
||||||
[Sex.unknown]: OB11UserSex.unknown
|
nickname: member.nick,
|
||||||
}
|
card: member.cardName,
|
||||||
return sexMap[sex] || OB11UserSex.unknown
|
sex: OB11Constructor.sex(member.sex),
|
||||||
|
age: 0,
|
||||||
|
area: "",
|
||||||
|
level: 0,
|
||||||
|
qq_level: member.qqLevel && calcQQLevel(member.qqLevel) || 0,
|
||||||
|
join_time: 0, // 暂时没法获取
|
||||||
|
last_sent_time: 0, // 暂时没法获取
|
||||||
|
title_expire_time: 0,
|
||||||
|
unfriendly: false,
|
||||||
|
card_changeable: true,
|
||||||
|
is_robot: member.isRobot,
|
||||||
|
shut_up_timestamp: member.shutUpTime,
|
||||||
|
role: OB11Constructor.groupMemberRole(member.role),
|
||||||
|
title: member.memberSpecialTitle || "",
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static groupMember(group_id: string, member: GroupMember): OB11GroupMember {
|
static stranger(user: User): OB11User {
|
||||||
return {
|
return {
|
||||||
group_id: parseInt(group_id),
|
...user,
|
||||||
user_id: parseInt(member.uin),
|
user_id: parseInt(user.uin),
|
||||||
nickname: member.nick,
|
nickname: user.nick,
|
||||||
card: member.cardName,
|
sex: OB11Constructor.sex(user.sex),
|
||||||
sex: OB11Constructor.sex(member.sex),
|
age: 0,
|
||||||
age: 0,
|
qid: user.qid,
|
||||||
area: "",
|
login_days: 0,
|
||||||
level: 0,
|
level: user.qqLevel && calcQQLevel(user.qqLevel) || 0,
|
||||||
qq_level: member.qqLevel && calcQQLevel(member.qqLevel) || 0,
|
|
||||||
join_time: 0, // 暂时没法获取
|
|
||||||
last_sent_time: 0, // 暂时没法获取
|
|
||||||
title_expire_time: 0,
|
|
||||||
unfriendly: false,
|
|
||||||
card_changeable: true,
|
|
||||||
is_robot: member.isRobot,
|
|
||||||
shut_up_timestamp: member.shutUpTime,
|
|
||||||
role: OB11Constructor.groupMemberRole(member.role),
|
|
||||||
title: member.memberSpecialTitle || "",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static stranger(user: User): OB11User {
|
static groupMembers(group: Group): OB11GroupMember[] {
|
||||||
return {
|
log("construct ob11 group members", group)
|
||||||
...user,
|
return group.members.map(m => OB11Constructor.groupMember(group.groupCode, m))
|
||||||
user_id: parseInt(user.uin),
|
}
|
||||||
nickname: user.nick,
|
|
||||||
sex: OB11Constructor.sex(user.sex),
|
|
||||||
age: 0,
|
|
||||||
qid: user.qid,
|
|
||||||
login_days: 0,
|
|
||||||
level: user.qqLevel && calcQQLevel(user.qqLevel) || 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static groupMembers(group: Group): OB11GroupMember[] {
|
static group(group: Group): OB11Group {
|
||||||
log("construct ob11 group members", group)
|
return {
|
||||||
return group.members.map(m => OB11Constructor.groupMember(group.groupCode, m))
|
group_id: parseInt(group.groupCode),
|
||||||
|
group_name: group.groupName,
|
||||||
|
member_count: group.memberCount,
|
||||||
|
max_member_count: group.maxMember
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static group(group: Group): OB11Group {
|
static groups(groups: Group[]): OB11Group[] {
|
||||||
return {
|
return groups.map(OB11Constructor.group)
|
||||||
group_id: parseInt(group.groupCode),
|
}
|
||||||
group_name: group.groupName,
|
|
||||||
member_count: group.memberCount,
|
|
||||||
max_member_count: group.maxMember
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static groups(groups: Group[]): OB11Group[] {
|
|
||||||
return groups.map(OB11Constructor.group)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import {Response} from "express";
|
import {Response} from "express";
|
||||||
import {OB11Response} from "../action/OB11Response";
|
import {OB11Response} from "../action/OB11Response";
|
||||||
import {HttpServerBase} from "../../common/server/http";
|
import {HttpServerBase} from "../../common/server/http";
|
||||||
import {actionHandlers} from "../action";
|
import {actionHandlers, actionMap} from "../action";
|
||||||
import {getConfigUtil} from "../../common/config";
|
import {getConfigUtil} from "../../common/config";
|
||||||
|
import {postOB11Event} from "./postOB11Event";
|
||||||
|
import {OB11HeartbeatEvent} from "../event/meta/OB11HeartbeatEvent";
|
||||||
|
import {selfInfo} from "../../common/data";
|
||||||
|
|
||||||
class OB11HTTPServer extends HttpServerBase {
|
class OB11HTTPServer extends HttpServerBase {
|
||||||
name = "OneBot V11 server"
|
name = "OneBot V11 server"
|
||||||
@ -21,9 +24,32 @@ class OB11HTTPServer extends HttpServerBase {
|
|||||||
export const ob11HTTPServer = new OB11HTTPServer();
|
export const ob11HTTPServer = new OB11HTTPServer();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
for (const action of actionHandlers) {
|
for (const [actionName, action] of actionMap) {
|
||||||
for (const method of ["post", "get"]) {
|
for (const method of ["post", "get"]) {
|
||||||
ob11HTTPServer.registerRouter(method, action.actionName, (res, payload) => action.handle(payload))
|
ob11HTTPServer.registerRouter(method, actionName, (res, payload) => action.handle(payload))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPHeart{
|
||||||
|
intervalId: NodeJS.Timeout | null = null
|
||||||
|
start(){
|
||||||
|
const {heartInterval} = getConfigUtil().getConfig();
|
||||||
|
if (this.intervalId) {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
}
|
||||||
|
this.intervalId = setInterval(() => {
|
||||||
|
// ws的心跳是ws自己维护的
|
||||||
|
postOB11Event(new OB11HeartbeatEvent(selfInfo.online, true, heartInterval), false, false)
|
||||||
|
}, heartInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
stop(){
|
||||||
|
if (this.intervalId){
|
||||||
|
clearInterval(this.intervalId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const httpHeart = new HTTPHeart();
|
@ -69,7 +69,7 @@ export function postWsEvent(event: PostEventType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function postOB11Event(msg: PostEventType, reportSelf = false) {
|
export function postOB11Event(msg: PostEventType, reportSelf = false, postWs = true) {
|
||||||
const config = getConfigUtil().getConfig();
|
const config = getConfigUtil().getConfig();
|
||||||
// 判断msg是否是event
|
// 判断msg是否是event
|
||||||
if (!config.reportSelfMessage && !reportSelf) {
|
if (!config.reportSelfMessage && !reportSelf) {
|
||||||
@ -172,5 +172,7 @@ export function postOB11Event(msg: PostEventType, reportSelf = false) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postWsEvent(msg);
|
if (postWs){
|
||||||
|
postWsEvent(msg);
|
||||||
|
}
|
||||||
}
|
}
|
@ -68,6 +68,9 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
`<div class="q-input"><input class="q-input__inner" data-config-key="ob11.httpPort" type="number" min="1" max="65534" value="${config.ob11.httpPort}" placeholder="${config.ob11.httpPort}" /></div>`,
|
`<div class="q-input"><input class="q-input__inner" data-config-key="ob11.httpPort" type="number" min="1" max="65534" value="${config.ob11.httpPort}" placeholder="${config.ob11.httpPort}" /></div>`,
|
||||||
'config-ob11-httpPort', config.ob11.enableHttp
|
'config-ob11-httpPort', config.ob11.enableHttp
|
||||||
),
|
),
|
||||||
|
SettingItem('启用 HTTP 心跳', null,
|
||||||
|
SettingSwitch('ob11.enableHttpHeart', config.ob11.enableHttpHeart, {'control-display-id': 'config-ob11-enableHttpHeart'}),
|
||||||
|
),
|
||||||
SettingItem('启用 HTTP 事件上报', null,
|
SettingItem('启用 HTTP 事件上报', null,
|
||||||
SettingSwitch('ob11.enableHttpPost', config.ob11.enableHttpPost, {'control-display-id': 'config-ob11-httpHosts'}),
|
SettingSwitch('ob11.enableHttpPost', config.ob11.enableHttpPost, {'control-display-id': 'config-ob11-httpHosts'}),
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user