mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
refactor
This commit is contained in:
parent
15b85f735d
commit
96aa5e264a
package.jsonadapter.tsentities.ts
src
common/utils
main
ntqqapi
onebot11
action
file
go-cqhttp
DelEssenceMsg.tsGetForwardMsg.tsGetGroupMsgHistory.tsMarkMsgAsRead.tsSendForwardMsg.tsSetEssenceMsg.ts
llonebot
msg
user
helper
@ -17,7 +17,7 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@minatojs/driver-sqlite": "4.5.0",
|
"@minatojs/driver-sqlite": "^4.6.0",
|
||||||
"compressing": "^1.10.1",
|
"compressing": "^1.10.1",
|
||||||
"cordis": "^3.18.1",
|
"cordis": "^3.18.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
@ -26,7 +26,7 @@
|
|||||||
"fast-xml-parser": "^4.5.0",
|
"fast-xml-parser": "^4.5.0",
|
||||||
"file-type": "^19.5.0",
|
"file-type": "^19.5.0",
|
||||||
"fluent-ffmpeg": "^2.1.3",
|
"fluent-ffmpeg": "^2.1.3",
|
||||||
"minato": "3.5.1",
|
"minato": "^3.6.0",
|
||||||
"protobufjs": "^7.4.0",
|
"protobufjs": "^7.4.0",
|
||||||
"silk-wasm": "^3.6.1",
|
"silk-wasm": "^3.6.1",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
|
@ -1,162 +0,0 @@
|
|||||||
import fsPromise from 'node:fs/promises'
|
|
||||||
import fs from 'node:fs'
|
|
||||||
import path from 'node:path'
|
|
||||||
import Database, { Tables } from 'minato'
|
|
||||||
import SQLite from '@minatojs/driver-sqlite'
|
|
||||||
import { Peer } from '@/ntqqapi/types'
|
|
||||||
import { createHash } from 'node:crypto'
|
|
||||||
import { LimitedHashTable } from './table'
|
|
||||||
import { DATA_DIR } from '../globalVars'
|
|
||||||
import { FileCacheV2 } from '../types'
|
|
||||||
|
|
||||||
interface SQLiteTables extends Tables {
|
|
||||||
message: {
|
|
||||||
shortId: number
|
|
||||||
msgId: string
|
|
||||||
chatType: number
|
|
||||||
peerUid: string
|
|
||||||
}
|
|
||||||
file_v2: FileCacheV2
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MsgIdAndPeerByShortId {
|
|
||||||
MsgId: string
|
|
||||||
Peer: Peer
|
|
||||||
}
|
|
||||||
|
|
||||||
// forked from https://github.com/NapNeko/NapCatQQ/blob/6f6b258f22d7563f15d84e7172c4d4cbb547f47e/src/common/utils/MessageUnique.ts#L84
|
|
||||||
class MessageUniqueWrapper {
|
|
||||||
private msgDataMap: LimitedHashTable<string, number>
|
|
||||||
private msgIdMap: LimitedHashTable<string, number>
|
|
||||||
private db: Database<SQLiteTables> | undefined
|
|
||||||
|
|
||||||
constructor(maxMap: number = 1000) {
|
|
||||||
this.msgIdMap = new LimitedHashTable<string, number>(maxMap)
|
|
||||||
this.msgDataMap = new LimitedHashTable<string, number>(maxMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
async init(uin: string) {
|
|
||||||
const dbDir = path.join(DATA_DIR, 'database')
|
|
||||||
if (!fs.existsSync(dbDir)) {
|
|
||||||
await fsPromise.mkdir(dbDir)
|
|
||||||
}
|
|
||||||
const database = new Database<SQLiteTables>()
|
|
||||||
await database.connect(SQLite, {
|
|
||||||
path: path.join(dbDir, `${uin}.db`)
|
|
||||||
})
|
|
||||||
database.extend('message', {
|
|
||||||
shortId: 'integer(10)',
|
|
||||||
chatType: 'unsigned',
|
|
||||||
msgId: 'string(24)',
|
|
||||||
peerUid: 'string(24)'
|
|
||||||
}, {
|
|
||||||
primary: 'shortId'
|
|
||||||
})
|
|
||||||
database.extend('file_v2', {
|
|
||||||
fileName: 'string',
|
|
||||||
fileSize: 'string',
|
|
||||||
fileUuid: 'string(128)',
|
|
||||||
msgId: 'string(24)',
|
|
||||||
msgTime: 'unsigned(10)',
|
|
||||||
peerUid: 'string(24)',
|
|
||||||
chatType: 'unsigned',
|
|
||||||
elementId: 'string(24)',
|
|
||||||
elementType: 'unsigned',
|
|
||||||
}, {
|
|
||||||
primary: 'fileUuid',
|
|
||||||
indexes: ['fileName']
|
|
||||||
})
|
|
||||||
this.db = database
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRecentMsgIds(Peer: Peer, size: number): Promise<string[]> {
|
|
||||||
const heads = this.msgIdMap.getHeads(size)
|
|
||||||
if (!heads) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
const data: (MsgIdAndPeerByShortId | undefined)[] = []
|
|
||||||
for (const t of heads) {
|
|
||||||
data.push(await MessageUnique.getMsgIdAndPeerByShortId(t.value))
|
|
||||||
}
|
|
||||||
const ret = data.filter((t) => t?.Peer.chatType === Peer.chatType && t?.Peer.peerUid === Peer.peerUid)
|
|
||||||
return ret.map((t) => t?.MsgId).filter((t) => t !== undefined)
|
|
||||||
}
|
|
||||||
|
|
||||||
createMsg(peer: Peer, msgId: string): number {
|
|
||||||
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`
|
|
||||||
const hash = createHash('md5').update(key).digest()
|
|
||||||
//设置第一个bit为0 保证shortId为正数
|
|
||||||
hash[0] &= 0x7f
|
|
||||||
const shortId = hash.readInt32BE(0)
|
|
||||||
//减少性能损耗
|
|
||||||
// const isExist = this.msgIdMap.getKey(shortId)
|
|
||||||
// if (isExist && isExist === msgId) {
|
|
||||||
// return shortId
|
|
||||||
// }
|
|
||||||
this.msgIdMap.set(msgId, shortId)
|
|
||||||
this.msgDataMap.set(key, shortId)
|
|
||||||
this.db?.upsert('message', [{
|
|
||||||
msgId,
|
|
||||||
shortId,
|
|
||||||
chatType: peer.chatType,
|
|
||||||
peerUid: peer.peerUid
|
|
||||||
}], 'shortId').then()
|
|
||||||
return shortId
|
|
||||||
}
|
|
||||||
|
|
||||||
async getMsgIdAndPeerByShortId(shortId: number): Promise<MsgIdAndPeerByShortId | undefined> {
|
|
||||||
const data = this.msgDataMap.getKey(shortId)
|
|
||||||
if (data) {
|
|
||||||
const [msgId, chatTypeStr, peerUid] = data.split('|')
|
|
||||||
const peer: Peer = {
|
|
||||||
chatType: parseInt(chatTypeStr),
|
|
||||||
peerUid,
|
|
||||||
guildId: '',
|
|
||||||
}
|
|
||||||
return { MsgId: msgId, Peer: peer }
|
|
||||||
}
|
|
||||||
const items = await this.db?.get('message', { shortId })
|
|
||||||
if (items?.length) {
|
|
||||||
const { msgId, chatType, peerUid } = items[0]
|
|
||||||
return {
|
|
||||||
MsgId: msgId,
|
|
||||||
Peer: {
|
|
||||||
chatType,
|
|
||||||
peerUid,
|
|
||||||
guildId: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getShortIdByMsgId(msgId: string): number | undefined {
|
|
||||||
return this.msgIdMap.getValue(msgId)
|
|
||||||
}
|
|
||||||
|
|
||||||
async getPeerByMsgId(msgId: string) {
|
|
||||||
const shortId = this.msgIdMap.getValue(msgId)
|
|
||||||
if (!shortId) return undefined
|
|
||||||
return await this.getMsgIdAndPeerByShortId(shortId)
|
|
||||||
}
|
|
||||||
|
|
||||||
resize(maxSize: number): void {
|
|
||||||
this.msgIdMap.resize(maxSize)
|
|
||||||
this.msgDataMap.resize(maxSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
addFileCache(data: FileCacheV2) {
|
|
||||||
return this.db?.upsert('file_v2', [data], 'fileUuid')
|
|
||||||
}
|
|
||||||
|
|
||||||
getFileCacheByName(fileName: string) {
|
|
||||||
return this.db?.get('file_v2', { fileName }, {
|
|
||||||
sort: { msgTime: 'desc' }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getFileCacheById(fileUuid: string) {
|
|
||||||
return this.db?.get('file_v2', { fileUuid })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MessageUnique: MessageUniqueWrapper = new MessageUniqueWrapper()
|
|
@ -1,5 +1,4 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import fs from 'node:fs'
|
|
||||||
import Log from './log'
|
import Log from './log'
|
||||||
import Core from '../ntqqapi/core'
|
import Core from '../ntqqapi/core'
|
||||||
import OneBot11Adapter from '../onebot11/adapter'
|
import OneBot11Adapter from '../onebot11/adapter'
|
||||||
@ -34,6 +33,11 @@ import {
|
|||||||
NTQQWebApi,
|
NTQQWebApi,
|
||||||
NTQQWindowApi
|
NTQQWindowApi
|
||||||
} from '../ntqqapi/api'
|
} from '../ntqqapi/api'
|
||||||
|
import { mkdir } from 'node:fs/promises'
|
||||||
|
import { existsSync, mkdirSync } from 'node:fs'
|
||||||
|
import Database from 'minato'
|
||||||
|
import SQLiteDriver from '@minatojs/driver-sqlite'
|
||||||
|
import Store from './store'
|
||||||
|
|
||||||
declare module 'cordis' {
|
declare module 'cordis' {
|
||||||
interface Events {
|
interface Events {
|
||||||
@ -45,12 +49,12 @@ let mainWindow: BrowserWindow | null = null
|
|||||||
|
|
||||||
// 加载插件时触发
|
// 加载插件时触发
|
||||||
function onLoad() {
|
function onLoad() {
|
||||||
if (!fs.existsSync(DATA_DIR)) {
|
if (!existsSync(DATA_DIR)) {
|
||||||
fs.mkdirSync(DATA_DIR, { recursive: true })
|
mkdirSync(DATA_DIR, { recursive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(LOG_DIR)) {
|
if (!existsSync(LOG_DIR)) {
|
||||||
fs.mkdirSync(LOG_DIR)
|
mkdirSync(LOG_DIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcMain.handle(CHANNEL_CHECK_VERSION, async () => {
|
ipcMain.handle(CHANNEL_CHECK_VERSION, async () => {
|
||||||
@ -151,8 +155,12 @@ function onLoad() {
|
|||||||
log('LLOneBot 开关设置为关闭,不启动LLOneBot')
|
log('LLOneBot 开关设置为关闭,不启动LLOneBot')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!fs.existsSync(TEMP_DIR)) {
|
if (!existsSync(TEMP_DIR)) {
|
||||||
fs.mkdirSync(TEMP_DIR)
|
await mkdir(TEMP_DIR)
|
||||||
|
}
|
||||||
|
const dbDir = path.join(DATA_DIR, 'database')
|
||||||
|
if (!existsSync(dbDir)) {
|
||||||
|
await mkdir(dbDir)
|
||||||
}
|
}
|
||||||
const ctx = new Context()
|
const ctx = new Context()
|
||||||
ctx.plugin(Log, {
|
ctx.plugin(Log, {
|
||||||
@ -179,6 +187,11 @@ function onLoad() {
|
|||||||
enableLocalFile2Url: config.enableLocalFile2Url!,
|
enableLocalFile2Url: config.enableLocalFile2Url!,
|
||||||
ffmpeg: config.ffmpeg,
|
ffmpeg: config.ffmpeg,
|
||||||
})
|
})
|
||||||
|
ctx.plugin(Database)
|
||||||
|
ctx.plugin(SQLiteDriver, {
|
||||||
|
path: path.join(dbDir, `${selfInfo.uin}.db`)
|
||||||
|
})
|
||||||
|
ctx.plugin(Store)
|
||||||
ctx.start()
|
ctx.start()
|
||||||
ipcMain.on(CHANNEL_SET_CONFIG_CONFIRMED, (event, config: LLOBConfig) => {
|
ipcMain.on(CHANNEL_SET_CONFIG_CONFIRMED, (event, config: LLOBConfig) => {
|
||||||
ctx.parallel('llonebot/config-updated', config)
|
ctx.parallel('llonebot/config-updated', config)
|
||||||
|
126
src/main/store.ts
Normal file
126
src/main/store.ts
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import { Peer } from '@/ntqqapi/types'
|
||||||
|
import { createHash } from 'node:crypto'
|
||||||
|
import { LimitedHashTable } from '@/common/utils/table'
|
||||||
|
import { FileCacheV2 } from '@/common/types'
|
||||||
|
import { Context, Service } from 'cordis'
|
||||||
|
|
||||||
|
declare module 'cordis' {
|
||||||
|
interface Context {
|
||||||
|
store: Store
|
||||||
|
}
|
||||||
|
interface Tables {
|
||||||
|
message: {
|
||||||
|
shortId: number
|
||||||
|
msgId: string
|
||||||
|
chatType: number
|
||||||
|
peerUid: string
|
||||||
|
}
|
||||||
|
file_v2: FileCacheV2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MsgInfo {
|
||||||
|
msgId: string
|
||||||
|
peer: Peer
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Store extends Service {
|
||||||
|
static inject = ['database', 'model']
|
||||||
|
private cache: LimitedHashTable<string, number>
|
||||||
|
|
||||||
|
constructor(protected ctx: Context) {
|
||||||
|
super(ctx, 'store', true)
|
||||||
|
this.cache = new LimitedHashTable<string, number>(1000)
|
||||||
|
this.initDatabase()
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initDatabase() {
|
||||||
|
this.ctx.model.extend('message', {
|
||||||
|
shortId: 'integer(10)',
|
||||||
|
chatType: 'unsigned',
|
||||||
|
msgId: 'string(24)',
|
||||||
|
peerUid: 'string(24)'
|
||||||
|
}, {
|
||||||
|
primary: 'shortId'
|
||||||
|
})
|
||||||
|
this.ctx.model.extend('file_v2', {
|
||||||
|
fileName: 'string',
|
||||||
|
fileSize: 'string',
|
||||||
|
fileUuid: 'string(128)',
|
||||||
|
msgId: 'string(24)',
|
||||||
|
msgTime: 'unsigned(10)',
|
||||||
|
peerUid: 'string(24)',
|
||||||
|
chatType: 'unsigned',
|
||||||
|
elementId: 'string(24)',
|
||||||
|
elementType: 'unsigned',
|
||||||
|
}, {
|
||||||
|
primary: 'fileUuid',
|
||||||
|
indexes: ['fileName']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createMsgShortId(peer: Peer, msgId: string): number {
|
||||||
|
const cacheKey = `${msgId}|${peer.chatType}|${peer.peerUid}`
|
||||||
|
const hash = createHash('md5').update(cacheKey).digest()
|
||||||
|
hash[0] &= 0x7f //设置第一个bit为0 保证shortId为正数
|
||||||
|
const shortId = hash.readInt32BE()
|
||||||
|
this.cache.set(cacheKey, shortId)
|
||||||
|
this.ctx.database.upsert('message', [{
|
||||||
|
msgId,
|
||||||
|
shortId,
|
||||||
|
chatType: peer.chatType,
|
||||||
|
peerUid: peer.peerUid
|
||||||
|
}], 'shortId').then()
|
||||||
|
return shortId
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMsgInfoByShortId(shortId: number): Promise<MsgInfo | undefined> {
|
||||||
|
const data = this.cache.getKey(shortId)
|
||||||
|
if (data) {
|
||||||
|
const [msgId, chatTypeStr, peerUid] = data.split('|')
|
||||||
|
return {
|
||||||
|
msgId,
|
||||||
|
peer: {
|
||||||
|
chatType: +chatTypeStr,
|
||||||
|
peerUid,
|
||||||
|
guildId: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const items = await this.ctx.database.get('message', { shortId })
|
||||||
|
if (items?.length) {
|
||||||
|
const { msgId, chatType, peerUid } = items[0]
|
||||||
|
return {
|
||||||
|
msgId,
|
||||||
|
peer: {
|
||||||
|
chatType,
|
||||||
|
peerUid,
|
||||||
|
guildId: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getShortIdByMsgId(msgId: string): Promise<number | undefined> {
|
||||||
|
return (await this.ctx.database.get('message', { msgId }))[0]?.shortId
|
||||||
|
}
|
||||||
|
|
||||||
|
getShortIdByMsgInfo(peer: Peer, msgId: string) {
|
||||||
|
const cacheKey = `${msgId}|${peer.chatType}|${peer.peerUid}`
|
||||||
|
return this.cache.getValue(cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
addFileCache(data: FileCacheV2) {
|
||||||
|
return this.ctx.database.upsert('file_v2', [data], 'fileUuid')
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileCacheByName(fileName: string) {
|
||||||
|
return this.ctx.database.get('file_v2', { fileName }, {
|
||||||
|
sort: { msgTime: 'desc' }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileCacheById(fileUuid: string) {
|
||||||
|
return this.ctx.database.get('file_v2', { fileUuid })
|
||||||
|
}
|
||||||
|
}
|
@ -233,34 +233,48 @@ export class NTQQGroupApi extends Service {
|
|||||||
>(NTMethod.GROUP_AT_ALL_REMAIN_COUNT, [{ groupCode }, null])
|
>(NTMethod.GROUP_AT_ALL_REMAIN_COUNT, [{ groupCode }, null])
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 27187 TODO */
|
|
||||||
async removeGroupEssence(groupCode: string, msgId: string) {
|
async removeGroupEssence(groupCode: string, msgId: string) {
|
||||||
const session = getSession()
|
const session = getSession()
|
||||||
// 代码没测过
|
if (session) {
|
||||||
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
|
const data = await session.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false)
|
||||||
const data = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false)
|
return session.getGroupService().removeGroupEssence({
|
||||||
const param = {
|
groupCode: groupCode,
|
||||||
|
msgRandom: Number(data?.msgList[0].msgRandom),
|
||||||
|
msgSeq: Number(data?.msgList[0].msgSeq)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const ntMsgApi = this.ctx.get('ntMsgApi')!
|
||||||
|
const data = await ntMsgApi.getMsgHistory({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false)
|
||||||
|
return await invoke('nodeIKernelGroupService/removeGroupEssence', [{
|
||||||
|
req: {
|
||||||
groupCode: groupCode,
|
groupCode: groupCode,
|
||||||
msgRandom: Number(data?.msgList[0].msgRandom),
|
msgRandom: Number(data?.msgList[0].msgRandom),
|
||||||
msgSeq: Number(data?.msgList[0].msgSeq)
|
msgSeq: Number(data?.msgList[0].msgSeq)
|
||||||
}
|
}
|
||||||
// GetMsgByShoretID(ShoretID) -> MsgService.getMsgs(Peer,MsgId,1,false) -> 组出参数
|
}, null])
|
||||||
return session?.getGroupService().removeGroupEssence(param)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 27187 TODO */
|
|
||||||
async addGroupEssence(groupCode: string, msgId: string) {
|
async addGroupEssence(groupCode: string, msgId: string) {
|
||||||
const session = getSession()
|
const session = getSession()
|
||||||
// 代码没测过
|
if (session) {
|
||||||
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
|
const data = await session.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false)
|
||||||
const data = await session?.getMsgService().getMsgsIncludeSelf({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false)
|
return session.getGroupService().addGroupEssence({
|
||||||
const param = {
|
groupCode: groupCode,
|
||||||
|
msgRandom: Number(data?.msgList[0].msgRandom),
|
||||||
|
msgSeq: Number(data?.msgList[0].msgSeq)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const ntMsgApi = this.ctx.get('ntMsgApi')!
|
||||||
|
const data = await ntMsgApi.getMsgHistory({ chatType: 2, guildId: '', peerUid: groupCode }, msgId, 1, false)
|
||||||
|
return await invoke('nodeIKernelGroupService/addGroupEssence', [{
|
||||||
|
req: {
|
||||||
groupCode: groupCode,
|
groupCode: groupCode,
|
||||||
msgRandom: Number(data?.msgList[0].msgRandom),
|
msgRandom: Number(data?.msgList[0].msgRandom),
|
||||||
msgSeq: Number(data?.msgList[0].msgSeq)
|
msgSeq: Number(data?.msgList[0].msgSeq)
|
||||||
}
|
}
|
||||||
// GetMsgByShoretID(ShoretID) -> MsgService.getMsgs(Peer,MsgId,1,false) -> 组出参数
|
}, null])
|
||||||
return session?.getGroupService().addGroupEssence(param)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async createGroupFileFolder(groupId: string, folderName: string) {
|
async createGroupFileFolder(groupId: string, folderName: string) {
|
||||||
@ -311,4 +325,14 @@ export class NTQQGroupApi extends Service {
|
|||||||
const ret = await invoke('nodeIKernelGroupService/getGroupRecommendContactArkJson', [{ groupCode }, null])
|
const ret = await invoke('nodeIKernelGroupService/getGroupRecommendContactArkJson', [{ groupCode }, null])
|
||||||
return ret.arkJson
|
return ret.arkJson
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async queryCachedEssenceMsg(groupCode: string, msgSeq = '0', msgRandom = '0') {
|
||||||
|
return await invoke('nodeIKernelGroupService/queryCachedEssenceMsg', [{
|
||||||
|
key: {
|
||||||
|
groupCode,
|
||||||
|
msgSeq: +msgSeq,
|
||||||
|
msgRandom: +msgRandom
|
||||||
|
}
|
||||||
|
}, null])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,18 +102,6 @@ export class NTQQUserApi extends Service {
|
|||||||
return await invoke('nodeIKernelTipOffService/getPskey', [{ domains, isForNewPCQQ: true }, null])
|
return await invoke('nodeIKernelTipOffService/getPskey', [{ domains, isForNewPCQQ: true }, null])
|
||||||
}
|
}
|
||||||
|
|
||||||
genBkn(sKey: string) {
|
|
||||||
sKey = sKey || ''
|
|
||||||
let hash = 5381
|
|
||||||
|
|
||||||
for (let i = 0; i < sKey.length; i++) {
|
|
||||||
const code = sKey.charCodeAt(i)
|
|
||||||
hash = hash + (hash << 5) + code
|
|
||||||
}
|
|
||||||
|
|
||||||
return (hash & 0x7fffffff).toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
async like(uid: string, count = 1) {
|
async like(uid: string, count = 1) {
|
||||||
const session = getSession()
|
const session = getSession()
|
||||||
if (session) {
|
if (session) {
|
||||||
|
@ -75,30 +75,6 @@ export interface GroupEssenceMsgRet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SetGroupNoticeParams {
|
|
||||||
groupCode: string
|
|
||||||
content: string
|
|
||||||
pinned: number
|
|
||||||
type: number
|
|
||||||
isShowEditCard: number
|
|
||||||
tipWindowType: number
|
|
||||||
confirmRequired: number
|
|
||||||
picId: string
|
|
||||||
imgWidth?: number
|
|
||||||
imgHeight?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SetGroupNoticeRet {
|
|
||||||
ec: number
|
|
||||||
em: string
|
|
||||||
id: number
|
|
||||||
ltsm: number
|
|
||||||
new_fid: string
|
|
||||||
read_only: number
|
|
||||||
role: number
|
|
||||||
srv_code: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NTQQWebApi extends Service {
|
export class NTQQWebApi extends Service {
|
||||||
static inject = ['ntUserApi']
|
static inject = ['ntUserApi']
|
||||||
|
|
||||||
@ -274,65 +250,7 @@ export class NTQQWebApi extends Service {
|
|||||||
return honorInfo
|
return honorInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
async setGroupNotice(params: SetGroupNoticeParams): Promise<SetGroupNoticeRet> {
|
|
||||||
const cookieObject = await this.ctx.ntUserApi.getCookies('qun.qq.com')
|
|
||||||
const settings = JSON.stringify({
|
|
||||||
is_show_edit_card: params.isShowEditCard,
|
|
||||||
tip_window_type: params.tipWindowType,
|
|
||||||
confirm_required: params.confirmRequired
|
|
||||||
})
|
|
||||||
|
|
||||||
return await RequestUtil.HttpGetJson<SetGroupNoticeRet>(
|
|
||||||
`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?${new URLSearchParams({
|
|
||||||
bkn: this.genBkn(cookieObject.skey),
|
|
||||||
qid: params.groupCode,
|
|
||||||
text: params.content,
|
|
||||||
pinned: params.pinned.toString(),
|
|
||||||
type: params.type.toString(),
|
|
||||||
settings: settings,
|
|
||||||
...(params.picId !== '' && {
|
|
||||||
pic: params.picId,
|
|
||||||
imgWidth: params.imgWidth?.toString(),
|
|
||||||
imgHeight: params.imgHeight?.toString(),
|
|
||||||
})
|
|
||||||
})}`,
|
|
||||||
'POST',
|
|
||||||
'',
|
|
||||||
{ 'Cookie': this.cookieToString(cookieObject) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private cookieToString(cookieObject: Dict) {
|
private cookieToString(cookieObject: Dict) {
|
||||||
return Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; ')
|
return Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; ')
|
||||||
}
|
}
|
||||||
|
|
||||||
async findGroupEssenceMsg(groupCode: string, msgSeq: number) {
|
|
||||||
for (let i = 0; i < 20; i++) {
|
|
||||||
const res = await this.getGroupEssenceMsgList(groupCode, i, 50)
|
|
||||||
if (!res) break
|
|
||||||
const msg = res.data.msg_list.find(e => e.msg_seq === msgSeq)
|
|
||||||
if (msg) return msg
|
|
||||||
if (res.data.is_end) break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getGroupEssenceMsgList(groupCode: string, pageStart: number, pageLimit: number) {
|
|
||||||
const cookieObject = await this.ctx.ntUserApi.getCookies('qun.qq.com')
|
|
||||||
try {
|
|
||||||
const ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet>(
|
|
||||||
`https://qun.qq.com/cgi-bin/group_digest/digest_list?${new URLSearchParams({
|
|
||||||
bkn: this.genBkn(cookieObject.skey),
|
|
||||||
page_start: pageStart.toString(),
|
|
||||||
page_limit: pageLimit.toString(),
|
|
||||||
group_code: groupCode,
|
|
||||||
})}`,
|
|
||||||
'GET',
|
|
||||||
'',
|
|
||||||
{ 'Cookie': this.cookieToString(cookieObject) }
|
|
||||||
)
|
|
||||||
return ret.retcode === 0 ? ret : undefined
|
|
||||||
} catch {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import { Service, Context } from 'cordis'
|
import { Service, Context } from 'cordis'
|
||||||
import { registerCallHook, registerReceiveHook, ReceiveCmdS } from './hook'
|
import { registerCallHook, registerReceiveHook, ReceiveCmdS } from './hook'
|
||||||
import { MessageUnique } from '../common/utils/messageUnique'
|
|
||||||
import { Config as LLOBConfig } from '../common/types'
|
import { Config as LLOBConfig } from '../common/types'
|
||||||
import { llonebotError } from '../common/globalVars'
|
import { llonebotError } from '../common/globalVars'
|
||||||
import { isNumeric } from '../common/utils/misc'
|
import { isNumeric } from '../common/utils/misc'
|
||||||
@ -45,7 +44,6 @@ class Core extends Service {
|
|||||||
|
|
||||||
public start() {
|
public start() {
|
||||||
llonebotError.otherError = ''
|
llonebotError.otherError = ''
|
||||||
MessageUnique.init(selfInfo.uin)
|
|
||||||
this.registerListener()
|
this.registerListener()
|
||||||
this.ctx.logger.info(`LLOneBot/${version}`)
|
this.ctx.logger.info(`LLOneBot/${version}`)
|
||||||
this.ctx.on('llonebot/config-updated', input => {
|
this.ctx.on('llonebot/config-updated', input => {
|
||||||
|
@ -72,14 +72,24 @@ export interface NodeIKernelGroupService {
|
|||||||
}
|
}
|
||||||
}): Promise<unknown>
|
}): Promise<unknown>
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
isEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>
|
||||||
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>
|
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
queryCachedEssenceMsg(req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<{
|
||||||
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>
|
items: {
|
||||||
|
groupCode: string
|
||||||
|
msgSeq: number
|
||||||
|
msgRandom: number
|
||||||
|
msgSenderUin: string
|
||||||
|
msgSenderNick: string
|
||||||
|
opType: number
|
||||||
|
opUin: string
|
||||||
|
opNick: string
|
||||||
|
opTime: number
|
||||||
|
grayTipSeq: string
|
||||||
|
}[]
|
||||||
|
}>
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
fetchGroupEssenceList(req: { groupCode: string, pageStart: number, pageLimit: number }, arg: unknown): Promise<unknown>
|
||||||
fetchGroupEssenceList(Req: { groupCode: string, pageStart: number, pageLimit: number }, Arg: unknown): Promise<unknown>
|
|
||||||
|
|
||||||
//26702
|
//26702
|
||||||
getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{
|
getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{
|
||||||
|
@ -2,7 +2,6 @@ import { BaseAction, Schema } from '../BaseAction'
|
|||||||
import { readFile } from 'node:fs/promises'
|
import { readFile } from 'node:fs/promises'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { Peer, ElementType } from '@/ntqqapi/types'
|
import { Peer, ElementType } from '@/ntqqapi/types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
export interface GetFilePayload {
|
export interface GetFilePayload {
|
||||||
file: string // 文件名或者fileUuid
|
file: string // 文件名或者fileUuid
|
||||||
@ -24,9 +23,9 @@ export abstract class GetFileBase extends BaseAction<GetFilePayload, GetFileResp
|
|||||||
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
||||||
const { enableLocalFile2Url } = this.adapter.config
|
const { enableLocalFile2Url } = this.adapter.config
|
||||||
|
|
||||||
let fileCache = await MessageUnique.getFileCacheById(payload.file)
|
let fileCache = await this.ctx.store.getFileCacheById(payload.file)
|
||||||
if (!fileCache?.length) {
|
if (!fileCache?.length) {
|
||||||
fileCache = await MessageUnique.getFileCacheByName(payload.file)
|
fileCache = await this.ctx.store.getFileCacheByName(payload.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileCache?.length) {
|
if (fileCache?.length) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { BaseAction, Schema } from '../BaseAction'
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: number | string
|
message_id: number | string
|
||||||
@ -13,13 +12,13 @@ export class DelEssenceMsg extends BaseAction<Payload, unknown> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
|
const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error('msg not found')
|
throw new Error('msg not found')
|
||||||
}
|
}
|
||||||
return await this.ctx.ntGroupApi.removeGroupEssence(
|
return await this.ctx.ntGroupApi.removeGroupEssence(
|
||||||
msg.Peer.peerUid,
|
msg.peer.peerUid,
|
||||||
msg.MsgId,
|
msg.msgId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import { BaseAction, Schema } from '../BaseAction'
|
|||||||
import { OB11ForwardMessage } from '../../types'
|
import { OB11ForwardMessage } from '../../types'
|
||||||
import { OB11Entities } from '../../entities'
|
import { OB11Entities } from '../../entities'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
import { filterNullable } from '@/common/utils/misc'
|
import { filterNullable } from '@/common/utils/misc'
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
@ -26,12 +25,12 @@ export class GetForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
if (!msgId) {
|
if (!msgId) {
|
||||||
throw Error('message_id不能为空')
|
throw Error('message_id不能为空')
|
||||||
}
|
}
|
||||||
const rootMsgId = MessageUnique.getShortIdByMsgId(msgId)
|
const rootMsgId = await this.ctx.store.getShortIdByMsgId(msgId)
|
||||||
const rootMsg = await MessageUnique.getMsgIdAndPeerByShortId(rootMsgId || +msgId)
|
const rootMsg = await this.ctx.store.getMsgInfoByShortId(rootMsgId || +msgId)
|
||||||
if (!rootMsg) {
|
if (!rootMsg) {
|
||||||
throw Error('msg not found')
|
throw Error('msg not found')
|
||||||
}
|
}
|
||||||
const data = await this.ctx.ntMsgApi.getMultiMsg(rootMsg.Peer, rootMsg.MsgId, rootMsg.MsgId)
|
const data = await this.ctx.ntMsgApi.getMultiMsg(rootMsg.peer, rootMsg.msgId, rootMsg.msgId)
|
||||||
if (data?.result !== 0) {
|
if (data?.result !== 0) {
|
||||||
throw Error('找不到相关的聊天记录' + data?.errMsg)
|
throw Error('找不到相关的聊天记录' + data?.errMsg)
|
||||||
}
|
}
|
||||||
@ -40,7 +39,7 @@ export class GetForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
msgList.map(async (msg) => {
|
msgList.map(async (msg) => {
|
||||||
const resMsg = await OB11Entities.message(this.ctx, msg)
|
const resMsg = await OB11Entities.message(this.ctx, msg)
|
||||||
if (!resMsg) return
|
if (!resMsg) return
|
||||||
resMsg.message_id = MessageUnique.createMsg({
|
resMsg.message_id = this.ctx.store.createMsgShortId({
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
}, msg.msgId)
|
}, msg.msgId)
|
||||||
|
@ -4,7 +4,6 @@ import { ActionName } from '../types'
|
|||||||
import { ChatType } from '@/ntqqapi/types'
|
import { ChatType } from '@/ntqqapi/types'
|
||||||
import { OB11Entities } from '../../entities'
|
import { OB11Entities } from '../../entities'
|
||||||
import { RawMessage } from '@/ntqqapi/types'
|
import { RawMessage } from '@/ntqqapi/types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
import { filterNullable } from '@/common/utils/misc'
|
import { filterNullable } from '@/common/utils/misc'
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
@ -35,7 +34,7 @@ export class GetGroupMsgHistory extends BaseAction<Payload, Response> {
|
|||||||
if (!payload.message_seq) {
|
if (!payload.message_seq) {
|
||||||
msgList = (await this.ctx.ntMsgApi.getAioFirstViewLatestMsgs(peer, +count)).msgList
|
msgList = (await this.ctx.ntMsgApi.getAioFirstViewLatestMsgs(peer, +count)).msgList
|
||||||
} else {
|
} else {
|
||||||
const startMsgId = (await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_seq))?.MsgId
|
const startMsgId = (await this.ctx.store.getMsgInfoByShortId(+payload.message_seq))?.msgId
|
||||||
if (!startMsgId) throw new Error(`消息${payload.message_seq}不存在`)
|
if (!startMsgId) throw new Error(`消息${payload.message_seq}不存在`)
|
||||||
msgList = (await this.ctx.ntMsgApi.getMsgHistory(peer, startMsgId, +count)).msgList
|
msgList = (await this.ctx.ntMsgApi.getMsgHistory(peer, startMsgId, +count)).msgList
|
||||||
}
|
}
|
||||||
@ -43,7 +42,7 @@ export class GetGroupMsgHistory extends BaseAction<Payload, Response> {
|
|||||||
if (reverseOrder) msgList.reverse()
|
if (reverseOrder) msgList.reverse()
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
msgList.map(async msg => {
|
msgList.map(async msg => {
|
||||||
msg.msgShortId = MessageUnique.createMsg({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
|
msg.msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
const ob11MsgList = await Promise.all(msgList.map((msg) => OB11Entities.message(this.ctx, msg)))
|
const ob11MsgList = await Promise.all(msgList.map((msg) => OB11Entities.message(this.ctx, msg)))
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { BaseAction, Schema } from '../BaseAction'
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: number | string
|
message_id: number | string
|
||||||
@ -13,11 +12,11 @@ export class MarkMsgAsRead extends BaseAction<Payload, null> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
protected async _handle(payload: Payload) {
|
protected async _handle(payload: Payload) {
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
|
const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error('msg not found')
|
throw new Error('msg not found')
|
||||||
}
|
}
|
||||||
await this.ctx.ntMsgApi.setMsgRead(msg.Peer)
|
await this.ctx.ntMsgApi.setMsgRead(msg.peer)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import { ActionName } from '../types'
|
|||||||
import { BaseAction, Schema } from '../BaseAction'
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
import { Peer } from '@/ntqqapi/types/msg'
|
import { Peer } from '@/ntqqapi/types/msg'
|
||||||
import { ChatType, ElementType, RawMessage, SendMessageElement } from '@/ntqqapi/types'
|
import { ChatType, ElementType, RawMessage, SendMessageElement } from '@/ntqqapi/types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
import { selfInfo } from '@/common/globalVars'
|
import { selfInfo } from '@/common/globalVars'
|
||||||
import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePeerMode } from '../../helper/createMessage'
|
import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePeerMode } from '../../helper/createMessage'
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
peerUid: selfInfo.uid
|
peerUid: selfInfo.uid
|
||||||
}
|
}
|
||||||
const nodeMsg = await this.ctx.ntMsgApi.sendMsg(peer, sendElements)
|
const nodeMsg = await this.ctx.ntMsgApi.sendMsg(peer, sendElements)
|
||||||
await this.ctx.sleep(400)
|
await this.ctx.sleep(300)
|
||||||
return nodeMsg
|
return nodeMsg
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.ctx.logger.warn(e, '克隆转发消息失败,将忽略本条消息', msg)
|
this.ctx.logger.warn(e, '克隆转发消息失败,将忽略本条消息', msg)
|
||||||
@ -70,19 +69,19 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
chatType: ChatType.friend,
|
chatType: ChatType.friend,
|
||||||
peerUid: selfInfo.uid,
|
peerUid: selfInfo.uid,
|
||||||
}
|
}
|
||||||
let nodeMsgIds: string[] = []
|
const nodeMsgIds: { msgId: string, peer: Peer }[] = []
|
||||||
// 先判断一遍是不是id和自定义混用
|
// 先判断一遍是不是id和自定义混用
|
||||||
for (const messageNode of messageNodes) {
|
for (const messageNode of messageNodes) {
|
||||||
// 一个node表示一个人的消息
|
// 一个node表示一个人的消息
|
||||||
const nodeId = messageNode.data.id
|
const nodeId = messageNode.data.id
|
||||||
// 有nodeId表示一个子转发消息卡片
|
// 有nodeId表示一个子转发消息卡片
|
||||||
if (nodeId) {
|
if (nodeId) {
|
||||||
const nodeMsg = await MessageUnique.getMsgIdAndPeerByShortId(+nodeId) || await MessageUnique.getPeerByMsgId(nodeId)
|
const nodeMsg = await this.ctx.store.getMsgInfoByShortId(+nodeId)
|
||||||
if (!nodeMsg) {
|
if (!nodeMsg) {
|
||||||
this.ctx.logger.warn('转发消息失败,未找到消息', nodeId)
|
this.ctx.logger.warn('转发消息失败,未找到消息', nodeId)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nodeMsgIds.push(nodeMsg.MsgId)
|
nodeMsgIds.push(nodeMsg)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 自定义的消息
|
// 自定义的消息
|
||||||
@ -111,17 +110,16 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
else {
|
else {
|
||||||
sendElementsSplit[splitIndex].push(ele)
|
sendElementsSplit[splitIndex].push(ele)
|
||||||
}
|
}
|
||||||
this.ctx.logger.info(sendElementsSplit)
|
|
||||||
}
|
}
|
||||||
// log("分割后的转发节点", sendElementsSplit)
|
this.ctx.logger.info('分割后的转发节点', sendElementsSplit)
|
||||||
for (const eles of sendElementsSplit) {
|
for (const eles of sendElementsSplit) {
|
||||||
const nodeMsg = await sendMsg(this.ctx, selfPeer, eles, [])
|
const nodeMsg = await sendMsg(this.ctx, selfPeer, eles, [])
|
||||||
if (!nodeMsg) {
|
if (!nodeMsg) {
|
||||||
this.ctx.logger.warn('转发节点生成失败', eles)
|
this.ctx.logger.warn('转发节点生成失败', eles)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nodeMsgIds.push(nodeMsg.msgId)
|
nodeMsgIds.push({ msgId: nodeMsg.msgId, peer: selfPeer })
|
||||||
await this.ctx.sleep(400)
|
await this.ctx.sleep(300)
|
||||||
}
|
}
|
||||||
deleteAfterSentFiles.map(path => unlink(path))
|
deleteAfterSentFiles.map(path => unlink(path))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -132,31 +130,34 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
|
|
||||||
// 检查srcPeer是否一致,不一致则需要克隆成自己的消息, 让所有srcPeer都变成自己的,使其保持一致才能够转发
|
// 检查srcPeer是否一致,不一致则需要克隆成自己的消息, 让所有srcPeer都变成自己的,使其保持一致才能够转发
|
||||||
const nodeMsgArray: RawMessage[] = []
|
const nodeMsgArray: RawMessage[] = []
|
||||||
let srcPeer: Peer | null = null
|
let srcPeer: Peer
|
||||||
let needSendSelf = false
|
let needSendSelf = false
|
||||||
for (const msgId of nodeMsgIds) {
|
for (const { msgId, peer } of nodeMsgIds) {
|
||||||
const nodeMsgPeer = await MessageUnique.getPeerByMsgId(msgId)
|
const nodeMsg = (await this.ctx.ntMsgApi.getMsgsByMsgId(peer, [msgId])).msgList[0]
|
||||||
if (nodeMsgPeer) {
|
srcPeer ??= { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid }
|
||||||
const nodeMsg = (await this.ctx.ntMsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0]
|
|
||||||
srcPeer = srcPeer ?? { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid }
|
|
||||||
if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
if (srcPeer.peerUid !== nodeMsg.peerUid) {
|
||||||
needSendSelf = true
|
needSendSelf = true
|
||||||
}
|
}
|
||||||
nodeMsgArray.push(nodeMsg)
|
nodeMsgArray.push(nodeMsg)
|
||||||
}
|
}
|
||||||
}
|
let retMsgIds: string[] = []
|
||||||
nodeMsgIds = nodeMsgArray.map((msg) => msg.msgId)
|
|
||||||
if (needSendSelf) {
|
if (needSendSelf) {
|
||||||
for (const msg of nodeMsgArray) {
|
for (const msg of nodeMsgArray) {
|
||||||
if (msg.peerUid === selfPeer.peerUid) continue
|
if (msg.peerUid === selfPeer.peerUid) {
|
||||||
await this.cloneMsg(msg)
|
retMsgIds.push(msg.msgId)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
const clonedMsg = await this.cloneMsg(msg)
|
||||||
|
if (clonedMsg) retMsgIds.push(clonedMsg.msgId)
|
||||||
}
|
}
|
||||||
if (nodeMsgIds.length === 0) {
|
} else {
|
||||||
|
retMsgIds = nodeMsgArray.map(msg => msg.msgId)
|
||||||
|
}
|
||||||
|
if (retMsgIds.length === 0) {
|
||||||
throw Error('转发消息失败,节点为空')
|
throw Error('转发消息失败,节点为空')
|
||||||
}
|
}
|
||||||
const returnMsg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds)
|
const returnMsg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds)
|
||||||
returnMsg.msgShortId = MessageUnique.createMsg(destPeer, returnMsg.msgId)
|
returnMsg.msgShortId = this.ctx.store.createMsgShortId(destPeer, returnMsg.msgId)
|
||||||
return returnMsg
|
return returnMsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { BaseAction } from '../BaseAction'
|
import { BaseAction } from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: number | string
|
message_id: number | string
|
||||||
@ -13,13 +12,13 @@ export class SetEssenceMsg extends BaseAction<Payload, unknown> {
|
|||||||
if (!payload.message_id) {
|
if (!payload.message_id) {
|
||||||
throw Error('message_id不能为空')
|
throw Error('message_id不能为空')
|
||||||
}
|
}
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
|
const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error('msg not found')
|
throw new Error('msg not found')
|
||||||
}
|
}
|
||||||
return await this.ctx.ntGroupApi.addGroupEssence(
|
return await this.ctx.ntGroupApi.addGroupEssence(
|
||||||
msg.Peer.peerUid,
|
msg.peer.peerUid,
|
||||||
msg.MsgId
|
msg.msgId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { BaseAction, Schema } from '../BaseAction'
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
import { Dict } from 'cosmokit'
|
import { Dict } from 'cosmokit'
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
@ -20,9 +19,9 @@ export class FetchEmojiLike extends BaseAction<Payload, Dict> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const msgInfo = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
|
const msgInfo = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
if (!msgInfo) throw new Error('消息不存在')
|
if (!msgInfo) throw new Error('消息不存在')
|
||||||
const { msgSeq } = (await this.ctx.ntMsgApi.getMsgsByMsgId(msgInfo.Peer, [msgInfo.MsgId])).msgList[0]
|
const { msgSeq } = (await this.ctx.ntMsgApi.getMsgsByMsgId(msgInfo.peer, [msgInfo.msgId])).msgList[0]
|
||||||
return await this.ctx.ntMsgApi.getMsgEmojiLikesList(msgInfo.Peer, msgSeq, payload.emojiId, payload.emojiType, +payload.count)
|
return await this.ctx.ntMsgApi.getMsgEmojiLikesList(msgInfo.peer, msgSeq, payload.emojiId, payload.emojiType, +payload.count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import { BaseAction, Schema } from '../BaseAction'
|
|||||||
import { OB11Message } from '@/onebot11/types'
|
import { OB11Message } from '@/onebot11/types'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { ChatType, RawMessage } from '@/ntqqapi/types'
|
import { ChatType, RawMessage } from '@/ntqqapi/types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
import { OB11Entities } from '@/onebot11/entities'
|
import { OB11Entities } from '@/onebot11/entities'
|
||||||
import { filterNullable } from '@/common/utils/misc'
|
import { filterNullable } from '@/common/utils/misc'
|
||||||
|
|
||||||
@ -32,9 +31,9 @@ export class GetFriendMsgHistory extends BaseAction<Payload, Response> {
|
|||||||
const startMsgId = payload.message_seq ?? payload.message_id
|
const startMsgId = payload.message_seq ?? payload.message_id
|
||||||
let msgList: RawMessage[]
|
let msgList: RawMessage[]
|
||||||
if (startMsgId) {
|
if (startMsgId) {
|
||||||
const msgInfo = await MessageUnique.getMsgIdAndPeerByShortId(+startMsgId)
|
const msgInfo = await this.ctx.store.getMsgInfoByShortId(+startMsgId)
|
||||||
if (!msgInfo) throw new Error(`消息${startMsgId}不存在`)
|
if (!msgInfo) throw new Error(`消息${startMsgId}不存在`)
|
||||||
msgList = (await this.ctx.ntMsgApi.getMsgHistory(msgInfo.Peer, msgInfo.MsgId, +payload.count)).msgList
|
msgList = (await this.ctx.ntMsgApi.getMsgHistory(msgInfo.peer, msgInfo.msgId, +payload.count)).msgList
|
||||||
} else {
|
} else {
|
||||||
const uid = await this.ctx.ntUserApi.getUidByUin(payload.user_id.toString())
|
const uid = await this.ctx.ntUserApi.getUidByUin(payload.user_id.toString())
|
||||||
if (!uid) throw new Error(`记录${payload.user_id}不存在`)
|
if (!uid) throw new Error(`记录${payload.user_id}不存在`)
|
||||||
@ -45,7 +44,7 @@ export class GetFriendMsgHistory extends BaseAction<Payload, Response> {
|
|||||||
if (msgList.length === 0) throw new Error('未找到消息')
|
if (msgList.length === 0) throw new Error('未找到消息')
|
||||||
if (payload.reverseOrder) msgList.reverse()
|
if (payload.reverseOrder) msgList.reverse()
|
||||||
msgList.map(msg => {
|
msgList.map(msg => {
|
||||||
msg.msgShortId = MessageUnique.createMsg({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
|
msg.msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
|
||||||
})
|
})
|
||||||
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Entities.message(this.ctx, msg)))
|
const ob11MsgList = await Promise.all(msgList.map(msg => OB11Entities.message(this.ctx, msg)))
|
||||||
return { messages: filterNullable(ob11MsgList) }
|
return { messages: filterNullable(ob11MsgList) }
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { BaseAction } from '../BaseAction'
|
import { BaseAction } from '../BaseAction'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: number | string
|
message_id: number | string
|
||||||
@ -13,11 +12,11 @@ class DeleteMsg extends BaseAction<Payload, void> {
|
|||||||
if (!payload.message_id) {
|
if (!payload.message_id) {
|
||||||
throw new Error('参数message_id不能为空')
|
throw new Error('参数message_id不能为空')
|
||||||
}
|
}
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
|
const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error(`消息${payload.message_id}不存在`)
|
throw new Error(`消息${payload.message_id}不存在`)
|
||||||
}
|
}
|
||||||
const data = await this.ctx.ntMsgApi.recallMsg(msg.Peer, [msg.MsgId])
|
const data = await this.ctx.ntMsgApi.recallMsg(msg.peer, [msg.msgId])
|
||||||
if (data.result !== 0) {
|
if (data.result !== 0) {
|
||||||
this.ctx.logger.error('delete_msg', payload.message_id, data)
|
this.ctx.logger.error('delete_msg', payload.message_id, data)
|
||||||
throw new Error(`消息撤回失败`)
|
throw new Error(`消息撤回失败`)
|
||||||
|
@ -2,7 +2,6 @@ import { BaseAction } from '../BaseAction'
|
|||||||
import { ChatType } from '@/ntqqapi/types'
|
import { ChatType } from '@/ntqqapi/types'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { Peer } from '@/ntqqapi/types'
|
import { Peer } from '@/ntqqapi/types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: number | string
|
message_id: number | string
|
||||||
@ -26,12 +25,12 @@ abstract class ForwardSingleMsg extends BaseAction<Payload, null> {
|
|||||||
if (!payload.message_id) {
|
if (!payload.message_id) {
|
||||||
throw Error('message_id不能为空')
|
throw Error('message_id不能为空')
|
||||||
}
|
}
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
|
const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error(`无法找到消息${payload.message_id}`)
|
throw new Error(`无法找到消息${payload.message_id}`)
|
||||||
}
|
}
|
||||||
const peer = await this.getTargetPeer(payload)
|
const peer = await this.getTargetPeer(payload)
|
||||||
const ret = await this.ctx.ntMsgApi.forwardMsg(msg.Peer, peer, [msg.MsgId])
|
const ret = await this.ctx.ntMsgApi.forwardMsg(msg.peer, peer, [msg.msgId])
|
||||||
if (ret.result !== 0) {
|
if (ret.result !== 0) {
|
||||||
throw new Error(`转发消息失败 ${ret.errMsg}`)
|
throw new Error(`转发消息失败 ${ret.errMsg}`)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import { BaseAction } from '../BaseAction'
|
|||||||
import { OB11Message } from '../../types'
|
import { OB11Message } from '../../types'
|
||||||
import { OB11Entities } from '../../entities'
|
import { OB11Entities } from '../../entities'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
export interface PayloadType {
|
export interface PayloadType {
|
||||||
message_id: number | string
|
message_id: number | string
|
||||||
@ -17,22 +16,21 @@ class GetMsg extends BaseAction<PayloadType, OB11Message> {
|
|||||||
if (!payload.message_id) {
|
if (!payload.message_id) {
|
||||||
throw new Error('参数message_id不能为空')
|
throw new Error('参数message_id不能为空')
|
||||||
}
|
}
|
||||||
const msgShortId = MessageUnique.getShortIdByMsgId(payload.message_id.toString())
|
const msgInfo = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
const msgIdWithPeer = await MessageUnique.getMsgIdAndPeerByShortId(msgShortId || +payload.message_id)
|
if (!msgInfo) {
|
||||||
if (!msgIdWithPeer) {
|
|
||||||
throw new Error('消息不存在')
|
throw new Error('消息不存在')
|
||||||
}
|
}
|
||||||
const peer = {
|
const peer = {
|
||||||
guildId: '',
|
guildId: '',
|
||||||
peerUid: msgIdWithPeer.Peer.peerUid,
|
peerUid: msgInfo.peer.peerUid,
|
||||||
chatType: msgIdWithPeer.Peer.chatType
|
chatType: msgInfo.peer.chatType
|
||||||
}
|
}
|
||||||
const msg = this.adapter.getMsgCache(msgIdWithPeer.MsgId) ?? (await this.ctx.ntMsgApi.getMsgsByMsgId(peer, [msgIdWithPeer.MsgId])).msgList[0]
|
const msg = this.adapter.getMsgCache(msgInfo.msgId) ?? (await this.ctx.ntMsgApi.getMsgsByMsgId(peer, [msgInfo.msgId])).msgList[0]
|
||||||
const retMsg = await OB11Entities.message(this.ctx, msg)
|
const retMsg = await OB11Entities.message(this.ctx, msg)
|
||||||
if (!retMsg) {
|
if (!retMsg) {
|
||||||
throw new Error('消息为空')
|
throw new Error('消息为空')
|
||||||
}
|
}
|
||||||
retMsg.message_id = MessageUnique.createMsg(peer, msg.msgId)!
|
retMsg.message_id = this.ctx.store.createMsgShortId(peer, msg.msgId)
|
||||||
retMsg.message_seq = retMsg.message_id
|
retMsg.message_seq = retMsg.message_id
|
||||||
retMsg.real_id = retMsg.message_id
|
retMsg.real_id = retMsg.message_id
|
||||||
return retMsg
|
return retMsg
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { BaseAction } from '../BaseAction'
|
import { BaseAction } from '../BaseAction'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
message_id: number | string
|
message_id: number | string
|
||||||
@ -14,19 +13,19 @@ export class SetMsgEmojiLike extends BaseAction<Payload, unknown> {
|
|||||||
if (!payload.message_id) {
|
if (!payload.message_id) {
|
||||||
throw Error('message_id不能为空')
|
throw Error('message_id不能为空')
|
||||||
}
|
}
|
||||||
const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
|
const msg = await this.ctx.store.getMsgInfoByShortId(+payload.message_id)
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
throw new Error('msg not found')
|
throw new Error('msg not found')
|
||||||
}
|
}
|
||||||
if (!payload.emoji_id) {
|
if (!payload.emoji_id) {
|
||||||
throw new Error('emojiId not found')
|
throw new Error('emojiId not found')
|
||||||
}
|
}
|
||||||
const msgData = (await this.ctx.ntMsgApi.getMsgsByMsgId(msg.Peer, [msg.MsgId])).msgList
|
const msgData = (await this.ctx.ntMsgApi.getMsgsByMsgId(msg.peer, [msg.msgId])).msgList
|
||||||
if (!msgData || msgData.length == 0 || !msgData[0].msgSeq) {
|
if (!msgData || msgData.length == 0 || !msgData[0].msgSeq) {
|
||||||
throw new Error('find msg by msgid error')
|
throw new Error('find msg by msgid error')
|
||||||
}
|
}
|
||||||
return await this.ctx.ntMsgApi.setEmojiLike(
|
return await this.ctx.ntMsgApi.setEmojiLike(
|
||||||
msg.Peer,
|
msg.peer,
|
||||||
msgData[0].msgSeq,
|
msgData[0].msgSeq,
|
||||||
payload.emoji_id.toString(),
|
payload.emoji_id.toString(),
|
||||||
true
|
true
|
||||||
|
@ -10,15 +10,12 @@ export default class SendLike extends BaseAction<Payload, null> {
|
|||||||
actionName = ActionName.SendLike
|
actionName = ActionName.SendLike
|
||||||
|
|
||||||
protected async _handle(payload: Payload): Promise<null> {
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
try {
|
const uin = payload.user_id.toString()
|
||||||
const qq = payload.user_id.toString()
|
const uid = await this.ctx.ntUserApi.getUidByUin(uin)
|
||||||
const uid: string = await this.ctx.ntUserApi.getUidByUin(qq) || ''
|
if (!uid) throw new Error('无法获取用户信息')
|
||||||
const result = await this.ctx.ntUserApi.like(uid, +payload.times || 1)
|
const result = await this.ctx.ntUserApi.like(uid, +payload.times || 1)
|
||||||
if (result?.result !== 0) {
|
if (result.result !== 0) {
|
||||||
throw Error(result?.errMsg)
|
throw new Error(result.errMsg)
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
throw `点赞失败 ${e}`
|
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import {
|
|||||||
} from '../ntqqapi/types'
|
} from '../ntqqapi/types'
|
||||||
import { OB11GroupRequestEvent } from './event/request/OB11GroupRequest'
|
import { OB11GroupRequestEvent } from './event/request/OB11GroupRequest'
|
||||||
import { OB11FriendRequestEvent } from './event/request/OB11FriendRequest'
|
import { OB11FriendRequestEvent } from './event/request/OB11FriendRequest'
|
||||||
import { MessageUnique } from '../common/utils/messageUnique'
|
|
||||||
import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent'
|
import { GroupDecreaseSubType, OB11GroupDecreaseEvent } from './event/notice/OB11GroupDecreaseEvent'
|
||||||
import { selfInfo } from '../common/globalVars'
|
import { selfInfo } from '../common/globalVars'
|
||||||
import { OB11Config, Config as LLOBConfig } from '../common/types'
|
import { OB11Config, Config as LLOBConfig } from '../common/types'
|
||||||
@ -37,7 +36,7 @@ declare module 'cordis' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OneBot11Adapter extends Service {
|
class OneBot11Adapter extends Service {
|
||||||
static inject = ['ntMsgApi', 'ntFileApi', 'ntFileCacheApi', 'ntFriendApi', 'ntGroupApi', 'ntUserApi', 'ntWindowApi', 'ntWebApi']
|
static inject = ['ntMsgApi', 'ntFileApi', 'ntFileCacheApi', 'ntFriendApi', 'ntGroupApi', 'ntUserApi', 'ntWindowApi', 'ntWebApi', 'store']
|
||||||
|
|
||||||
public messages: Map<string, RawMessage> = new Map()
|
public messages: Map<string, RawMessage> = new Map()
|
||||||
public startTime = 0
|
public startTime = 0
|
||||||
@ -190,7 +189,7 @@ class OneBot11Adapter extends Service {
|
|||||||
chatType: message.chatType,
|
chatType: message.chatType,
|
||||||
peerUid: message.peerUid
|
peerUid: message.peerUid
|
||||||
}
|
}
|
||||||
message.msgShortId = MessageUnique.createMsg(peer, message.msgId)
|
message.msgShortId = this.ctx.store.createMsgShortId(peer, message.msgId)
|
||||||
this.addMsgCache(message)
|
this.addMsgCache(message)
|
||||||
|
|
||||||
OB11Entities.message(this.ctx, message)
|
OB11Entities.message(this.ctx, message)
|
||||||
@ -227,7 +226,11 @@ class OneBot11Adapter extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleRecallMsg(message: RawMessage) {
|
private handleRecallMsg(message: RawMessage) {
|
||||||
const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId)
|
const peer = {
|
||||||
|
peerUid: message.peerUid,
|
||||||
|
chatType: message.chatType
|
||||||
|
}
|
||||||
|
const oriMessageId = this.ctx.store.getShortIdByMsgInfo(peer, message.msgId)
|
||||||
if (!oriMessageId) {
|
if (!oriMessageId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import {
|
|||||||
} from '../ntqqapi/types'
|
} from '../ntqqapi/types'
|
||||||
import { EventType } from './event/OB11BaseEvent'
|
import { EventType } from './event/OB11BaseEvent'
|
||||||
import { encodeCQCode } from './cqcode'
|
import { encodeCQCode } from './cqcode'
|
||||||
import { MessageUnique } from '../common/utils/messageUnique'
|
|
||||||
import { OB11GroupIncreaseEvent } from './event/notice/OB11GroupIncreaseEvent'
|
import { OB11GroupIncreaseEvent } from './event/notice/OB11GroupIncreaseEvent'
|
||||||
import { OB11GroupBanEvent } from './event/notice/OB11GroupBanEvent'
|
import { OB11GroupBanEvent } from './event/notice/OB11GroupBanEvent'
|
||||||
import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNoticeEvent'
|
import { OB11GroupUploadNoticeEvent } from './event/notice/OB11GroupUploadNoticeEvent'
|
||||||
@ -178,7 +177,7 @@ export namespace OB11Entities {
|
|||||||
messageSegment = {
|
messageSegment = {
|
||||||
type: OB11MessageDataType.reply,
|
type: OB11MessageDataType.reply,
|
||||||
data: {
|
data: {
|
||||||
id: MessageUnique.createMsg(peer, replyMsg ? replyMsg.msgId : records.msgId).toString()
|
id: ctx.store.createMsgShortId(peer, replyMsg ? replyMsg.msgId : records.msgId).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -198,7 +197,7 @@ export namespace OB11Entities {
|
|||||||
file_size: fileSize,
|
file_size: fileSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageUnique.addFileCache({
|
ctx.store.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
msgId: msg.msgId,
|
msgId: msg.msgId,
|
||||||
msgTime: +msg.msgTime,
|
msgTime: +msg.msgTime,
|
||||||
@ -226,7 +225,7 @@ export namespace OB11Entities {
|
|||||||
file_size: fileSize,
|
file_size: fileSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageUnique.addFileCache({
|
ctx.store.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
msgId: msg.msgId,
|
msgId: msg.msgId,
|
||||||
msgTime: +msg.msgTime,
|
msgTime: +msg.msgTime,
|
||||||
@ -251,7 +250,7 @@ export namespace OB11Entities {
|
|||||||
file_size: fileSize,
|
file_size: fileSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageUnique.addFileCache({
|
ctx.store.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
msgId: msg.msgId,
|
msgId: msg.msgId,
|
||||||
msgTime: +msg.msgTime,
|
msgTime: +msg.msgTime,
|
||||||
@ -275,7 +274,7 @@ export namespace OB11Entities {
|
|||||||
file_size: fileSize,
|
file_size: fileSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageUnique.addFileCache({
|
ctx.store.addFileCache({
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
msgId: msg.msgId,
|
msgId: msg.msgId,
|
||||||
msgTime: +msg.msgTime,
|
msgTime: +msg.msgTime,
|
||||||
@ -530,7 +529,7 @@ export namespace OB11Entities {
|
|||||||
if (!replyMsgList?.length) {
|
if (!replyMsgList?.length) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const shortId = MessageUnique.getShortIdByMsgId(replyMsgList[0].msgId)
|
const shortId = ctx.store.getShortIdByMsgInfo(peer, replyMsgList[0].msgId)
|
||||||
return new OB11GroupMsgEmojiLikeEvent(
|
return new OB11GroupMsgEmojiLikeEvent(
|
||||||
parseInt(msg.peerUid),
|
parseInt(msg.peerUid),
|
||||||
parseInt(senderUin),
|
parseInt(senderUin),
|
||||||
@ -581,27 +580,28 @@ export namespace OB11Entities {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (grayTipElement.jsonGrayTipElement?.busiId === '2401') {
|
if (grayTipElement.jsonGrayTipElement?.busiId === '2401' && json.items[2]) {
|
||||||
ctx.logger.info('收到群精华消息', json)
|
ctx.logger.info('收到群精华消息', json)
|
||||||
const searchParams = new URL(json.items[0].jp).searchParams
|
const searchParams = new URL(json.items[2].jp).searchParams
|
||||||
const msgSeq = searchParams.get('msgSeq')
|
const msgSeq = searchParams.get('seq')
|
||||||
const groupCode = searchParams.get('groupCode')
|
const groupCode = searchParams.get('gc')
|
||||||
if (!groupCode || !msgSeq) return
|
const msgRandom = searchParams.get('random')
|
||||||
|
if (!groupCode || !msgSeq || !msgRandom) return
|
||||||
const peer = {
|
const peer = {
|
||||||
guildId: '',
|
guildId: '',
|
||||||
chatType: ChatType.group,
|
chatType: ChatType.group,
|
||||||
peerUid: groupCode
|
peerUid: groupCode
|
||||||
}
|
}
|
||||||
const essence = await ctx.ntWebApi.findGroupEssenceMsg(groupCode, +msgSeq)
|
const essence = await ctx.ntGroupApi.queryCachedEssenceMsg(groupCode, msgSeq, msgRandom)
|
||||||
if (!essence) return
|
const { msgList } = await ctx.ntMsgApi.queryMsgsWithFilterExBySeq(peer, msgSeq, '0')
|
||||||
const { msgList } = await ctx.ntMsgApi.queryMsgsWithFilterExBySeq(peer, msgSeq, String(essence.sender_time))
|
const sourceMsg = msgList.find(e => e.msgRandom === msgRandom)
|
||||||
|
if (!sourceMsg) return
|
||||||
return new OB11GroupEssenceEvent(
|
return new OB11GroupEssenceEvent(
|
||||||
parseInt(msg.peerUid),
|
parseInt(msg.peerUid),
|
||||||
MessageUnique.getShortIdByMsgId(msgList[0].msgId)!,
|
ctx.store.getShortIdByMsgInfo(peer, sourceMsg.msgId)!,
|
||||||
parseInt(msgList[0].senderUin),
|
parseInt(essence.items[0]?.msgSenderUin ?? sourceMsg.senderUin),
|
||||||
parseInt(essence.add_digest_uin),
|
parseInt(essence.items[0]?.opUin ?? '0'),
|
||||||
)
|
)
|
||||||
// 获取MsgSeq+Peer可获取具体消息
|
|
||||||
}
|
}
|
||||||
if (grayTipElement.jsonGrayTipElement?.busiId === '2407') {
|
if (grayTipElement.jsonGrayTipElement?.busiId === '2407') {
|
||||||
const memberUin = json.items[1].param[0]
|
const memberUin = json.items[1].param[0]
|
||||||
|
@ -16,7 +16,6 @@ import {
|
|||||||
import { decodeCQCode } from '../cqcode'
|
import { decodeCQCode } from '../cqcode'
|
||||||
import { Peer } from '@/ntqqapi/types/msg'
|
import { Peer } from '@/ntqqapi/types/msg'
|
||||||
import { SendElementEntities } from '@/ntqqapi/entities'
|
import { SendElementEntities } from '@/ntqqapi/entities'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
import { selfInfo } from '@/common/globalVars'
|
import { selfInfo } from '@/common/globalVars'
|
||||||
import { uri2local } from '@/common/utils'
|
import { uri2local } from '@/common/utils'
|
||||||
import { Context } from 'cordis'
|
import { Context } from 'cordis'
|
||||||
@ -87,14 +86,14 @@ export async function createSendElements(
|
|||||||
break
|
break
|
||||||
case OB11MessageDataType.reply: {
|
case OB11MessageDataType.reply: {
|
||||||
if (sendMsg.data?.id) {
|
if (sendMsg.data?.id) {
|
||||||
const replyMsgId = await MessageUnique.getMsgIdAndPeerByShortId(+sendMsg.data.id)
|
const replyMsgId = await ctx.store.getMsgInfoByShortId(+sendMsg.data.id)
|
||||||
if (!replyMsgId) {
|
if (!replyMsgId) {
|
||||||
ctx.logger.warn('回复消息不存在', replyMsgId)
|
ctx.logger.warn('回复消息不存在', replyMsgId)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const replyMsg = (await ctx.ntMsgApi.getMsgsByMsgId(
|
const replyMsg = (await ctx.ntMsgApi.getMsgsByMsgId(
|
||||||
replyMsgId.Peer,
|
replyMsgId.peer,
|
||||||
[replyMsgId.MsgId!]
|
[replyMsgId.msgId!]
|
||||||
)).msgList[0]
|
)).msgList[0]
|
||||||
if (replyMsg) {
|
if (replyMsg) {
|
||||||
sendElements.push(
|
sendElements.push(
|
||||||
@ -277,7 +276,7 @@ export async function sendMsg(
|
|||||||
//log('设置消息超时时间', timeout)
|
//log('设置消息超时时间', timeout)
|
||||||
const returnMsg = await ctx.ntMsgApi.sendMsg(peer, sendElements, timeout)
|
const returnMsg = await ctx.ntMsgApi.sendMsg(peer, sendElements, timeout)
|
||||||
if (returnMsg) {
|
if (returnMsg) {
|
||||||
returnMsg.msgShortId = MessageUnique.createMsg(peer, returnMsg.msgId)
|
returnMsg.msgShortId = ctx.store.createMsgShortId(peer, returnMsg.msgId)
|
||||||
ctx.logger.info('消息发送', returnMsg.msgShortId)
|
ctx.logger.info('消息发送', returnMsg.msgShortId)
|
||||||
deleteAfterSentFiles.map(path => fsPromise.unlink(path))
|
deleteAfterSentFiles.map(path => fsPromise.unlink(path))
|
||||||
return returnMsg
|
return returnMsg
|
||||||
|
@ -3,7 +3,6 @@ import { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest'
|
|||||||
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest'
|
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest'
|
||||||
import { GroupRequestOperateTypes } from '@/ntqqapi/types'
|
import { GroupRequestOperateTypes } from '@/ntqqapi/types'
|
||||||
import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePeerMode } from '../helper/createMessage'
|
import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePeerMode } from '../helper/createMessage'
|
||||||
import { MessageUnique } from '@/common/utils/messageUnique'
|
|
||||||
import { isNullable } from 'cosmokit'
|
import { isNullable } from 'cosmokit'
|
||||||
import { Context } from 'cordis'
|
import { Context } from 'cordis'
|
||||||
|
|
||||||
@ -88,18 +87,18 @@ async function handleMsg(ctx: Context, msg: OB11Message, quickAction: QuickOpera
|
|||||||
}
|
}
|
||||||
if (msg.message_type === 'group') {
|
if (msg.message_type === 'group') {
|
||||||
const groupMsgQuickAction = quickAction as QuickOperationGroupMessage
|
const groupMsgQuickAction = quickAction as QuickOperationGroupMessage
|
||||||
const rawMessage = await MessageUnique.getMsgIdAndPeerByShortId(+(msg.message_id ?? 0))
|
const rawMessage = await ctx.store.getMsgInfoByShortId(+(msg.message_id ?? 0))
|
||||||
if (!rawMessage) return
|
if (!rawMessage) return
|
||||||
// handle group msg
|
// handle group msg
|
||||||
if (groupMsgQuickAction.delete) {
|
if (groupMsgQuickAction.delete) {
|
||||||
ctx.ntMsgApi.recallMsg(peer, [rawMessage.MsgId]).catch(e => ctx.logger.error(e))
|
ctx.ntMsgApi.recallMsg(peer, [rawMessage.msgId]).catch(e => ctx.logger.error(e))
|
||||||
}
|
}
|
||||||
if (groupMsgQuickAction.kick) {
|
if (groupMsgQuickAction.kick) {
|
||||||
const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.MsgId])
|
const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.msgId])
|
||||||
ctx.ntGroupApi.kickMember(peer.peerUid, [msgList[0].senderUid]).catch(e => ctx.logger.error(e))
|
ctx.ntGroupApi.kickMember(peer.peerUid, [msgList[0].senderUid]).catch(e => ctx.logger.error(e))
|
||||||
}
|
}
|
||||||
if (groupMsgQuickAction.ban) {
|
if (groupMsgQuickAction.ban) {
|
||||||
const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.MsgId])
|
const { msgList } = await ctx.ntMsgApi.getMsgsByMsgId(peer, [rawMessage.msgId])
|
||||||
ctx.ntGroupApi.banMember(peer.peerUid, [
|
ctx.ntGroupApi.banMember(peer.peerUid, [
|
||||||
{
|
{
|
||||||
uid: msgList[0].senderUid,
|
uid: msgList[0].senderUid,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user