mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9bb69058c2 | ||
![]() |
89971dd2e4 | ||
![]() |
aea67db27c | ||
![]() |
c4b45f8298 | ||
![]() |
1a77abfc62 | ||
![]() |
eb32ecb79b | ||
![]() |
ccf91f4a94 | ||
![]() |
282b2a0da0 | ||
![]() |
b28b812396 | ||
![]() |
1936671cb3 | ||
![]() |
6a8d67a8ae |
12
README.md
12
README.md
@@ -1,9 +1,11 @@
|
|||||||
# LLOneBot API
|
# LLOneBot API
|
||||||
|
|
||||||
将NTQQLiteLoaderAPI封装成OneBot11标准的API
|
LiteLoaderQQNT的OneBot11协议插件
|
||||||
|
|
||||||
*注意:本文档对应的是 LiteLoader 1.0.0及以上版本,如果你使用的是旧版本请切换到本项目v1分支查看文档*
|
*注意:本文档对应的是 LiteLoader 1.0.0及以上版本,如果你使用的是旧版本请切换到本项目v1分支查看文档*
|
||||||
|
|
||||||
|
*V3之后不再需要LLAPI*
|
||||||
|
|
||||||
## 安装方法
|
## 安装方法
|
||||||
|
|
||||||
1.安装[LiteLoaderQQNT](https://liteloaderqqnt.github.io/guide/install.html)
|
1.安装[LiteLoaderQQNT](https://liteloaderqqnt.github.io/guide/install.html)
|
||||||
@@ -16,7 +18,7 @@
|
|||||||
|
|
||||||
## 支持的API
|
## 支持的API
|
||||||
|
|
||||||
目前只支持http协议POST方法,不支持websocket,事件上报也是http协议
|
目前只支持http协议,不支持websocket,事件上报也是http协议
|
||||||
|
|
||||||
主要功能:
|
主要功能:
|
||||||
- [x] 发送好友消息
|
- [x] 发送好友消息
|
||||||
@@ -46,6 +48,7 @@
|
|||||||
- [x] send_private_msg
|
- [x] send_private_msg
|
||||||
- [x] delete_msg
|
- [x] delete_msg
|
||||||
- [x] get_group_list
|
- [x] get_group_list
|
||||||
|
- [x] get_group_info
|
||||||
- [x] get_group_member_list
|
- [x] get_group_member_list
|
||||||
- [x] get_group_member_info
|
- [x] get_group_member_info
|
||||||
- [x] get_friend_list
|
- [x] get_friend_list
|
||||||
@@ -67,7 +70,7 @@
|
|||||||
<details>
|
<details>
|
||||||
<summary>调用接口报404</summary>
|
<summary>调用接口报404</summary>
|
||||||
<br/>
|
<br/>
|
||||||
目前没有支持全部的onebot规范接口,请检查是否调用了不支持的接口,并且所有接口都只支持POST方法,调用GET方法会报404
|
目前没有支持全部的onebot规范接口,请检查是否调用了不支持的接口
|
||||||
</details>
|
</details>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
@@ -94,11 +97,10 @@
|
|||||||
|
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
- [x] 重构摆脱LLAPI,目前调用LLAPI只能在renderer进程调用,需重构成在main进程调用
|
||||||
- [ ] 转发消息记录
|
- [ ] 转发消息记录
|
||||||
- [ ] 好友点赞api
|
- [ ] 好友点赞api
|
||||||
- [ ] 支持websocket,等个有缘人提PR实现
|
- [ ] 支持websocket,等个有缘人提PR实现
|
||||||
- [x] 重构摆脱LLAPI,目前调用LLAPI只能在renderer进程调用,需重构成在main进程调用
|
|
||||||
|
|
||||||
## onebot11文档
|
## onebot11文档
|
||||||
<https://11.onebot.dev/>
|
<https://11.onebot.dev/>
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "LLOneBot",
|
"name": "LLOneBot",
|
||||||
"slug": "LLOneBot",
|
"slug": "LLOneBot",
|
||||||
"description": "LiteLoaderQQNT的OneBotApi",
|
"description": "LiteLoaderQQNT的OneBotApi",
|
||||||
"version": "2.5.0",
|
"version": "3.0.7",
|
||||||
"thumbnail": "./icon.png",
|
"thumbnail": "./icon.png",
|
||||||
"authors": [{
|
"authors": [{
|
||||||
"name": "linyuchen",
|
"name": "linyuchen",
|
||||||
|
@@ -1,10 +1,31 @@
|
|||||||
import { NTQQApi } from '../ntqqapi/ntcall';
|
import { NTQQApi } from '../ntqqapi/ntcall';
|
||||||
import { Friend, Group, RawMessage, SelfInfo } from "../ntqqapi/types";
|
import { Friend, Group, GroupMember, RawMessage, SelfInfo } from "../ntqqapi/types";
|
||||||
|
import { log } from "./utils";
|
||||||
|
|
||||||
export let groups: Group[] = []
|
export let groups: Group[] = []
|
||||||
export let friends: Friend[] = []
|
export let friends: Friend[] = []
|
||||||
export let msgHistory: Record<string, RawMessage> = {} // msgId: RawMessage
|
export let msgHistory: Record<string, RawMessage> = {} // msgId: RawMessage
|
||||||
|
|
||||||
|
let globalMsgId = Date.now()
|
||||||
|
|
||||||
|
export function addHistoryMsg(msg: RawMessage): boolean{
|
||||||
|
let existMsg = msgHistory[msg.msgId]
|
||||||
|
if (existMsg){
|
||||||
|
Object.assign(existMsg, msg)
|
||||||
|
msg.msgShortId = existMsg.msgShortId;
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
msg.msgShortId = ++globalMsgId
|
||||||
|
msgHistory[msg.msgId] = msg
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getHistoryMsgByShortId(shortId: number | string){
|
||||||
|
// log("getHistoryMsgByShortId", shortId, Object.values(msgHistory).map(m=>m.msgShortId))
|
||||||
|
return Object.values(msgHistory).find(msg => msg.msgShortId.toString() == shortId.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function getFriend(qq: string): Promise<Friend | undefined> {
|
export async function getFriend(qq: string): Promise<Friend | undefined> {
|
||||||
let friend = friends.find(friend => friend.uin === qq)
|
let friend = friends.find(friend => friend.uin === qq)
|
||||||
// if (!friend){
|
// if (!friend){
|
||||||
@@ -23,16 +44,23 @@ export async function getGroup(qq: string): Promise<Group | undefined> {
|
|||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getGroupMember(groupQQ: string, memberQQ: string) {
|
export async function getGroupMember(groupQQ: string, memberQQ: string=null, memberUid: string=null) {
|
||||||
const group = await getGroup(groupQQ)
|
const group = await getGroup(groupQQ)
|
||||||
if (group) {
|
if (group) {
|
||||||
let member = group.members?.find(member => member.uin === memberQQ)
|
let filterFunc: (member: GroupMember) => boolean
|
||||||
|
if (memberQQ){
|
||||||
|
filterFunc = member => member.uin === memberQQ
|
||||||
|
}
|
||||||
|
else if (memberUid){
|
||||||
|
filterFunc = member => member.uid === memberUid
|
||||||
|
}
|
||||||
|
let member = group.members?.find(filterFunc)
|
||||||
if (!member){
|
if (!member){
|
||||||
const _members = await NTQQApi.getGroupMembers(groupQQ)
|
const _members = await NTQQApi.getGroupMembers(groupQQ)
|
||||||
if (_members.length){
|
if (_members.length){
|
||||||
group.members = _members
|
group.members = _members
|
||||||
}
|
}
|
||||||
member = group.members?.find(member => member.uin === memberQQ)
|
member = group.members?.find(filterFunc)
|
||||||
}
|
}
|
||||||
return member
|
return member
|
||||||
}
|
}
|
||||||
|
103
src/main/main.ts
103
src/main/main.ts
@@ -10,10 +10,9 @@ import {
|
|||||||
CHANNEL_LOG,
|
CHANNEL_LOG,
|
||||||
CHANNEL_SET_CONFIG,
|
CHANNEL_SET_CONFIG,
|
||||||
} from "../common/channels";
|
} from "../common/channels";
|
||||||
import { ConfigUtil } from "../common/config";
|
|
||||||
import { postMsg, startExpress } from "../onebot11/server";
|
import { postMsg, startExpress } from "../onebot11/server";
|
||||||
import { CONFIG_DIR, getConfigUtil, log } from "../common/utils";
|
import { CONFIG_DIR, getConfigUtil, log } from "../common/utils";
|
||||||
import { friends, groups, msgHistory, selfInfo } from "../common/data";
|
import { addHistoryMsg, msgHistory, selfInfo } from "../common/data";
|
||||||
import { hookNTQQApiReceive, ReceiveCmd, registerReceiveHook } from "../ntqqapi/hook";
|
import { hookNTQQApiReceive, ReceiveCmd, registerReceiveHook } from "../ntqqapi/hook";
|
||||||
import { OB11Constructor } from "../onebot11/constructor";
|
import { OB11Constructor } from "../onebot11/constructor";
|
||||||
import { NTQQApi } from "../ntqqapi/ntcall";
|
import { NTQQApi } from "../ntqqapi/ntcall";
|
||||||
@@ -32,7 +31,7 @@ function onLoad() {
|
|||||||
|
|
||||||
|
|
||||||
if (!fs.existsSync(CONFIG_DIR)) {
|
if (!fs.existsSync(CONFIG_DIR)) {
|
||||||
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
fs.mkdirSync(CONFIG_DIR, {recursive: true});
|
||||||
}
|
}
|
||||||
ipcMain.handle(CHANNEL_GET_CONFIG, (event: any, arg: any) => {
|
ipcMain.handle(CHANNEL_GET_CONFIG, (event: any, arg: any) => {
|
||||||
return getConfigUtil().getConfig()
|
return getConfigUtil().getConfig()
|
||||||
@@ -47,8 +46,12 @@ function onLoad() {
|
|||||||
|
|
||||||
|
|
||||||
function postRawMsg(msgList: RawMessage[]) {
|
function postRawMsg(msgList: RawMessage[]) {
|
||||||
const { debug, reportSelfMessage } = getConfigUtil().getConfig();
|
const {debug, reportSelfMessage} = getConfigUtil().getConfig();
|
||||||
for (const message of msgList) {
|
for (let message of msgList) {
|
||||||
|
message.msgShortId = msgHistory[message.msgId]?.msgShortId
|
||||||
|
if (!message.msgShortId) {
|
||||||
|
addHistoryMsg(message)
|
||||||
|
}
|
||||||
OB11Constructor.message(message).then((msg) => {
|
OB11Constructor.message(message).then((msg) => {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
msg.raw = message;
|
msg.raw = message;
|
||||||
@@ -57,82 +60,68 @@ function onLoad() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
postMsg(msg);
|
postMsg(msg);
|
||||||
|
// log("post msg", msg)
|
||||||
}).catch(e => log("constructMessage error: ", e.toString()));
|
}).catch(e => log("constructMessage error: ", e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerReceiveHook<{ msgList: Array<RawMessage> }>(ReceiveCmd.NEW_MSG, (payload) => {
|
|
||||||
try {
|
|
||||||
postRawMsg(payload.msgList);
|
|
||||||
} catch (e) {
|
|
||||||
log("report message error: ", e.toString())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmd.SELF_SEND_MSG, (payload) => {
|
function start() {
|
||||||
const { reportSelfMessage } = getConfigUtil().getConfig()
|
log("llonebot start")
|
||||||
if (!reportSelfMessage) {
|
registerReceiveHook<{ msgList: Array<RawMessage> }>(ReceiveCmd.NEW_MSG, (payload) => {
|
||||||
return
|
try {
|
||||||
}
|
// log("received msg length", payload.msgList.length);
|
||||||
log("reportSelfMessage", payload)
|
postRawMsg(payload.msgList);
|
||||||
try {
|
} catch (e) {
|
||||||
postRawMsg([payload.msgRecord]);
|
log("report message error: ", e.toString())
|
||||||
} catch (e) {
|
}
|
||||||
log("report self message error: ", e.toString())
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
async function getSelfInfo() {
|
registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmd.SELF_SEND_MSG, (payload) => {
|
||||||
try{
|
const {reportSelfMessage} = getConfigUtil().getConfig()
|
||||||
|
if (!reportSelfMessage) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// log("reportSelfMessage", payload)
|
||||||
|
try {
|
||||||
|
postRawMsg([payload.msgRecord]);
|
||||||
|
} catch (e) {
|
||||||
|
log("report self message error: ", e.toString())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
NTQQApi.getGroups(true).then()
|
||||||
|
startExpress(getConfigUtil().getConfig().port)
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = async () => {
|
||||||
|
try {
|
||||||
const _ = await NTQQApi.getSelfInfo()
|
const _ = await NTQQApi.getSelfInfo()
|
||||||
Object.assign(selfInfo, _)
|
Object.assign(selfInfo, _)
|
||||||
selfInfo.nick = selfInfo.uin
|
selfInfo.nick = selfInfo.uin
|
||||||
log("get self simple info", _)
|
log("get self simple info", _)
|
||||||
}catch(e){
|
} catch (e) {
|
||||||
log("retry get self info")
|
log("retry get self info")
|
||||||
|
|
||||||
}
|
}
|
||||||
if (selfInfo.uin) {
|
if (selfInfo.uin) {
|
||||||
try {
|
try {
|
||||||
const userInfo = (await NTQQApi.getUserInfo(selfInfo.uid))
|
const userInfo = (await NTQQApi.getUserInfo(selfInfo.uid))
|
||||||
|
log("self info", userInfo);
|
||||||
if (userInfo) {
|
if (userInfo) {
|
||||||
selfInfo.nick = userInfo.nick
|
selfInfo.nick = userInfo.nick
|
||||||
|
} else {
|
||||||
|
return setTimeout(init, 1000)
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
log("get self nickname failed", e.toString())
|
log("get self nickname failed", e.toString())
|
||||||
|
return setTimeout(init, 1000)
|
||||||
}
|
}
|
||||||
// try {
|
start();
|
||||||
// friends.push(...(await NTQQApi.getFriends(true)))
|
|
||||||
// log("get friends", friends)
|
|
||||||
// let _groups: Group[] = []
|
|
||||||
// for(let i=0; i++; i<3){
|
|
||||||
// try{
|
|
||||||
// _groups = await NTQQApi.getGroups(true)
|
|
||||||
// log("get groups sucess", _groups)
|
|
||||||
// break
|
|
||||||
// } catch(e) {
|
|
||||||
// log("get groups failed", e)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for (let g of _groups) {
|
|
||||||
// g.members = (await NTQQApi.getGroupMembers(g.groupCode))
|
|
||||||
// log("group members", g.members)
|
|
||||||
// groups.push(g)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } catch (e) {
|
|
||||||
// log("!!!初始化失败", e.stack.toString())
|
|
||||||
// }
|
|
||||||
startExpress(getConfigUtil().getConfig().port)
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
setTimeout(() => {
|
setTimeout(init, 1000)
|
||||||
getSelfInfo().then()
|
|
||||||
}, 100)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getSelfInfo().then()
|
setTimeout(init, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,24 +1,24 @@
|
|||||||
import {BrowserWindow} from 'electron';
|
import { BrowserWindow } from 'electron';
|
||||||
import {getConfigUtil, log} from "../common/utils";
|
import { getConfigUtil, log } from "../common/utils";
|
||||||
import {NTQQApi, NTQQApiClass, sendMessagePool} from "./ntcall";
|
import { NTQQApi, NTQQApiClass, sendMessagePool } from "./ntcall";
|
||||||
import { Group, User } from "./types";
|
import { Group, User } from "./types";
|
||||||
import { RawMessage } from "./types";
|
import { RawMessage } from "./types";
|
||||||
import {friends, groups, msgHistory} from "../common/data";
|
import { addHistoryMsg, friends, groups, msgHistory } from "../common/data";
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export let hookApiCallbacks: Record<string, (apiReturn: any)=>void>={}
|
export let hookApiCallbacks: Record<string, (apiReturn: any) => void> = {}
|
||||||
|
|
||||||
export enum ReceiveCmd {
|
export enum ReceiveCmd {
|
||||||
UPDATE_MSG = "nodeIKernelMsgListener/onMsgInfoListUpdate",
|
UPDATE_MSG = "nodeIKernelMsgListener/onMsgInfoListUpdate",
|
||||||
NEW_MSG = "nodeIKernelMsgListener/onRecvMsg",
|
NEW_MSG = "nodeIKernelMsgListener/onRecvMsg",
|
||||||
SELF_SEND_MSG = "nodeIKernelMsgListener/onAddSendMsg",
|
SELF_SEND_MSG = "nodeIKernelMsgListener/onAddSendMsg",
|
||||||
USER_INFO = "nodeIKernelProfileListener/onProfileDetailInfoChanged",
|
USER_INFO = "nodeIKernelProfileListener/onProfileSimpleChanged",
|
||||||
GROUPS = "nodeIKernelGroupListener/onGroupListUpdate",
|
GROUPS = "nodeIKernelGroupListener/onGroupListUpdate",
|
||||||
GROUPS_UNIX = "onGroupListUpdate",
|
GROUPS_UNIX = "onGroupListUpdate",
|
||||||
FRIENDS = "onBuddyListChange"
|
FRIENDS = "onBuddyListChange"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NTQQApiReturnData<PayloadType=unknown> extends Array<any> {
|
interface NTQQApiReturnData<PayloadType = unknown> extends Array<any> {
|
||||||
0: {
|
0: {
|
||||||
"type": "request",
|
"type": "request",
|
||||||
"eventName": NTQQApiClass,
|
"eventName": NTQQApiClass,
|
||||||
@@ -51,7 +51,7 @@ export function hookNTQQApiReceive(window: BrowserWindow) {
|
|||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
hook.hookFunc(receiveData.payload);
|
hook.hookFunc(receiveData.payload);
|
||||||
}catch (e) {
|
} catch (e) {
|
||||||
log("hook error", e, receiveData.payload)
|
log("hook error", e, receiveData.payload)
|
||||||
}
|
}
|
||||||
}).then()
|
}).then()
|
||||||
@@ -59,10 +59,10 @@ export function hookNTQQApiReceive(window: BrowserWindow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (args[0]?.callbackId){
|
if (args[0]?.callbackId) {
|
||||||
// log("hookApiCallback", hookApiCallbacks, args)
|
// log("hookApiCallback", hookApiCallbacks, args)
|
||||||
const callbackId = args[0].callbackId;
|
const callbackId = args[0].callbackId;
|
||||||
if (hookApiCallbacks[callbackId]){
|
if (hookApiCallbacks[callbackId]) {
|
||||||
// log("callback found")
|
// log("callback found")
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
hookApiCallbacks[callbackId](args[1]);
|
hookApiCallbacks[callbackId](args[1]);
|
||||||
@@ -85,36 +85,43 @@ export function registerReceiveHook<PayloadType>(method: ReceiveCmd, hookFunc: (
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeReceiveHook(id: string){
|
export function removeReceiveHook(id: string) {
|
||||||
const index = receiveHooks.findIndex(h=>h.id === id)
|
const index = receiveHooks.findIndex(h => h.id === id)
|
||||||
receiveHooks.splice(index, 1);
|
receiveHooks.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateGroups(_groups: Group[]){
|
async function updateGroups(_groups: Group[]) {
|
||||||
for(let group of _groups){
|
for (let group of _groups) {
|
||||||
let existGroup = groups.find(g=>g.groupCode == group.groupCode)
|
let existGroup = groups.find(g => g.groupCode == group.groupCode)
|
||||||
if (!existGroup){
|
if (!existGroup) {
|
||||||
// log("update group")
|
NTQQApi.getGroupMembers(group.groupCode).then(members => {
|
||||||
let _membeers = await NTQQApi.getGroupMembers(group.groupCode)
|
if (members) {
|
||||||
if (_membeers){
|
group.members = members
|
||||||
group.members = _membeers
|
}
|
||||||
}
|
})
|
||||||
|
groups.push(group)
|
||||||
log("update group members", group.members)
|
log("update group members", group.members)
|
||||||
}
|
} else {
|
||||||
else{
|
Object.assign(existGroup, group)
|
||||||
group.members = [...existGroup.members]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
groups.length = 0;
|
|
||||||
groups.push(..._groups)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registerReceiveHook<{groupList: Group[]}>(ReceiveCmd.GROUPS, (payload)=>updateGroups(payload.groupList).then())
|
registerReceiveHook<{ groupList: Group[] }>(ReceiveCmd.GROUPS, (payload) => updateGroups(payload.groupList).then())
|
||||||
registerReceiveHook<{groupList: Group[]}>(ReceiveCmd.GROUPS_UNIX, (payload)=>updateGroups(payload.groupList).then())
|
registerReceiveHook<{ groupList: Group[] }>(ReceiveCmd.GROUPS_UNIX, (payload) => updateGroups(payload.groupList).then())
|
||||||
registerReceiveHook<{data:{categoryId: number, categroyName: string, categroyMbCount: number, buddyList: User[]}[]}>(ReceiveCmd.FRIENDS, payload=>{
|
registerReceiveHook<{
|
||||||
friends.length = 0
|
data: { categoryId: number, categroyName: string, categroyMbCount: number, buddyList: User[] }[]
|
||||||
|
}>(ReceiveCmd.FRIENDS, payload => {
|
||||||
for (const fData of payload.data) {
|
for (const fData of payload.data) {
|
||||||
friends.push(...fData.buddyList)
|
const _friends = fData.buddyList;
|
||||||
|
for (let friend of _friends) {
|
||||||
|
let existFriend = friends.find(f => f.uin == friend.uin)
|
||||||
|
if (!existFriend) {
|
||||||
|
friends.push(friend)
|
||||||
|
} else {
|
||||||
|
Object.assign(existFriend, friend)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -124,31 +131,30 @@ registerReceiveHook<{data:{categoryId: number, categroyName: string, categroyMbC
|
|||||||
|
|
||||||
registerReceiveHook<{ msgList: Array<RawMessage> }>(ReceiveCmd.UPDATE_MSG, (payload) => {
|
registerReceiveHook<{ msgList: Array<RawMessage> }>(ReceiveCmd.UPDATE_MSG, (payload) => {
|
||||||
for (const message of payload.msgList) {
|
for (const message of payload.msgList) {
|
||||||
msgHistory[message.msgId] = message;
|
addHistoryMsg(message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
registerReceiveHook<{ msgList: Array<RawMessage> }>(ReceiveCmd.NEW_MSG, (payload) => {
|
registerReceiveHook<{ msgList: Array<RawMessage> }>(ReceiveCmd.NEW_MSG, (payload) => {
|
||||||
for (const message of payload.msgList) {
|
for (const message of payload.msgList) {
|
||||||
log("收到新消息,push到历史记录", message)
|
// log("收到新消息,push到历史记录", message)
|
||||||
if (!msgHistory[message.msgId]){
|
addHistoryMsg(message)
|
||||||
msgHistory[message.msgId] = message
|
}
|
||||||
}
|
const msgIds = Object.keys(msgHistory);
|
||||||
else{
|
if (msgIds.length > 30000) {
|
||||||
Object.assign(msgHistory[message.msgId], message)
|
delete msgHistory[msgIds.sort()[0]]
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
registerReceiveHook<{msgRecord: RawMessage}>(ReceiveCmd.SELF_SEND_MSG, ({msgRecord})=>{
|
registerReceiveHook<{ msgRecord: RawMessage }>(ReceiveCmd.SELF_SEND_MSG, ({msgRecord}) => {
|
||||||
const message = msgRecord;
|
const message = msgRecord;
|
||||||
const peerUid = message.peerUid;
|
const peerUid = message.peerUid;
|
||||||
// log("收到自己发送成功的消息", Object.keys(sendMessagePool), message);
|
// log("收到自己发送成功的消息", Object.keys(sendMessagePool), message);
|
||||||
const sendCallback = sendMessagePool[peerUid];
|
const sendCallback = sendMessagePool[peerUid];
|
||||||
if (sendCallback){
|
if (sendCallback) {
|
||||||
try{
|
try {
|
||||||
sendCallback(message);
|
sendCallback(message);
|
||||||
}catch(e){
|
} catch (e) {
|
||||||
log("receive self msg error", e.stack)
|
log("receive self msg error", e.stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,11 +2,12 @@ import { ipcMain } from "electron";
|
|||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { ReceiveCmd, hookApiCallbacks, registerReceiveHook, removeReceiveHook } from "./hook";
|
import { ReceiveCmd, hookApiCallbacks, registerReceiveHook, removeReceiveHook } from "./hook";
|
||||||
import { log } from "../common/utils";
|
import { log } from "../common/utils";
|
||||||
import { ChatType, Friend, SelfInfo, User } from "./types";
|
import { ChatType, Friend, PicElement, SelfInfo, User } from "./types";
|
||||||
import { Group } from "./types";
|
import { Group } from "./types";
|
||||||
import { GroupMember } from "./types";
|
import { GroupMember } from "./types";
|
||||||
import { RawMessage } from "./types";
|
import { RawMessage } from "./types";
|
||||||
import { SendMessageElement } from "./types";
|
import { SendMessageElement } from "./types";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
interface IPCReceiveEvent {
|
interface IPCReceiveEvent {
|
||||||
eventName: string
|
eventName: string
|
||||||
@@ -43,6 +44,7 @@ export enum NTQQApiMethod {
|
|||||||
MEDIA_FILE_PATH = "nodeIKernelMsgService/getRichMediaFilePathForGuild",
|
MEDIA_FILE_PATH = "nodeIKernelMsgService/getRichMediaFilePathForGuild",
|
||||||
RECALL_MSG = "nodeIKernelMsgService/recallMsg",
|
RECALL_MSG = "nodeIKernelMsgService/recallMsg",
|
||||||
SEND_MSG = "nodeIKernelMsgService/sendMsg",
|
SEND_MSG = "nodeIKernelMsgService/sendMsg",
|
||||||
|
DOWNLOAD_MEDIA = "nodeIKernelMsgService/downloadRichMedia"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NTQQApiChannel {
|
enum NTQQApiChannel {
|
||||||
@@ -140,10 +142,9 @@ export class NTQQApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async getUserInfo(uid: string) {
|
static async getUserInfo(uid: string) {
|
||||||
const result = await callNTQQApi<{ info: User }>(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.USER_INFO,
|
const result = await callNTQQApi<{ profiles: Map<string, User> }>(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.USER_INFO,
|
||||||
[{ force: true, uids: [uid] }, undefined], ReceiveCmd.USER_INFO)
|
[{ force: true, uids: [uid] }, undefined], ReceiveCmd.USER_INFO)
|
||||||
return result.info
|
return result.profiles.get(uid)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getFriends(forced = false) {
|
static async getFriends(forced = false) {
|
||||||
@@ -244,6 +245,28 @@ export class NTQQApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string){
|
||||||
|
// 用于下载收到的消息中的图片等
|
||||||
|
if (fs.existsSync(sourcePath)){
|
||||||
|
return sourcePath
|
||||||
|
}
|
||||||
|
const apiParams = [
|
||||||
|
{
|
||||||
|
getReq: {
|
||||||
|
msgId: msgId,
|
||||||
|
chatType: chatType,
|
||||||
|
peerUid: peerUid,
|
||||||
|
elementId: elementId,
|
||||||
|
thumbSize: 0,
|
||||||
|
downloadType: 1,
|
||||||
|
filePath: thumbPath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
|
await callNTQQApi(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.DOWNLOAD_MEDIA, apiParams)
|
||||||
|
return sourcePath
|
||||||
|
}
|
||||||
static recallMsg(peer: Peer, msgIds: string[]) {
|
static recallMsg(peer: Peer, msgIds: string[]) {
|
||||||
return callNTQQApi(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.RECALL_MSG, [{ peer, msgIds }, null])
|
return callNTQQApi(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.RECALL_MSG, [{ peer, msgIds }, null])
|
||||||
}
|
}
|
||||||
@@ -293,4 +316,5 @@ export class NTQQApi {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -167,8 +167,22 @@ export interface ArkElement {
|
|||||||
bytesData: string;
|
bytesData: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const IMAGE_HTTP_HOST = "https://gchat.qpic.cn"
|
||||||
|
|
||||||
|
export interface PicElement {
|
||||||
|
originImageUrl: string; // http url, 没有host,host是https://gchat.qpic.cn/
|
||||||
|
sourcePath: string; // 图片本地路径
|
||||||
|
thumbPath: Map<number, string>;
|
||||||
|
picWidth: number;
|
||||||
|
picHeight: number;
|
||||||
|
fileSize: number;
|
||||||
|
fileName: string;
|
||||||
|
fileUuid: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface RawMessage {
|
export interface RawMessage {
|
||||||
msgId: string;
|
msgId: string;
|
||||||
|
msgShortId?: number; // 自己维护的消息id
|
||||||
msgTime: string;
|
msgTime: string;
|
||||||
msgSeq: string;
|
msgSeq: string;
|
||||||
senderUin: string; // 发送者QQ号
|
senderUin: string; // 发送者QQ号
|
||||||
@@ -178,6 +192,7 @@ export interface RawMessage {
|
|||||||
sendMemberName?: string; // 发送者群名片
|
sendMemberName?: string; // 发送者群名片
|
||||||
chatType: ChatType;
|
chatType: ChatType;
|
||||||
elements: {
|
elements: {
|
||||||
|
elementId: string,
|
||||||
replyElement: {
|
replyElement: {
|
||||||
senderUid: string; // 原消息发送者QQ号
|
senderUid: string; // 原消息发送者QQ号
|
||||||
sourceMsgIsIncPic: boolean; // 原消息是否有图片
|
sourceMsgIsIncPic: boolean; // 原消息是否有图片
|
||||||
@@ -186,18 +201,11 @@ export interface RawMessage {
|
|||||||
};
|
};
|
||||||
textElement: {
|
textElement: {
|
||||||
atType: AtType;
|
atType: AtType;
|
||||||
atUid: string;
|
atUid: string; // QQ号
|
||||||
content: string;
|
content: string;
|
||||||
atNtUid: string;
|
atNtUid: string; // uid号
|
||||||
};
|
|
||||||
picElement: {
|
|
||||||
sourcePath: string; // 图片本地路径
|
|
||||||
picWidth: number;
|
|
||||||
picHeight: number;
|
|
||||||
fileSize: number;
|
|
||||||
fileName: string;
|
|
||||||
fileUuid: string;
|
|
||||||
};
|
};
|
||||||
|
picElement: PicElement;
|
||||||
pttElement: PttElement;
|
pttElement: PttElement;
|
||||||
arkElement: ArkElement;
|
arkElement: ArkElement;
|
||||||
}[];
|
}[];
|
||||||
|
@@ -1,21 +1,21 @@
|
|||||||
import { ActionName } from "./types";
|
import { ActionName } from "./types";
|
||||||
import BaseAction from "./BaseAction";
|
import BaseAction from "./BaseAction";
|
||||||
import { NTQQApi } from "../../ntqqapi/ntcall";
|
import { NTQQApi } from "../../ntqqapi/ntcall";
|
||||||
import { msgHistory } from "../../common/data";
|
import { getHistoryMsgByShortId, msgHistory } from "../../common/data";
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: string
|
message_id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
class DeleteMsg extends BaseAction<Payload, void> {
|
class DeleteMsg extends BaseAction<Payload, void> {
|
||||||
actionName = ActionName.DeleteMsg
|
actionName = ActionName.DeleteMsg
|
||||||
|
|
||||||
protected async _handle(payload:Payload){
|
protected async _handle(payload:Payload){
|
||||||
let msg = msgHistory[payload.message_id]
|
let msg = getHistoryMsgByShortId(payload.message_id)
|
||||||
await NTQQApi.recallMsg({
|
await NTQQApi.recallMsg({
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
peerUid: msg.peerUid
|
peerUid: msg.peerUid
|
||||||
}, [payload.message_id])
|
}, [msg.msgId])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { msgHistory } from "../../common/data";
|
import { getHistoryMsgByShortId, msgHistory } from "../../common/data";
|
||||||
import { OB11Message } from '../types';
|
import { OB11Message } from '../types';
|
||||||
import { OB11Constructor } from "../constructor";
|
import { OB11Constructor } from "../constructor";
|
||||||
import { log } from "../../common/utils";
|
import { log } from "../../common/utils";
|
||||||
@@ -7,7 +7,7 @@ import { ActionName } from "./types";
|
|||||||
|
|
||||||
|
|
||||||
export interface PayloadType {
|
export interface PayloadType {
|
||||||
message_id: string
|
message_id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ReturnDataType = OB11Message
|
export type ReturnDataType = OB11Message
|
||||||
@@ -17,7 +17,7 @@ class GetMsg extends BaseAction<PayloadType, OB11Message> {
|
|||||||
|
|
||||||
protected async _handle(payload: PayloadType){
|
protected async _handle(payload: PayloadType){
|
||||||
// log("history msg ids", Object.keys(msgHistory));
|
// log("history msg ids", Object.keys(msgHistory));
|
||||||
const msg = msgHistory[payload.message_id.toString()]
|
const msg = getHistoryMsgByShortId(payload.message_id)
|
||||||
if (msg) {
|
if (msg) {
|
||||||
const msgData = await OB11Constructor.message(msg);
|
const msgData = await OB11Constructor.message(msg);
|
||||||
return msgData
|
return msgData
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
import { AtType, ChatType, Group } from "../../ntqqapi/types";
|
import { AtType, ChatType, Group } from "../../ntqqapi/types";
|
||||||
import { friends, getGroup, getStrangerByUin, msgHistory } from "../../common/data";
|
import {
|
||||||
|
addHistoryMsg,
|
||||||
|
friends,
|
||||||
|
getGroup,
|
||||||
|
getHistoryMsgByShortId,
|
||||||
|
getStrangerByUin,
|
||||||
|
} from "../../common/data";
|
||||||
import { OB11MessageData, OB11MessageDataType, OB11PostSendMsg } from '../types';
|
import { OB11MessageData, OB11MessageDataType, OB11PostSendMsg } from '../types';
|
||||||
import { NTQQApi } from "../../ntqqapi/ntcall";
|
import { NTQQApi } from "../../ntqqapi/ntcall";
|
||||||
import { Peer } from "../../ntqqapi/ntcall";
|
import { Peer } from "../../ntqqapi/ntcall";
|
||||||
@@ -10,9 +16,10 @@ import { v4 as uuid4 } from 'uuid';
|
|||||||
import { log } from "../../common/utils";
|
import { log } from "../../common/utils";
|
||||||
import BaseAction from "./BaseAction";
|
import BaseAction from "./BaseAction";
|
||||||
import { ActionName } from "./types";
|
import { ActionName } from "./types";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
export interface ReturnDataType {
|
export interface ReturnDataType {
|
||||||
message_id: string
|
message_id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
||||||
@@ -23,6 +30,7 @@ class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
chatType: ChatType.friend,
|
chatType: ChatType.friend,
|
||||||
peerUid: ""
|
peerUid: ""
|
||||||
}
|
}
|
||||||
|
let deleteAfterSentFiles: string[] = []
|
||||||
let group: Group | undefined = undefined;
|
let group: Group | undefined = undefined;
|
||||||
if (payload?.group_id) {
|
if (payload?.group_id) {
|
||||||
group = await getGroup(payload.group_id.toString())
|
group = await getGroup(payload.group_id.toString())
|
||||||
@@ -88,27 +96,27 @@ class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
let replyMsgId = sendMsg.data.id;
|
let replyMsgId = sendMsg.data.id;
|
||||||
if (replyMsgId) {
|
if (replyMsgId) {
|
||||||
replyMsgId = replyMsgId.toString()
|
replyMsgId = replyMsgId.toString()
|
||||||
const replyMsg = msgHistory[replyMsgId]
|
const replyMsg = getHistoryMsgByShortId(replyMsgId)
|
||||||
if (replyMsg) {
|
if (replyMsg) {
|
||||||
sendElements.push(SendMsgElementConstructor.reply(replyMsg.msgSeq, replyMsgId, replyMsg.senderUin, replyMsg.senderUin))
|
sendElements.push(SendMsgElementConstructor.reply(replyMsg.msgSeq, replyMsg.msgId, replyMsg.senderUin, replyMsg.senderUin))
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case OB11MessageDataType.image: {
|
|
||||||
const file = sendMsg.data?.file
|
|
||||||
if (file) {
|
|
||||||
const picPath = await (await uri2local(uuid4(), file)).path
|
|
||||||
if (picPath) {
|
|
||||||
sendElements.push(await SendMsgElementConstructor.pic(picPath))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case OB11MessageDataType.image:
|
||||||
case OB11MessageDataType.voice: {
|
case OB11MessageDataType.voice: {
|
||||||
const file = sendMsg.data?.file
|
const file = sendMsg.data?.file
|
||||||
if (file) {
|
if (file) {
|
||||||
const voicePath = await (await uri2local(uuid4(), file)).path
|
const {path, isLocal} = (await uri2local(uuid4(), file))
|
||||||
if (voicePath) {
|
if (path) {
|
||||||
sendElements.push(await SendMsgElementConstructor.ptt(voicePath))
|
if (!isLocal){ // 只删除http和base64转过来的文件
|
||||||
|
deleteAfterSentFiles.push(path)
|
||||||
|
}
|
||||||
|
if (sendMsg.type === OB11MessageDataType.image){
|
||||||
|
sendElements.push(await SendMsgElementConstructor.pic(path))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendElements.push(await SendMsgElementConstructor.ptt(path))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +125,9 @@ class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
// log("send msg:", peer, sendElements)
|
// log("send msg:", peer, sendElements)
|
||||||
try {
|
try {
|
||||||
const returnMsg = await NTQQApi.sendMsg(peer, sendElements)
|
const returnMsg = await NTQQApi.sendMsg(peer, sendElements)
|
||||||
return { message_id: returnMsg.msgId }
|
addHistoryMsg(returnMsg)
|
||||||
|
deleteAfterSentFiles.map(f=>fs.unlink(f, ()=>{}))
|
||||||
|
return { message_id: returnMsg.msgShortId }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw(e.toString())
|
throw(e.toString())
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,27 @@
|
|||||||
import {OB11MessageDataType, OB11GroupMemberRole, OB11Message, OB11MessageData, OB11Group, OB11GroupMember, OB11User} from "./types";
|
import {
|
||||||
import { AtType, ChatType, Group, GroupMember, RawMessage, SelfInfo, User } from '../ntqqapi/types';
|
OB11MessageDataType,
|
||||||
import { getFriend, getGroupMember, getHistoryMsgBySeq, selfInfo } from '../common/data';
|
OB11GroupMemberRole,
|
||||||
import {file2base64, getConfigUtil, log} from "../common/utils";
|
OB11Message,
|
||||||
|
OB11Group,
|
||||||
|
OB11GroupMember,
|
||||||
|
OB11User
|
||||||
|
} from "./types";
|
||||||
|
import { AtType, ChatType, Group, GroupMember, IMAGE_HTTP_HOST, RawMessage, SelfInfo, User } from '../ntqqapi/types';
|
||||||
|
import { getFriend, getGroupMember, getHistoryMsgBySeq, msgHistory, selfInfo } from '../common/data';
|
||||||
|
import { file2base64, getConfigUtil, log } from "../common/utils";
|
||||||
|
import { NTQQApi } from "../ntqqapi/ntcall";
|
||||||
|
|
||||||
|
|
||||||
export class OB11Constructor {
|
export class OB11Constructor {
|
||||||
static async message(msg: RawMessage): Promise<OB11Message> {
|
static async message(msg: RawMessage): Promise<OB11Message> {
|
||||||
|
|
||||||
const {enableBase64} = getConfigUtil().getConfig()
|
const {enableBase64} = getConfigUtil().getConfig()
|
||||||
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: selfInfo.uin,
|
self_id: selfInfo.uin,
|
||||||
user_id: msg.senderUin,
|
user_id: msg.senderUin,
|
||||||
time: parseInt(msg.msgTime) || 0,
|
time: parseInt(msg.msgTime) || 0,
|
||||||
message_id: msg.msgId,
|
message_id: msg.msgShortId,
|
||||||
real_id: msg.msgId,
|
real_id: msg.msgId,
|
||||||
message_type: msg.chatType == ChatType.group ? "group" : "private",
|
message_type: msg.chatType == ChatType.group ? "group" : "private",
|
||||||
sender: {
|
sender: {
|
||||||
@@ -27,6 +36,7 @@ export class OB11Constructor {
|
|||||||
post_type: "message",
|
post_type: "message",
|
||||||
}
|
}
|
||||||
if (msg.chatType == ChatType.group) {
|
if (msg.chatType == ChatType.group) {
|
||||||
|
resMsg.sub_type = "normal"
|
||||||
resMsg.group_id = msg.peerUin
|
resMsg.group_id = msg.peerUin
|
||||||
const member = await getGroupMember(msg.peerUin, msg.senderUin);
|
const member = await getGroupMember(msg.peerUin, msg.senderUin);
|
||||||
if (member) {
|
if (member) {
|
||||||
@@ -53,10 +63,18 @@ export class OB11Constructor {
|
|||||||
message_data["data"]["mention"] = "all"
|
message_data["data"]["mention"] = "all"
|
||||||
message_data["data"]["qq"] = "all"
|
message_data["data"]["qq"] = "all"
|
||||||
} else {
|
} else {
|
||||||
let uid = element.textElement.atUid
|
let atUid = element.textElement.atNtUid
|
||||||
let atMember = await getGroupMember(msg.peerUin, uid)
|
let atQQ = element.textElement.atUid
|
||||||
message_data["data"]["mention"] = atMember?.uin
|
if (!atQQ || atQQ === "0") {
|
||||||
message_data["data"]["qq"] = atMember?.uin
|
const atMember = await getGroupMember(msg.peerUin, null, atUid)
|
||||||
|
if (atMember) {
|
||||||
|
atQQ = atMember.uin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (atQQ) {
|
||||||
|
message_data["data"]["mention"] = atQQ
|
||||||
|
message_data["data"]["qq"] = atQQ
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (element.textElement) {
|
} else if (element.textElement) {
|
||||||
message_data["type"] = "text"
|
message_data["type"] = "text"
|
||||||
@@ -66,13 +84,18 @@ export class OB11Constructor {
|
|||||||
message_data["data"]["file_id"] = element.picElement.fileUuid
|
message_data["data"]["file_id"] = element.picElement.fileUuid
|
||||||
message_data["data"]["path"] = element.picElement.sourcePath
|
message_data["data"]["path"] = element.picElement.sourcePath
|
||||||
message_data["data"]["file"] = element.picElement.sourcePath
|
message_data["data"]["file"] = element.picElement.sourcePath
|
||||||
|
try {
|
||||||
|
await NTQQApi.downloadMedia(msg.msgId, msg.chatType, msg.peerUid,
|
||||||
|
element.elementId, element.picElement.thumbPath.get(0), element.picElement.sourcePath)
|
||||||
|
} catch (e) {
|
||||||
|
message_data["data"]["http_file"] = IMAGE_HTTP_HOST + element.picElement.originImageUrl
|
||||||
|
}
|
||||||
} else if (element.replyElement) {
|
} else if (element.replyElement) {
|
||||||
message_data["type"] = "reply"
|
message_data["type"] = "reply"
|
||||||
const replyMsg = getHistoryMsgBySeq(element.replyElement.replayMsgSeq)
|
const replyMsg = getHistoryMsgBySeq(element.replyElement.replayMsgSeq)
|
||||||
if (replyMsg) {
|
if (replyMsg) {
|
||||||
message_data["data"]["id"] = replyMsg.msgId
|
message_data["data"]["id"] = replyMsg.msgShortId
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if (element.pttElement) {
|
} else if (element.pttElement) {
|
||||||
@@ -89,11 +112,12 @@ export class OB11Constructor {
|
|||||||
message_data["type"] = OB11MessageDataType.json;
|
message_data["type"] = OB11MessageDataType.json;
|
||||||
message_data["data"]["data"] = element.arkElement.bytesData;
|
message_data["data"]["data"] = element.arkElement.bytesData;
|
||||||
}
|
}
|
||||||
if (message_data.data.file) {
|
if (message_data.data.http_file) {
|
||||||
|
message_data.data.file = message_data.data.http_file
|
||||||
|
} else if (message_data.data.file) {
|
||||||
let filePath: string = message_data.data.file;
|
let filePath: string = message_data.data.file;
|
||||||
message_data.data.file = "file://" + filePath
|
message_data.data.file = "file://" + filePath
|
||||||
if (enableBase64) {
|
if (enableBase64) {
|
||||||
// filePath = filePath.replace("\\Ori\\", "\\Thumb\\")
|
|
||||||
let {err, data} = await file2base64(filePath);
|
let {err, data} = await file2base64(filePath);
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log("文件转base64失败", err)
|
console.log("文件转base64失败", err)
|
||||||
@@ -106,36 +130,26 @@ export class OB11Constructor {
|
|||||||
resMsg.message.push(message_data);
|
resMsg.message.push(message_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (msgHistory.length > 10000) {
|
|
||||||
// msgHistory.splice(0, 100)
|
|
||||||
// }
|
|
||||||
// msgHistory.push(message)
|
|
||||||
// if (!reportSelfMessage && onebot_message_data["user_id"] == self_qq) {
|
|
||||||
// console.log("开启了不上传自己发送的消息,进行拦截 ", onebot_message_data);
|
|
||||||
// } else {
|
|
||||||
// console.log("发送上传消息给ipc main", onebot_message_data);
|
|
||||||
// window.llonebot.postData(onebot_message_data);
|
|
||||||
// }
|
|
||||||
return resMsg;
|
return resMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static friend(friend: User): OB11User{
|
static friend(friend: User): OB11User {
|
||||||
return {
|
return {
|
||||||
user_id: friend.uin,
|
user_id: friend.uin,
|
||||||
nickname: friend.nick,
|
nickname: friend.nick,
|
||||||
remark: friend.remark
|
remark: friend.remark
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static selfInfo(selfInfo: SelfInfo): OB11User{
|
static selfInfo(selfInfo: SelfInfo): OB11User {
|
||||||
return {
|
return {
|
||||||
user_id: selfInfo.uin,
|
user_id: selfInfo.uin,
|
||||||
nickname: selfInfo.nick
|
nickname: selfInfo.nick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static friends(friends: User[]): OB11User[]{
|
static friends(friends: User[]): OB11User[] {
|
||||||
return friends.map(OB11Constructor.friend)
|
return friends.map(OB11Constructor.friend)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +161,7 @@ export class OB11Constructor {
|
|||||||
}[role]
|
}[role]
|
||||||
}
|
}
|
||||||
|
|
||||||
static groupMember(group_id: string, member: GroupMember): OB11GroupMember{
|
static groupMember(group_id: string, member: GroupMember): OB11GroupMember {
|
||||||
return {
|
return {
|
||||||
group_id,
|
group_id,
|
||||||
user_id: member.uin,
|
user_id: member.uin,
|
||||||
@@ -156,19 +170,19 @@ export class OB11Constructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static groupMembers(group: Group): OB11GroupMember[]{
|
static groupMembers(group: Group): OB11GroupMember[] {
|
||||||
log("construct ob11 group members", group)
|
log("construct ob11 group members", group)
|
||||||
return group.members.map(m=>OB11Constructor.groupMember(group.groupCode, m))
|
return group.members.map(m => OB11Constructor.groupMember(group.groupCode, m))
|
||||||
}
|
}
|
||||||
|
|
||||||
static group(group: Group): OB11Group{
|
static group(group: Group): OB11Group {
|
||||||
return {
|
return {
|
||||||
group_id: group.groupCode,
|
group_id: group.groupCode,
|
||||||
group_name: group.groupName
|
group_name: group.groupName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static groups(groups: Group[]): OB11Group[]{
|
static groups(groups: Group[]): OB11Group[] {
|
||||||
return groups.map(OB11Constructor.group)
|
return groups.map(OB11Constructor.group)
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -58,12 +58,12 @@ export enum OB11MessageType {
|
|||||||
export interface OB11Message {
|
export interface OB11Message {
|
||||||
self_id?: string,
|
self_id?: string,
|
||||||
time: number,
|
time: number,
|
||||||
message_id: string,
|
message_id: number,
|
||||||
real_id: string,
|
real_id: string,
|
||||||
user_id: string,
|
user_id: string,
|
||||||
group_id?: string,
|
group_id?: string,
|
||||||
message_type: "private" | "group",
|
message_type: "private" | "group",
|
||||||
sub_type?: "friend" | "group" | "other",
|
sub_type?: "friend" | "group" | "normal",
|
||||||
sender: OB11Sender,
|
sender: OB11Sender,
|
||||||
message: OB11MessageData[],
|
message: OB11MessageData[],
|
||||||
raw_message: string,
|
raw_message: string,
|
||||||
|
@@ -6,6 +6,12 @@ const fs = require("fs").promises;
|
|||||||
export async function uri2local(fileName: string, uri: string){
|
export async function uri2local(fileName: string, uri: string){
|
||||||
let filePath = path.join(CONFIG_DIR, fileName)
|
let filePath = path.join(CONFIG_DIR, fileName)
|
||||||
let url = new URL(uri);
|
let url = new URL(uri);
|
||||||
|
let res = {
|
||||||
|
success: false,
|
||||||
|
errMsg: "",
|
||||||
|
path: "",
|
||||||
|
isLocal: false
|
||||||
|
}
|
||||||
if (url.protocol == "base64:") {
|
if (url.protocol == "base64:") {
|
||||||
// base64转成文件
|
// base64转成文件
|
||||||
let base64Data = uri.split("base64://")[1]
|
let base64Data = uri.split("base64://")[1]
|
||||||
@@ -13,51 +19,44 @@ export async function uri2local(fileName: string, uri: string){
|
|||||||
const buffer = Buffer.from(base64Data, 'base64');
|
const buffer = Buffer.from(base64Data, 'base64');
|
||||||
await fs.writeFile(filePath, buffer);
|
await fs.writeFile(filePath, buffer);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
return {
|
res.errMsg = `base64文件下载失败,` + e.toString()
|
||||||
success: false,
|
return res
|
||||||
errMsg: `base64文件下载失败,` + e.toString(),
|
|
||||||
path: ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (url.protocol == "http:" || url.protocol == "https:") {
|
} else if (url.protocol == "http:" || url.protocol == "https:") {
|
||||||
// 下载文件
|
// 下载文件
|
||||||
let res = await fetch(url)
|
let fetchRes = await fetch(url)
|
||||||
if (!res.ok) {
|
if (!fetchRes.ok) {
|
||||||
return {
|
res.errMsg = `${url}下载失败,` + fetchRes.statusText
|
||||||
success: false,
|
return res
|
||||||
errMsg: `${url}下载失败,` + res.statusText,
|
|
||||||
path: ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let blob = await res.blob();
|
let blob = await fetchRes.blob();
|
||||||
let buffer = await blob.arrayBuffer();
|
let buffer = await blob.arrayBuffer();
|
||||||
try {
|
try {
|
||||||
await fs.writeFile(filePath, Buffer.from(buffer));
|
await fs.writeFile(filePath, Buffer.from(buffer));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
return {
|
res.errMsg = `${url}下载失败,` + e.toString()
|
||||||
success: false,
|
return res
|
||||||
errMsg: `${url}下载失败,` + e.toString(),
|
|
||||||
path: ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (url.protocol === "file:"){
|
} else if (url.protocol === "file:"){
|
||||||
await fs.copyFile(url.pathname, filePath);
|
// await fs.copyFile(url.pathname, filePath);
|
||||||
// filePath = (await NTQQApi.uploadFile(url.pathname)).path;
|
let pathname = decodeURIComponent(url.pathname)
|
||||||
|
if (process.platform === "win32"){
|
||||||
|
filePath = pathname.slice(1)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
filePath = pathname
|
||||||
|
}
|
||||||
|
res.isLocal = true
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return {
|
res.errMsg = `不支持的file协议,` + url.protocol
|
||||||
success: false,
|
return res
|
||||||
errMsg: `不支持的file协议,` + url.protocol,
|
|
||||||
path: ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (isGIF(filePath)) {
|
if (isGIF(filePath) && !res.isLocal) {
|
||||||
await fs.rename(filePath, filePath + ".gif");
|
await fs.rename(filePath, filePath + ".gif");
|
||||||
filePath += ".gif";
|
filePath += ".gif";
|
||||||
}
|
}
|
||||||
return {
|
res.success = true
|
||||||
success: true,
|
res.path = filePath
|
||||||
errMsg: "",
|
return res
|
||||||
path: filePath
|
|
||||||
};
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user