mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
825c7c8e29 | ||
![]() |
c8d5eebe5d | ||
![]() |
466a3e4d66 | ||
![]() |
f6263375f1 | ||
![]() |
f79581d97e | ||
![]() |
56f26e9aa8 | ||
![]() |
9e03071629 | ||
![]() |
1f02c98c8f | ||
![]() |
e1e5c278b9 | ||
![]() |
104839f7ea | ||
![]() |
bb8771a5b4 | ||
![]() |
4a2523463b | ||
![]() |
a23a99310a | ||
![]() |
5c5105ce88 | ||
![]() |
1bf5e41bdc | ||
![]() |
cd679cc041 | ||
![]() |
eabee466bb | ||
![]() |
d3f93257ce | ||
![]() |
33f340ca81 | ||
![]() |
0d27ef7ebc | ||
![]() |
479e8c9d25 | ||
![]() |
e3dffa24f8 | ||
![]() |
30b8793ee1 | ||
![]() |
edf7a97269 | ||
![]() |
47b068737d | ||
![]() |
bfb67188ce | ||
![]() |
7ad384d407 | ||
![]() |
66335ddf9b | ||
![]() |
f7926c2e1b | ||
![]() |
b669e28038 | ||
![]() |
70b3005005 | ||
![]() |
94f1d84dd8 | ||
![]() |
aa2b4a160d | ||
![]() |
9be43de04b |
@@ -39,6 +39,7 @@ const config: ElectronViteConfig = {
|
|||||||
...external.map(genCpModule),
|
...external.map(genCpModule),
|
||||||
{ src: './manifest.json', dest: 'dist' },
|
{ src: './manifest.json', dest: 'dist' },
|
||||||
{ src: './icon.webp', dest: 'dist' },
|
{ src: './icon.webp', dest: 'dist' },
|
||||||
|
{ src: './src/ntqqapi/native/napcat-protocol-packet/Moehoo/*', dest: 'dist/main/Moehoo' },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
@@ -4,12 +4,16 @@
|
|||||||
"name": "LLOneBot",
|
"name": "LLOneBot",
|
||||||
"slug": "LLOneBot",
|
"slug": "LLOneBot",
|
||||||
"description": "实现 OneBot 11 和 Satori 协议,用于 QQ 机器人开发",
|
"description": "实现 OneBot 11 和 Satori 协议,用于 QQ 机器人开发",
|
||||||
"version": "4.1.0",
|
"version": "4.3.0",
|
||||||
"icon": "./icon.webp",
|
"icon": "./icon.webp",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "linyuchen",
|
"name": "linyuchen",
|
||||||
"link": "https://github.com/linyuchen"
|
"link": "https://github.com/linyuchen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idranme",
|
||||||
|
"link": "https://github.com/idranme"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
|
12
package.json
12
package.json
@@ -12,7 +12,7 @@
|
|||||||
"deploy-win": "cmd /c \"xcopy /C /S /Y dist\\* %LITELOADERQQNT_PROFILE%\\plugins\\LLOneBot\\\"",
|
"deploy-win": "cmd /c \"xcopy /C /S /Y dist\\* %LITELOADERQQNT_PROFILE%\\plugins\\LLOneBot\\\"",
|
||||||
"format": "prettier -cw .",
|
"format": "prettier -cw .",
|
||||||
"check": "tsc",
|
"check": "tsc",
|
||||||
"compile:proto": "pbjs --no-create --no-convert --no-verify -t static-module -w es6 -p src/ntqqapi/proto -o src/ntqqapi/proto/compiled.js profileLikeTip.proto groupNotify.proto message.proto richMedia.proto && pbts -o src/ntqqapi/proto/compiled.d.ts src/ntqqapi/proto/compiled.js"
|
"compile:proto": "pbjs --no-create --no-convert --no-delimited --no-verify -t static-module -w es6 -p src/ntqqapi/proto -o src/ntqqapi/proto/compiled.js profileLikeTip.proto groupNotify.proto message.proto richMedia.proto && pbts -o src/ntqqapi/proto/compiled.d.ts src/ntqqapi/proto/compiled.js"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -26,23 +26,23 @@
|
|||||||
"cosmokit": "^1.6.3",
|
"cosmokit": "^1.6.3",
|
||||||
"express": "^5.0.1",
|
"express": "^5.0.1",
|
||||||
"fluent-ffmpeg": "^2.1.3",
|
"fluent-ffmpeg": "^2.1.3",
|
||||||
"minato": "^3.6.0",
|
"minato": "^3.6.1",
|
||||||
"protobufjs": "^7.4.0",
|
"protobufjs": "^7.4.0",
|
||||||
"silk-wasm": "^3.6.1",
|
"silk-wasm": "^3.6.3",
|
||||||
"ts-case-convert": "^2.1.0",
|
"ts-case-convert": "^2.1.0",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/fluent-ffmpeg": "^2.1.26",
|
"@types/fluent-ffmpeg": "^2.1.27",
|
||||||
"@types/node": "^20.14.15",
|
"@types/node": "^20.14.15",
|
||||||
"@types/ws": "^8.5.12",
|
"@types/ws": "^8.5.13",
|
||||||
"electron": "^31.4.0",
|
"electron": "^31.4.0",
|
||||||
"electron-vite": "^2.3.0",
|
"electron-vite": "^2.3.0",
|
||||||
"protobufjs-cli": "^1.1.3",
|
"protobufjs-cli": "^1.1.3",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^5.4.9",
|
"vite": "^5.4.10",
|
||||||
"vite-plugin-cp": "^4.0.8"
|
"vite-plugin-cp": "^4.0.8"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.5.1"
|
"packageManager": "yarn@4.5.1"
|
||||||
|
@@ -13,6 +13,10 @@ const manifest = {
|
|||||||
{
|
{
|
||||||
name: 'linyuchen',
|
name: 'linyuchen',
|
||||||
link: 'https://github.com/linyuchen'
|
link: 'https://github.com/linyuchen'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idranme",
|
||||||
|
"link": "https://github.com/idranme"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
repository: {
|
repository: {
|
||||||
|
@@ -27,9 +27,10 @@ export function checkFileReceived(path: string, timeout: number = 3000): Promise
|
|||||||
|
|
||||||
export function calculateFileMD5(filePath: string): Promise<string> {
|
export function calculateFileMD5(filePath: string): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
const hash = createHash('md5')
|
||||||
|
|
||||||
// 创建一个流式读取器
|
// 创建一个流式读取器
|
||||||
const stream = fs.createReadStream(filePath)
|
const stream = fs.createReadStream(filePath)
|
||||||
const hash = createHash('md5')
|
|
||||||
|
|
||||||
stream.on('data', (data: Buffer) => {
|
stream.on('data', (data: Buffer) => {
|
||||||
// 当读取到数据时,更新哈希对象的状态
|
// 当读取到数据时,更新哈希对象的状态
|
||||||
@@ -122,8 +123,11 @@ export async function uri2local(ctx: Context, uri: string, needExt?: boolean): P
|
|||||||
const { type } = checkUriType(uri)
|
const { type } = checkUriType(uri)
|
||||||
|
|
||||||
if (type === FileUriType.FileURL) {
|
if (type === FileUriType.FileURL) {
|
||||||
const filePath = fileURLToPath(uri)
|
const fileUri = uri.replace('%', '%25').replace('#', '%23')
|
||||||
|
const filePath = fileURLToPath(fileUri)
|
||||||
const fileName = path.basename(filePath)
|
const fileName = path.basename(filePath)
|
||||||
|
// console.log('fileURLToPath', filePath)
|
||||||
|
// console.log('fileName', fileName)
|
||||||
return { success: true, errMsg: '', fileName, path: filePath, isLocal: true }
|
return { success: true, errMsg: '', fileName, path: filePath, isLocal: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
src/common/utils/window.ts
Normal file
9
src/common/utils/window.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { BrowserWindow } from 'electron'
|
||||||
|
import { log } from '@/common/utils'
|
||||||
|
|
||||||
|
export function getAllWindowIds(): number[] {
|
||||||
|
const allWindows = BrowserWindow.getAllWindows();
|
||||||
|
const ids = allWindows.map(window => window.id);
|
||||||
|
log('getAllWindowIds', ids);
|
||||||
|
return ids;
|
||||||
|
}
|
@@ -35,6 +35,7 @@ import {
|
|||||||
NTQQWindowApi
|
NTQQWindowApi
|
||||||
} from '../ntqqapi/api'
|
} from '../ntqqapi/api'
|
||||||
import { existsSync, mkdirSync } from 'node:fs'
|
import { existsSync, mkdirSync } from 'node:fs'
|
||||||
|
import { NTQQSystemApi } from '@/ntqqapi/api/system'
|
||||||
|
|
||||||
declare module 'cordis' {
|
declare module 'cordis' {
|
||||||
interface Events {
|
interface Events {
|
||||||
@@ -74,6 +75,7 @@ function onLoad() {
|
|||||||
ctx.plugin(NTQQWebApi)
|
ctx.plugin(NTQQWebApi)
|
||||||
ctx.plugin(NTQQWindowApi)
|
ctx.plugin(NTQQWindowApi)
|
||||||
ctx.plugin(Database)
|
ctx.plugin(Database)
|
||||||
|
ctx.plugin(NTQQSystemApi)
|
||||||
|
|
||||||
let started = false
|
let started = false
|
||||||
|
|
||||||
@@ -180,18 +182,16 @@ function onLoad() {
|
|||||||
if (self.uin) {
|
if (self.uin) {
|
||||||
clearInterval(intervalId)
|
clearInterval(intervalId)
|
||||||
log('process pid', process.pid)
|
log('process pid', process.pid)
|
||||||
|
|
||||||
const config = getConfigUtil().getConfig()
|
const config = getConfigUtil().getConfig()
|
||||||
|
|
||||||
if (config.enableLLOB && (config.satori.enable || config.ob11.enable)) {
|
if (config.enableLLOB && (config.satori.enable || config.ob11.enable)) {
|
||||||
startHook()
|
startHook()
|
||||||
await ctx.sleep(350)
|
await ctx.sleep(600)
|
||||||
} else {
|
} else {
|
||||||
llonebotError.otherError = 'LLOneBot 未启动'
|
llonebotError.otherError = 'LLOneBot 未启动'
|
||||||
log('LLOneBot 开关设置为关闭,不启动 LLOneBot')
|
log('LLOneBot 开关设置为关闭,不启动 LLOneBot')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.plugin(Log, {
|
ctx.plugin(Log, {
|
||||||
enable: config.log!,
|
enable: config.log!,
|
||||||
filename: logFileName
|
filename: logFileName
|
||||||
@@ -225,11 +225,14 @@ function onLoad() {
|
|||||||
started = true
|
started = true
|
||||||
llonebotError.otherError = ''
|
llonebotError.otherError = ''
|
||||||
}
|
}
|
||||||
}, 600)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建窗口时触发
|
// 创建窗口时触发
|
||||||
function onBrowserWindowCreated(window: BrowserWindow) {
|
function onBrowserWindowCreated(window: BrowserWindow) {
|
||||||
|
if (window.id === 2) {
|
||||||
|
mainWindow = window
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@@ -43,7 +43,7 @@ export class NTQQFileApi extends Service {
|
|||||||
msgId,
|
msgId,
|
||||||
elemId: elementId,
|
elemId: elementId,
|
||||||
videoCodecFormat: 0,
|
videoCodecFormat: 0,
|
||||||
params: {
|
exParams: {
|
||||||
downSourceType: 1,
|
downSourceType: 1,
|
||||||
triggerType: 1
|
triggerType: 1
|
||||||
}
|
}
|
||||||
|
@@ -107,7 +107,8 @@ export class NTQQFriendApi extends Service {
|
|||||||
return ret.arkMsg
|
return ret.arkMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
async setBuddyRemark(uid: string, remark: string) {
|
async setBuddyRemark(uid: string, remark?: string) {
|
||||||
|
remark = remark ?? ''
|
||||||
return await invoke('nodeIKernelBuddyService/setBuddyRemark', [{
|
return await invoke('nodeIKernelBuddyService/setBuddyRemark', [{
|
||||||
remarkParams: { uid, remark }
|
remarkParams: { uid, remark }
|
||||||
}])
|
}])
|
||||||
@@ -122,4 +123,8 @@ export class NTQQFriendApi extends Service {
|
|||||||
}
|
}
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setBuddyCategory(uid: string, categoryId: number) {
|
||||||
|
return await invoke('nodeIKernelBuddyService/setBuddyCategory', [{uid, categoryId}])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,12 @@ declare module 'cordis' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum GroupMsgMask {
|
||||||
|
ALLOW_NOTIFY = 1, // 允许提醒
|
||||||
|
ALLOW_NOT_NOTIFY = 4, // 接受消息不提醒
|
||||||
|
BOX_NOT_NOTIFY = 2, // 收进群助手不提醒
|
||||||
|
NOT_ALLOW = 3, // 屏蔽
|
||||||
|
}
|
||||||
export class NTQQGroupApi extends Service {
|
export class NTQQGroupApi extends Service {
|
||||||
static inject = ['ntWindowApi']
|
static inject = ['ntWindowApi']
|
||||||
|
|
||||||
@@ -110,8 +116,9 @@ export class NTQQGroupApi extends Service {
|
|||||||
const groupCode = flagitem[0]
|
const groupCode = flagitem[0]
|
||||||
const seq = flagitem[1]
|
const seq = flagitem[1]
|
||||||
const type = parseInt(flagitem[2])
|
const type = parseInt(flagitem[2])
|
||||||
|
const doubt = flagitem[3] === '1'
|
||||||
return await invoke(NTMethod.HANDLE_GROUP_REQUEST, [{
|
return await invoke(NTMethod.HANDLE_GROUP_REQUEST, [{
|
||||||
doubt: false,
|
doubt,
|
||||||
operateMsg: {
|
operateMsg: {
|
||||||
operateType,
|
operateType,
|
||||||
targetMsg: {
|
targetMsg: {
|
||||||
@@ -340,4 +347,13 @@ export class NTQQGroupApi extends Service {
|
|||||||
[{ groupId }]
|
[{ groupId }]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setGroupMsgMask(groupCode: string, msgMask: GroupMsgMask){
|
||||||
|
return await invoke('nodeIKernelGroupService/setGroupMsgMask', [{ groupCode, msgMask }])
|
||||||
|
}
|
||||||
|
|
||||||
|
async setGroupRemark(groupCode: string, groupRemark?: string) {
|
||||||
|
groupRemark = groupRemark ?? ''
|
||||||
|
return await invoke('nodeIKernelGroupService/modifyGroupRemark', [{ groupCode, groupRemark }])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -153,7 +153,17 @@ export class NTQQMsgApi extends Service {
|
|||||||
afterFirstCmd: false,
|
afterFirstCmd: false,
|
||||||
cmdCB: payload => {
|
cmdCB: payload => {
|
||||||
for (const msgRecord of payload.msgList) {
|
for (const msgRecord of payload.msgList) {
|
||||||
if (msgRecord.peerUid === destPeer.peerUid && msgRecord.senderUid === selfUid) {
|
if (
|
||||||
|
msgRecord.msgType === 11 &&
|
||||||
|
msgRecord.subMsgType === 7 &&
|
||||||
|
msgRecord.peerUid === destPeer.peerUid &&
|
||||||
|
msgRecord.senderUid === selfUid
|
||||||
|
) {
|
||||||
|
const element = msgRecord.elements[0]
|
||||||
|
const data = JSON.parse(element.arkElement!.bytesData)
|
||||||
|
if (data.app !== 'com.tencent.multimsg' || !data.meta.detail.resid) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,20 +171,12 @@ export class NTQQMsgApi extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for (const msg of data.msgList) {
|
return data.msgList.find(msgRecord => {
|
||||||
const arkElement = msg.elements.find(ele => ele.arkElement)
|
const { arkElement } = msgRecord.elements[0]
|
||||||
if (!arkElement) {
|
if (arkElement?.bytesData.includes('com.tencent.multimsg')) {
|
||||||
continue
|
return true
|
||||||
}
|
}
|
||||||
const forwardData = JSON.parse(arkElement.arkElement!.bytesData)
|
})!
|
||||||
if (forwardData.app !== 'com.tencent.multimsg') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (msg.peerUid === destPeer.peerUid && msg.senderUid === selfUid) {
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('转发消息超时')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSingleMsg(peer: Peer, msgSeq: string) {
|
async getSingleMsg(peer: Peer, msgSeq: string) {
|
||||||
|
39
src/ntqqapi/api/system.ts
Normal file
39
src/ntqqapi/api/system.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { Context, Service } from 'cordis'
|
||||||
|
import { invoke, NTClass } from '@/ntqqapi/ntcall'
|
||||||
|
|
||||||
|
declare module 'cordis' {
|
||||||
|
interface Context {
|
||||||
|
ntSystemApi: NTQQSystemApi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NTQQSystemApi extends Service {
|
||||||
|
static inject = ['ntUserApi']
|
||||||
|
|
||||||
|
constructor(protected ctx: Context) {
|
||||||
|
super(ctx, 'ntSystemApi', true)
|
||||||
|
}
|
||||||
|
|
||||||
|
async restart(){
|
||||||
|
// todo: 调用此接口后会将 NTQQ 设置里面的自动登录和无需手机确认打开,重启后将状态恢复到之前的状态
|
||||||
|
|
||||||
|
// 设置自动登录
|
||||||
|
await this.setSettingAutoLogin(true)
|
||||||
|
// 退出账号
|
||||||
|
invoke('quitAccount', [], {
|
||||||
|
className: NTClass.BUSINESS_API
|
||||||
|
}).then()
|
||||||
|
invoke('notifyQQClose', [{ type: 1 }], { className: NTClass.QQ_EX_API }).then()
|
||||||
|
// 等待登录界面,模拟点击登录按钮?还是直接调用登录方法?
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否自动登录
|
||||||
|
async getSettingAutoLogin(): Promise<boolean>{
|
||||||
|
return invoke('nodeIKernelNodeMiscService/queryAutoRun', [])
|
||||||
|
}
|
||||||
|
async setSettingAutoLogin(state: boolean){
|
||||||
|
await invoke('nodeIKernelSettingService/setNeedConfirmSwitch', [{state: 1}]) // 1:不需要手机确认,2:需要手机确认
|
||||||
|
|
||||||
|
await invoke('nodeIKernelSettingService/setAutoLoginSwitch', [{state}])
|
||||||
|
}
|
||||||
|
}
|
@@ -16,10 +16,11 @@ import {
|
|||||||
BuddyReqType,
|
BuddyReqType,
|
||||||
GrayTipElementSubType
|
GrayTipElementSubType
|
||||||
} from './types'
|
} from './types'
|
||||||
import { selfInfo, llonebotError } from '../common/globalVars'
|
import { selfInfo } from '../common/globalVars'
|
||||||
import { version } from '../version'
|
import { version } from '../version'
|
||||||
import { invoke } from './ntcall'
|
import { invoke } from './ntcall'
|
||||||
import { Native } from './native/index'
|
import { Native } from './native/crychic'
|
||||||
|
import { initWrapperSession, NTQQPacketApi } from './native/napcat-protocol-packet'
|
||||||
|
|
||||||
declare module 'cordis' {
|
declare module 'cordis' {
|
||||||
interface Context {
|
interface Context {
|
||||||
@@ -29,7 +30,7 @@ declare module 'cordis' {
|
|||||||
'nt/message-created': (input: RawMessage) => void
|
'nt/message-created': (input: RawMessage) => void
|
||||||
'nt/message-deleted': (input: RawMessage) => void
|
'nt/message-deleted': (input: RawMessage) => void
|
||||||
'nt/message-sent': (input: RawMessage) => void
|
'nt/message-sent': (input: RawMessage) => void
|
||||||
'nt/group-notify': (input: GroupNotify) => void
|
'nt/group-notify': (input: { notify: GroupNotify, doubt: boolean }) => void
|
||||||
'nt/friend-request': (input: FriendRequest) => void
|
'nt/friend-request': (input: FriendRequest) => void
|
||||||
'nt/group-member-info-updated': (input: { groupCode: string, members: GroupMember[] }) => void
|
'nt/group-member-info-updated': (input: { groupCode: string, members: GroupMember[] }) => void
|
||||||
'nt/system-message-created': (input: Uint8Array) => void
|
'nt/system-message-created': (input: Uint8Array) => void
|
||||||
@@ -40,10 +41,14 @@ class Core extends Service {
|
|||||||
static inject = ['ntMsgApi', 'ntFriendApi', 'ntGroupApi', 'store']
|
static inject = ['ntMsgApi', 'ntFriendApi', 'ntGroupApi', 'store']
|
||||||
public startTime = 0
|
public startTime = 0
|
||||||
public native
|
public native
|
||||||
|
public packet!: NTQQPacketApi
|
||||||
|
|
||||||
constructor(protected ctx: Context, public config: Core.Config) {
|
constructor(protected ctx: Context, public config: Core.Config) {
|
||||||
super(ctx, 'app', true)
|
super(ctx, 'app', true)
|
||||||
this.native = new Native(ctx)
|
this.native = new Native(ctx)
|
||||||
|
initWrapperSession().then(session => {
|
||||||
|
this.packet = new NTQQPacketApi(session)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public start() {
|
public start() {
|
||||||
@@ -228,7 +233,7 @@ class Core extends Service {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
groupNotifyIgnore.push(notify.seq)
|
groupNotifyIgnore.push(notify.seq)
|
||||||
this.ctx.parallel('nt/group-notify', notify)
|
this.ctx.parallel('nt/group-notify', { notify, doubt: payload.doubt })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -2,6 +2,7 @@ import { NTMethod } from './ntcall'
|
|||||||
import { log } from '@/common/utils'
|
import { log } from '@/common/utils'
|
||||||
import { randomUUID } from 'node:crypto'
|
import { randomUUID } from 'node:crypto'
|
||||||
import { ipcMain } from 'electron'
|
import { ipcMain } from 'electron'
|
||||||
|
import { Dict } from 'cosmokit'
|
||||||
|
|
||||||
export const hookApiCallbacks: Record<string, (res: any) => void> = {}
|
export const hookApiCallbacks: Record<string, (res: any) => void> = {}
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ export enum ReceiveCmdS {
|
|||||||
MEDIA_UPLOAD_COMPLETE = 'nodeIKernelMsgListener/onRichMediaUploadComplete',
|
MEDIA_UPLOAD_COMPLETE = 'nodeIKernelMsgListener/onRichMediaUploadComplete',
|
||||||
}
|
}
|
||||||
|
|
||||||
const logHook = false
|
const logHook = true
|
||||||
|
|
||||||
const receiveHooks: Map<string, {
|
const receiveHooks: Map<string, {
|
||||||
method: ReceiveCmdS[]
|
method: ReceiveCmdS[]
|
||||||
@@ -40,40 +41,43 @@ const callHooks: Array<{
|
|||||||
}> = []
|
}> = []
|
||||||
|
|
||||||
export function startHook() {
|
export function startHook() {
|
||||||
|
log('start hook')
|
||||||
|
|
||||||
const senderExclude = Symbol()
|
const senderExclude = Symbol()
|
||||||
|
|
||||||
ipcMain.emit = new Proxy(ipcMain.emit, {
|
ipcMain.emit = new Proxy(ipcMain.emit, {
|
||||||
apply(target, thisArg, args: [eventName: string, ...args: any]) {
|
apply(target, thisArg, args: [channel: string, ...args: any]) {
|
||||||
if (args[2]?.eventName.startsWith('ns-LoggerApi')) {
|
if (args[2]?.eventName?.startsWith('ns-LoggerApi')) {
|
||||||
return target.apply(thisArg, args)
|
return target.apply(thisArg, args)
|
||||||
}
|
}
|
||||||
if (logHook) {
|
if (logHook) {
|
||||||
log('request', args)
|
log('request', args)
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = args[1]
|
const event = args[1]
|
||||||
if (event.sender && !event.sender[senderExclude]) {
|
if (event.sender && !event.sender[senderExclude]) {
|
||||||
event.sender[senderExclude] = true
|
event.sender[senderExclude] = true
|
||||||
event.sender.send = new Proxy(event.sender.send, {
|
event.sender.send = new Proxy(event.sender.send, {
|
||||||
apply(target, thisArg, args: any[]) {
|
apply(target, thisArg, args: [channel: string, meta: Dict, data: Dict[]]) {
|
||||||
if (args[1].eventName?.startsWith('ns-LoggerApi')) {
|
if (args[1]?.eventName?.startsWith('ns-LoggerApi')) {
|
||||||
return target.apply(thisArg, args)
|
return target.apply(thisArg, args)
|
||||||
}
|
}
|
||||||
if (logHook) {
|
if (logHook) {
|
||||||
log('received', args)
|
log('received', args)
|
||||||
}
|
}
|
||||||
|
|
||||||
const callbackId = args[1].callbackId
|
const callbackId = args[1]?.callbackId
|
||||||
if (callbackId) {
|
if (callbackId) {
|
||||||
if (hookApiCallbacks[callbackId]) {
|
if (hookApiCallbacks[callbackId]) {
|
||||||
Promise.resolve(hookApiCallbacks[callbackId](args[2]))
|
Promise.resolve(hookApiCallbacks[callbackId](args[2]))
|
||||||
delete hookApiCallbacks[callbackId]
|
delete hookApiCallbacks[callbackId]
|
||||||
}
|
}
|
||||||
} else if (args[2]) {
|
} else if (args[2]) {
|
||||||
for (const receiveData of args[2]) {
|
if (['IPC_DOWN_2', 'IPC_DOWN_3'].includes(args[0])) {
|
||||||
for (const hook of receiveHooks.values()) {
|
for (const receiveData of args[2]) {
|
||||||
if (hook.method.includes(receiveData.cmdName)) {
|
for (const hook of receiveHooks.values()) {
|
||||||
Promise.resolve(hook.hookFunc(receiveData.payload))
|
if (hook.method.includes(receiveData.cmdName)) {
|
||||||
|
Promise.resolve(hook.hookFunc(receiveData.payload))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +97,7 @@ export function startHook() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return target.apply(thisArg, args)
|
return target.apply(thisArg, args)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import { Context } from 'cordis'
|
import { Context } from 'cordis'
|
||||||
import { Dict } from 'cosmokit'
|
import { Dict } from 'cosmokit'
|
||||||
import { getBuildVersion } from '@/common/utils/misc'
|
import { getBuildVersion } from '../../../common/utils/misc'
|
||||||
import { TEMP_DIR } from '@/common/globalVars'
|
import { TEMP_DIR } from '../../../common/globalVars'
|
||||||
import { copyFile } from 'fs/promises'
|
import { copyFile } from 'fs/promises'
|
||||||
import { ChatType, Peer } from '../types'
|
import { ChatType, Peer } from '../../types'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import addon from './external/crychic-win32-x64.node?asset'
|
import addon from './external/crychic-win32-x64.node?asset'
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ export class Native {
|
|||||||
public activated = false
|
public activated = false
|
||||||
private crychic?: Dict
|
private crychic?: Dict
|
||||||
private seq = 0
|
private seq = 0
|
||||||
private cb: Map<number, Function> = new Map()
|
private cb: Map<number, (res: any) => void> = new Map()
|
||||||
|
|
||||||
constructor(private ctx: Context) {
|
constructor(private ctx: Context) {
|
||||||
ctx.on('ready', () => {
|
ctx.on('ready', () => {
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
17
src/ntqqapi/native/napcat-protocol-packet/index.d.ts
vendored
Normal file
17
src/ntqqapi/native/napcat-protocol-packet/index.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { WrapperSession } from './wrapper-session/types';
|
||||||
|
export { initWrapperSession } from './wrapper-session';
|
||||||
|
export declare class NTQQPacketApi {
|
||||||
|
private qqVersion;
|
||||||
|
private packetSession;
|
||||||
|
private logger;
|
||||||
|
private readonly wrapperSession;
|
||||||
|
constructor(wrapperSession: WrapperSession);
|
||||||
|
get available(): boolean;
|
||||||
|
private checkQQVersion;
|
||||||
|
private InitSendPacket;
|
||||||
|
private sendPacket;
|
||||||
|
private sendOidbPacket;
|
||||||
|
sendPokePacket(peer: number, group?: number): Promise<void>;
|
||||||
|
sendGroupSignPacket(selfUin: string, groupCode: string): Promise<void>;
|
||||||
|
sendSetSpecialTittlePacket(groupCode: string, uid: string, tittle: string): Promise<void>;
|
||||||
|
}
|
7187
src/ntqqapi/native/napcat-protocol-packet/index.mjs
Normal file
7187
src/ntqqapi/native/napcat-protocol-packet/index.mjs
Normal file
File diff suppressed because one or more lines are too long
1
src/ntqqapi/native/napcat-protocol-packet/wrapper-session/index.d.ts
vendored
Normal file
1
src/ntqqapi/native/napcat-protocol-packet/wrapper-session/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export declare function initWrapperSession(): Promise<any>;
|
6
src/ntqqapi/native/napcat-protocol-packet/wrapper-session/types.d.ts
vendored
Normal file
6
src/ntqqapi/native/napcat-protocol-packet/wrapper-session/types.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export interface MsgService {
|
||||||
|
sendSsoCmdReqByContend: (cmd: string, trace_id: string) => Promise<unknown>;
|
||||||
|
}
|
||||||
|
export type WrapperSession = {
|
||||||
|
getMsgService(): MsgService;
|
||||||
|
};
|
@@ -1,6 +1,6 @@
|
|||||||
import { ipcMain } from 'electron'
|
import { ipcMain } from 'electron'
|
||||||
import { hookApiCallbacks, registerReceiveHook, removeReceiveHook } from './hook'
|
import { hookApiCallbacks, registerReceiveHook, removeReceiveHook } from './hook'
|
||||||
import { getBuildVersion, log } from '../common/utils'
|
import { log } from '../common/utils'
|
||||||
import { randomUUID } from 'node:crypto'
|
import { randomUUID } from 'node:crypto'
|
||||||
import {
|
import {
|
||||||
GeneralCallResult,
|
GeneralCallResult,
|
||||||
@@ -29,7 +29,8 @@ export enum NTClass {
|
|||||||
SKEY_API = 'ns-SkeyApi',
|
SKEY_API = 'ns-SkeyApi',
|
||||||
GROUP_HOME_WORK = 'ns-GroupHomeWork',
|
GROUP_HOME_WORK = 'ns-GroupHomeWork',
|
||||||
GROUP_ESSENCE = 'ns-GroupEssence',
|
GROUP_ESSENCE = 'ns-GroupEssence',
|
||||||
NODE_STORE_API = 'ns-NodeStoreApi'
|
NODE_STORE_API = 'ns-NodeStoreApi',
|
||||||
|
QQ_EX_API = 'ns-QQEXApi',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NTMethod {
|
export enum NTMethod {
|
||||||
@@ -108,13 +109,26 @@ interface InvokeOptions<ReturnType> {
|
|||||||
timeout?: number
|
timeout?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let channel: NTChannel
|
||||||
|
|
||||||
|
function getChannel() {
|
||||||
|
if (channel) {
|
||||||
|
return channel
|
||||||
|
}
|
||||||
|
if (ipcMain.eventNames().includes(NTChannel.IPC_UP_2)) {
|
||||||
|
return channel = NTChannel.IPC_UP_2
|
||||||
|
} else {
|
||||||
|
return channel = NTChannel.IPC_UP_3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function invoke<
|
export function invoke<
|
||||||
R extends Awaited<ReturnType<Extract<NTService[S][M], (...args: any) => unknown>>>,
|
R extends Awaited<ReturnType<Extract<NTService[S][M], (...args: any) => unknown>>>,
|
||||||
S extends keyof NTService = any,
|
S extends keyof NTService = any,
|
||||||
M extends keyof NTService[S] & string = any
|
M extends keyof NTService[S] & string = any
|
||||||
>(method: Extract<unknown, `${S}/${M}`> | string, args: unknown[], options: InvokeOptions<R> = {}) {
|
>(method: Extract<unknown, `${S}/${M}`> | string, args: unknown[], options: InvokeOptions<R> = {}) {
|
||||||
const className = options.className ?? NTClass.NT_API
|
const className = options.className ?? NTClass.NT_API
|
||||||
const channel = options.channel ?? getBuildVersion() >= 28788 ? NTChannel.IPC_UP_3 : NTChannel.IPC_UP_2
|
const channel = options.channel ?? getChannel()
|
||||||
const timeout = options.timeout ?? 5000
|
const timeout = options.timeout ?? 5000
|
||||||
const afterFirstCmd = options.afterFirstCmd ?? true
|
const afterFirstCmd = options.afterFirstCmd ?? true
|
||||||
let eventName = className + '-' + channel[channel.length - 1]
|
let eventName = className + '-' + channel[channel.length - 1]
|
||||||
|
595
src/ntqqapi/proto/compiled.d.ts
vendored
595
src/ntqqapi/proto/compiled.d.ts
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -442,6 +442,7 @@ export interface RawMessage {
|
|||||||
attrType: number
|
attrType: number
|
||||||
attrId: string
|
attrId: string
|
||||||
}>
|
}>
|
||||||
|
isOnlineMsg: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Peer {
|
export interface Peer {
|
||||||
|
@@ -23,8 +23,8 @@ interface FileResponse {
|
|||||||
export class DownloadFile extends BaseAction<Payload, FileResponse> {
|
export class DownloadFile extends BaseAction<Payload, FileResponse> {
|
||||||
actionName = ActionName.GoCQHTTP_DownloadFile
|
actionName = ActionName.GoCQHTTP_DownloadFile
|
||||||
payloadSchema = Schema.object({
|
payloadSchema = Schema.object({
|
||||||
url: String,
|
url: Schema.string(),
|
||||||
base64: String,
|
base64: Schema.string(),
|
||||||
headers: Schema.union([String, Schema.array(String)])
|
headers: Schema.union([String, Schema.array(String)])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@ interface Payload {
|
|||||||
interface Response extends OB11User {
|
interface Response extends OB11User {
|
||||||
reg_time: number
|
reg_time: number
|
||||||
long_nick: string
|
long_nick: string
|
||||||
|
city: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetStrangerInfo extends BaseAction<Payload, Response> {
|
export class GetStrangerInfo extends BaseAction<Payload, Response> {
|
||||||
@@ -33,7 +34,8 @@ export class GetStrangerInfo extends BaseAction<Payload, Response> {
|
|||||||
level: data.detail.commonExt.qqLevel && calcQQLevel(data.detail.commonExt.qqLevel) || 0,
|
level: data.detail.commonExt.qqLevel && calcQQLevel(data.detail.commonExt.qqLevel) || 0,
|
||||||
login_days: 0,
|
login_days: 0,
|
||||||
reg_time: data.detail.commonExt.regTime,
|
reg_time: data.detail.commonExt.regTime,
|
||||||
long_nick: data.detail.simpleInfo.baseInfo.longNick
|
long_nick: data.detail.simpleInfo.baseInfo.longNick,
|
||||||
|
city: data.detail.commonExt.city
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const data = await this.ctx.ntUserApi.getUserDetailInfoByUin(uin)
|
const data = await this.ctx.ntUserApi.getUserDetailInfoByUin(uin)
|
||||||
@@ -46,7 +48,8 @@ export class GetStrangerInfo extends BaseAction<Payload, Response> {
|
|||||||
level: data.info.qqLevel && calcQQLevel(data.info.qqLevel) || 0,
|
level: data.info.qqLevel && calcQQLevel(data.info.qqLevel) || 0,
|
||||||
login_days: 0,
|
login_days: 0,
|
||||||
reg_time: data.info.regTime,
|
reg_time: data.info.regTime,
|
||||||
long_nick: data.info.longNick
|
long_nick: data.info.longNick,
|
||||||
|
city: data.info.city
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@ interface Payload {
|
|||||||
|
|
||||||
interface Response {
|
interface Response {
|
||||||
message_id: number
|
message_id: number
|
||||||
forward_id?: string
|
forward_id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SendForwardMsg extends BaseAction<Payload, Response> {
|
export class SendForwardMsg extends BaseAction<Payload, Response> {
|
||||||
@@ -60,14 +60,11 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let msg: RawMessage
|
|
||||||
if (fake && this.ctx.app.native.activated) {
|
if (fake && this.ctx.app.native.activated) {
|
||||||
msg = await this.handleFakeForwardNode(peer, nodes)
|
return await this.handleFakeForwardNode(peer, nodes)
|
||||||
} else {
|
} else {
|
||||||
msg = await this.handleForwardNode(peer, nodes)
|
return await this.handleForwardNode(peer, nodes)
|
||||||
}
|
}
|
||||||
const msgShortId = this.ctx.store.createMsgShortId({ chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId)
|
|
||||||
return { message_id: msgShortId }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseNodeContent(nodes: OB11MessageNode[]) {
|
private parseNodeContent(nodes: OB11MessageNode[]) {
|
||||||
@@ -82,7 +79,7 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleFakeForwardNode(peer: Peer, nodes: OB11MessageNode[]) {
|
private async handleFakeForwardNode(peer: Peer, nodes: OB11MessageNode[]): Promise<Response> {
|
||||||
const encoder = new MessageEncoder(this.ctx, peer)
|
const encoder = new MessageEncoder(this.ctx, peer)
|
||||||
const raw = await encoder.generate(nodes)
|
const raw = await encoder.generate(nodes)
|
||||||
const transmit = Msg.PbMultiMsgTransmit.encode({ pbItemList: raw.multiMsgItems }).finish()
|
const transmit = Msg.PbMultiMsgTransmit.encode({ pbItemList: raw.multiMsgItems }).finish()
|
||||||
@@ -122,7 +119,11 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}], 1800)
|
}], 1800)
|
||||||
return msg!
|
const msgShortId = this.ctx.store.createMsgShortId({
|
||||||
|
chatType: msg!.chatType,
|
||||||
|
peerUid: msg!.peerUid
|
||||||
|
}, msg!.msgId)
|
||||||
|
return { message_id: msgShortId, forward_id: resid }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.ctx.logger.error('合并转发失败', e)
|
this.ctx.logger.error('合并转发失败', e)
|
||||||
throw new Error(`发送伪造合并转发消息失败 (res_id: ${resid} `)
|
throw new Error(`发送伪造合并转发消息失败 (res_id: ${resid} `)
|
||||||
@@ -153,7 +154,7 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 返回一个合并转发的消息id
|
// 返回一个合并转发的消息id
|
||||||
private async handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]) {
|
private async handleForwardNode(destPeer: Peer, messageNodes: OB11MessageNode[]): Promise<Response> {
|
||||||
const selfPeer = {
|
const selfPeer = {
|
||||||
chatType: ChatType.C2C,
|
chatType: ChatType.C2C,
|
||||||
peerUid: selfInfo.uid,
|
peerUid: selfInfo.uid,
|
||||||
@@ -245,8 +246,13 @@ export class SendForwardMsg extends BaseAction<Payload, Response> {
|
|||||||
if (retMsgIds.length === 0) {
|
if (retMsgIds.length === 0) {
|
||||||
throw Error('转发消息失败,节点为空')
|
throw Error('转发消息失败,节点为空')
|
||||||
}
|
}
|
||||||
const returnMsg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds)
|
const msg = await this.ctx.ntMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds)
|
||||||
return returnMsg
|
const resid = JSON.parse(msg.elements[0].arkElement!.bytesData).meta.detail.resid
|
||||||
|
const msgShortId = this.ctx.store.createMsgShortId({
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid
|
||||||
|
}, msg.msgId)
|
||||||
|
return { message_id: msgShortId, forward_id: resid }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
src/onebot11/action/go-cqhttp/SendGroupSign.ts
Normal file
19
src/onebot11/action/go-cqhttp/SendGroupSign.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
import { selfInfo } from '@/common/globalVars'
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
group_id: number | string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SendGroupSign extends BaseAction<Payload, null> {
|
||||||
|
actionName = ActionName.GoCQHTTP_SendGroupSign
|
||||||
|
payloadSchema = Schema.object({
|
||||||
|
group_id: Schema.union([Number, String]).required(),
|
||||||
|
})
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
await this.ctx.app.packet.sendGroupSignPacket(selfInfo.uin, payload.group_id.toString())
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
30
src/onebot11/action/go-cqhttp/SetGroupSpecialTitle.ts
Normal file
30
src/onebot11/action/go-cqhttp/SetGroupSpecialTitle.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
import { selfInfo } from '@/common/globalVars'
|
||||||
|
import { GroupMemberRole } from '@/ntqqapi/types'
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
group_id: number | string
|
||||||
|
user_id: number | string
|
||||||
|
special_title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SetGroupSpecialTitle extends BaseAction<Payload, null> {
|
||||||
|
actionName = ActionName.GoCQHTTP_SetGroupSpecialTitle
|
||||||
|
payloadSchema = Schema.object({
|
||||||
|
group_id: Schema.union([Number, String]).required(),
|
||||||
|
user_id: Schema.union([Number, String]).required(),
|
||||||
|
special_title: Schema.string()
|
||||||
|
})
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
const uid = await this.ctx.ntUserApi.getUidByUin(payload.user_id.toString(), payload.group_id.toString())
|
||||||
|
if (!uid) throw new Error(`用户${payload.user_id}的uid获取失败`)
|
||||||
|
const self = await this.ctx.ntGroupApi.getGroupMember(payload.group_id.toString(), selfInfo.uid, false)
|
||||||
|
if (self.role !== GroupMemberRole.Owner){
|
||||||
|
throw new Error(`不是群${payload.group_id}的群主,无法设置群头衔`)
|
||||||
|
}
|
||||||
|
await this.ctx.app.packet.sendSetSpecialTittlePacket(payload.group_id.toString(), uid, payload.special_title || "")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@@ -78,6 +78,13 @@ import { GroupPoke } from './llonebot/GroupPoke'
|
|||||||
import { FriendPoke } from './llonebot/FriendPoke'
|
import { FriendPoke } from './llonebot/FriendPoke'
|
||||||
import { GetGroupFileSystemInfo } from './go-cqhttp/GetGroupFileSystemInfo'
|
import { GetGroupFileSystemInfo } from './go-cqhttp/GetGroupFileSystemInfo'
|
||||||
import { GetCredentials } from './system/GetCredentials'
|
import { GetCredentials } from './system/GetCredentials'
|
||||||
|
import { SetGroupSpecialTitle } from '@/onebot11/action/go-cqhttp/SetGroupSpecialTitle'
|
||||||
|
import { SendGroupSign } from '@/onebot11/action/go-cqhttp/SendGroupSign'
|
||||||
|
import { SetRestart } from '@/onebot11/action/system/SetRestart'
|
||||||
|
import { SetFriendCategory } from '@/onebot11/action/llonebot/SetFriendCategory'
|
||||||
|
import { SetFriendRemark } from '@/onebot11/action/llonebot/SetFriendRemark'
|
||||||
|
import { SetGroupMsgMask } from '@/onebot11/action/llonebot/SetGroupMsgMask'
|
||||||
|
import { SetGroupRemark } from '@/onebot11/action/llonebot/SetGroupRemark'
|
||||||
|
|
||||||
export function initActionMap(adapter: Adapter) {
|
export function initActionMap(adapter: Adapter) {
|
||||||
const actionHandlers = [
|
const actionHandlers = [
|
||||||
@@ -98,6 +105,10 @@ export function initActionMap(adapter: Adapter) {
|
|||||||
new GetRobotUinRange(adapter),
|
new GetRobotUinRange(adapter),
|
||||||
new GroupPoke(adapter),
|
new GroupPoke(adapter),
|
||||||
new FriendPoke(adapter),
|
new FriendPoke(adapter),
|
||||||
|
new SetFriendCategory(adapter),
|
||||||
|
new SetFriendRemark(adapter),
|
||||||
|
new SetGroupMsgMask(adapter),
|
||||||
|
new SetGroupRemark(adapter),
|
||||||
// onebot11
|
// onebot11
|
||||||
new SendLike(adapter),
|
new SendLike(adapter),
|
||||||
new GetMsg(adapter),
|
new GetMsg(adapter),
|
||||||
@@ -131,6 +142,7 @@ export function initActionMap(adapter: Adapter) {
|
|||||||
new ForwardFriendSingleMsg(adapter),
|
new ForwardFriendSingleMsg(adapter),
|
||||||
new ForwardGroupSingleMsg(adapter),
|
new ForwardGroupSingleMsg(adapter),
|
||||||
new GetCredentials(adapter),
|
new GetCredentials(adapter),
|
||||||
|
new SetRestart(adapter),
|
||||||
// go-cqhttp
|
// go-cqhttp
|
||||||
new GetEssenceMsgList(adapter),
|
new GetEssenceMsgList(adapter),
|
||||||
new GetGroupHonorInfo(adapter),
|
new GetGroupHonorInfo(adapter),
|
||||||
@@ -161,6 +173,8 @@ export function initActionMap(adapter: Adapter) {
|
|||||||
new DeleteFriend(adapter),
|
new DeleteFriend(adapter),
|
||||||
new OCRImage(adapter),
|
new OCRImage(adapter),
|
||||||
new GetGroupFileSystemInfo(adapter),
|
new GetGroupFileSystemInfo(adapter),
|
||||||
|
new SetGroupSpecialTitle(adapter),
|
||||||
|
new SendGroupSign(adapter),
|
||||||
]
|
]
|
||||||
const actionMap = new Map()
|
const actionMap = new Map()
|
||||||
for (const action of actionHandlers) {
|
for (const action of actionHandlers) {
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { BaseAction, Schema } from '../BaseAction'
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { getBuildVersion } from '@/common/utils/misc'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
user_id: number | string
|
user_id: number | string
|
||||||
@@ -13,13 +12,15 @@ export class FriendPoke extends BaseAction<Payload, null> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
if (!this.ctx.app.native.checkPlatform()) {
|
// if (!this.ctx.app.native.checkPlatform()) {
|
||||||
throw new Error('当前系统平台或架构不支持')
|
// throw new Error('当前系统平台或架构不支持')
|
||||||
}
|
// }
|
||||||
if (!this.ctx.app.native.checkVersion()) {
|
// if (!this.ctx.app.native.checkVersion()) {
|
||||||
throw new Error(`当前 QQ 版本 ${getBuildVersion()} 不支持,可尝试其他版本 27333—27597`)
|
// throw new Error(`当前 QQ 版本 ${getBuildVersion()} 不支持,可尝试其他版本 27333—27597`)
|
||||||
}
|
// }
|
||||||
await this.ctx.app.native.sendFriendPoke(+payload.user_id)
|
// await this.ctx.app.native.sendFriendPoke(+payload.user_id)
|
||||||
|
|
||||||
|
await this.ctx.app.packet.sendPokePacket(+payload.user_id)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { BaseAction, Schema } from '../BaseAction'
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
import { ActionName } from '../types'
|
import { ActionName } from '../types'
|
||||||
import { getBuildVersion } from '@/common/utils/misc'
|
|
||||||
|
|
||||||
interface Payload {
|
interface Payload {
|
||||||
group_id: number | string
|
group_id: number | string
|
||||||
@@ -15,13 +14,14 @@ export class GroupPoke extends BaseAction<Payload, null> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
if (!this.ctx.app.native.checkPlatform()) {
|
// if (!this.ctx.app.native.checkPlatform()) {
|
||||||
throw new Error('当前系统平台或架构不支持')
|
// throw new Error('当前系统平台或架构不支持')
|
||||||
}
|
// }
|
||||||
if (!this.ctx.app.native.checkVersion()) {
|
// if (!this.ctx.app.native.checkVersion()) {
|
||||||
throw new Error(`当前 QQ 版本 ${getBuildVersion()} 不支持,可尝试其他版本 27333—27597`)
|
// throw new Error(`当前 QQ 版本 ${getBuildVersion()} 不支持,可尝试其他版本 27333—27597`)
|
||||||
}
|
// }
|
||||||
await this.ctx.app.native.sendGroupPoke(+payload.group_id, +payload.user_id)
|
// await this.ctx.app.native.sendGroupPoke(+payload.group_id, +payload.user_id)
|
||||||
|
await this.ctx.app.packet.sendPokePacket(+payload.user_id, +payload.group_id)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
src/onebot11/action/llonebot/SetFriendCategory.ts
Normal file
17
src/onebot11/action/llonebot/SetFriendCategory.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { BaseAction } from '../BaseAction'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
user_id: string,
|
||||||
|
category_id: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SetFriendCategory extends BaseAction<Payload, null> {
|
||||||
|
actionName = ActionName.SetFriendCategory
|
||||||
|
|
||||||
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
|
const uid = await this.ctx.ntUserApi.getUidByUin(payload.user_id.toString())
|
||||||
|
if (!uid) throw new Error('无法获取好友信息')
|
||||||
|
return this.ctx.ntFriendApi.setBuddyCategory(uid, +payload.category_id)
|
||||||
|
}
|
||||||
|
}
|
17
src/onebot11/action/llonebot/SetFriendRemark.ts
Normal file
17
src/onebot11/action/llonebot/SetFriendRemark.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { BaseAction } from '../BaseAction'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
user_id: string,
|
||||||
|
remark?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SetFriendRemark extends BaseAction<Payload, null> {
|
||||||
|
actionName = ActionName.SetFriendRemark
|
||||||
|
|
||||||
|
protected async _handle(payload: Payload): Promise<null> {
|
||||||
|
const uid = await this.ctx.ntUserApi.getUidByUin(payload.user_id.toString())
|
||||||
|
if (!uid) throw new Error('无法获取好友信息')
|
||||||
|
return this.ctx.ntFriendApi.setBuddyRemark(uid, payload.remark || '')
|
||||||
|
}
|
||||||
|
}
|
16
src/onebot11/action/llonebot/SetGroupMsgMask.ts
Normal file
16
src/onebot11/action/llonebot/SetGroupMsgMask.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { BaseAction } from '../BaseAction'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
import { GroupMsgMask } from '@/ntqqapi/api'
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
group_id: string,
|
||||||
|
mask: GroupMsgMask
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SetGroupMsgMask extends BaseAction<Payload, unknown> {
|
||||||
|
actionName = ActionName.SetGroupMsgMask
|
||||||
|
|
||||||
|
protected async _handle(payload: Payload): Promise<unknown>{
|
||||||
|
return this.ctx.ntGroupApi.setGroupMsgMask(payload.group_id.toString(), +payload.mask)
|
||||||
|
}
|
||||||
|
}
|
15
src/onebot11/action/llonebot/SetGroupRemark.ts
Normal file
15
src/onebot11/action/llonebot/SetGroupRemark.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { BaseAction } from '../BaseAction'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
group_id: string,
|
||||||
|
remark?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SetGroupRemark extends BaseAction<Payload, unknown> {
|
||||||
|
actionName = ActionName.SetGroupRemark
|
||||||
|
|
||||||
|
protected async _handle(payload: Payload): Promise<unknown>{
|
||||||
|
return this.ctx.ntGroupApi.setGroupRemark(payload.group_id.toString(), payload.remark)
|
||||||
|
}
|
||||||
|
}
|
@@ -7,62 +7,52 @@ import { ChatCacheListItemBasic, CacheFileType } from '@/ntqqapi/types'
|
|||||||
export default class CleanCache extends BaseAction<void, void> {
|
export default class CleanCache extends BaseAction<void, void> {
|
||||||
actionName = ActionName.CleanCache
|
actionName = ActionName.CleanCache
|
||||||
|
|
||||||
protected _handle(): Promise<void> {
|
protected async _handle(): Promise<void> {
|
||||||
return new Promise<void>(async (res, rej) => {
|
const cacheFilePaths: string[] = []
|
||||||
try {
|
|
||||||
// dbUtil.clearCache()
|
|
||||||
const cacheFilePaths: string[] = []
|
|
||||||
|
|
||||||
await this.ctx.ntFileCacheApi.setCacheSilentScan(false)
|
await this.ctx.ntFileCacheApi.setCacheSilentScan(false)
|
||||||
|
|
||||||
cacheFilePaths.push(await this.ctx.ntFileCacheApi.getHotUpdateCachePath())
|
cacheFilePaths.push(await this.ctx.ntFileCacheApi.getHotUpdateCachePath())
|
||||||
cacheFilePaths.push(await this.ctx.ntFileCacheApi.getDesktopTmpPath())
|
cacheFilePaths.push(await this.ctx.ntFileCacheApi.getDesktopTmpPath())
|
||||||
|
|
||||||
const list = await this.ctx.ntFileCacheApi.getCacheSessionPathList()
|
const list = await this.ctx.ntFileCacheApi.getCacheSessionPathList()
|
||||||
list.forEach((e) => cacheFilePaths.push(e.value))
|
list.forEach((e) => cacheFilePaths.push(e.value))
|
||||||
|
|
||||||
// await NTQQApi.addCacheScannedPaths(); // XXX: 调用就崩溃,原因目前还未知
|
// await NTQQApi.addCacheScannedPaths(); // XXX: 调用就崩溃,原因目前还未知
|
||||||
const cacheScanResult = await this.ctx.ntFileCacheApi.scanCache()
|
const cacheScanResult = await this.ctx.ntFileCacheApi.scanCache()
|
||||||
const cacheSize = parseInt(cacheScanResult.size[6])
|
const cacheSize = parseInt(cacheScanResult.size[6])
|
||||||
|
|
||||||
if (cacheScanResult.result !== 0) {
|
if (cacheScanResult.result !== 0) {
|
||||||
throw 'Something went wrong while scanning cache. Code: ' + cacheScanResult.result
|
throw 'Something went wrong while scanning cache. Code: ' + cacheScanResult.result
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.ctx.ntFileCacheApi.setCacheSilentScan(true)
|
await this.ctx.ntFileCacheApi.setCacheSilentScan(true)
|
||||||
if (cacheSize > 0 && cacheFilePaths.length > 2) {
|
if (cacheSize > 0 && cacheFilePaths.length > 2) {
|
||||||
// 存在缓存文件且大小不为 0 时执行清理动作
|
// 存在缓存文件且大小不为 0 时执行清理动作
|
||||||
// await NTQQApi.clearCache([ 'tmp', 'hotUpdate', ...cacheScanResult ]) // XXX: 也是调用就崩溃,调用 fs 删除得了
|
// await NTQQApi.clearCache([ 'tmp', 'hotUpdate', ...cacheScanResult ]) // XXX: 也是调用就崩溃,调用 fs 删除得了
|
||||||
deleteCachePath(cacheFilePaths)
|
deleteCachePath(cacheFilePaths)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取聊天记录列表
|
// 获取聊天记录列表
|
||||||
// NOTE: 以防有人不需要删除聊天记录,暂时先注释掉,日后加个开关
|
// NOTE: 以防有人不需要删除聊天记录,暂时先注释掉,日后加个开关
|
||||||
// const privateChatCache = await getCacheList(ChatType.friend); // 私聊消息
|
// const privateChatCache = await getCacheList(ChatType.friend); // 私聊消息
|
||||||
// const groupChatCache = await getCacheList(ChatType.group); // 群聊消息
|
// const groupChatCache = await getCacheList(ChatType.group); // 群聊消息
|
||||||
// const chatCacheList = [ ...privateChatCache, ...groupChatCache ];
|
// const chatCacheList = [ ...privateChatCache, ...groupChatCache ];
|
||||||
const chatCacheList: ChatCacheListItemBasic[] = []
|
const chatCacheList: ChatCacheListItemBasic[] = []
|
||||||
|
|
||||||
// 获取聊天缓存文件列表
|
// 获取聊天缓存文件列表
|
||||||
const cacheFileList: string[] = []
|
const cacheFileList: string[] = []
|
||||||
|
|
||||||
for (const name in CacheFileType) {
|
for (const name in CacheFileType) {
|
||||||
if (!isNaN(parseInt(name))) continue
|
if (!isNaN(parseInt(name))) continue
|
||||||
|
|
||||||
const fileTypeAny: any = CacheFileType[name]
|
const fileType = CacheFileType[name] as unknown as CacheFileType
|
||||||
const fileType: CacheFileType = fileTypeAny
|
|
||||||
|
|
||||||
cacheFileList.push(...(await this.ctx.ntFileCacheApi.getFileCacheInfo(fileType)).infos.map((file) => file.fileKey))
|
cacheFileList.push(...(await this.ctx.ntFileCacheApi.getFileCacheInfo(fileType)).infos.map((file) => file.fileKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 一并清除
|
// 一并清除
|
||||||
await this.ctx.ntFileCacheApi.clearChatCache(chatCacheList, cacheFileList)
|
await this.ctx.ntFileCacheApi.clearChatCache(chatCacheList, cacheFileList)
|
||||||
res()
|
|
||||||
} catch (e) {
|
|
||||||
console.error('清理缓存时发生了错误')
|
|
||||||
rej(e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/onebot11/action/system/SetRestart.ts
Normal file
10
src/onebot11/action/system/SetRestart.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { BaseAction } from '@/onebot11/action/BaseAction'
|
||||||
|
import { ActionName } from '@/onebot11/action/types'
|
||||||
|
|
||||||
|
export class SetRestart extends BaseAction<null, void> {
|
||||||
|
actionName = ActionName.SetRestart
|
||||||
|
|
||||||
|
protected async _handle() {
|
||||||
|
await this.ctx.ntSystemApi.restart()
|
||||||
|
}
|
||||||
|
}
|
@@ -29,6 +29,10 @@ export enum ActionName {
|
|||||||
GetRobotUinRange = 'get_robot_uin_range',
|
GetRobotUinRange = 'get_robot_uin_range',
|
||||||
GroupPoke = 'group_poke',
|
GroupPoke = 'group_poke',
|
||||||
FriendPoke = 'friend_poke',
|
FriendPoke = 'friend_poke',
|
||||||
|
SetFriendRemark = 'set_friend_remark',
|
||||||
|
SetFriendCategory = 'set_friend_category',
|
||||||
|
SetGroupMsgMask = 'set_group_msg_mask',
|
||||||
|
SetGroupRemark = 'set_group_remark',
|
||||||
// onebot 11
|
// onebot 11
|
||||||
SendLike = 'send_like',
|
SendLike = 'send_like',
|
||||||
GetLoginInfo = 'get_login_info',
|
GetLoginInfo = 'get_login_info',
|
||||||
@@ -47,6 +51,7 @@ export enum ActionName {
|
|||||||
SetGroupLeave = 'set_group_leave',
|
SetGroupLeave = 'set_group_leave',
|
||||||
GetVersionInfo = 'get_version_info',
|
GetVersionInfo = 'get_version_info',
|
||||||
GetStatus = 'get_status',
|
GetStatus = 'get_status',
|
||||||
|
SetRestart = 'set_restart',
|
||||||
CanSendRecord = 'can_send_record',
|
CanSendRecord = 'can_send_record',
|
||||||
CanSendImage = 'can_send_image',
|
CanSendImage = 'can_send_image',
|
||||||
SetGroupKick = 'set_group_kick',
|
SetGroupKick = 'set_group_kick',
|
||||||
@@ -91,4 +96,6 @@ export enum ActionName {
|
|||||||
GoCQHTTP_DeleteFriend = 'delete_friend',
|
GoCQHTTP_DeleteFriend = 'delete_friend',
|
||||||
GoCQHTTP_OCRImage = 'ocr_image',
|
GoCQHTTP_OCRImage = 'ocr_image',
|
||||||
GoCQHTTP_GetGroupFileSystemInfo = 'get_group_file_system_info',
|
GoCQHTTP_GetGroupFileSystemInfo = 'get_group_file_system_info',
|
||||||
|
GoCQHTTP_SetGroupSpecialTitle = 'set_group_special_title',
|
||||||
|
GoCQHTTP_SendGroupSign = 'send_group_sign',
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,6 @@ import { OB11Config, Config as LLOBConfig } from '../common/types'
|
|||||||
import { OB11WebSocket, OB11WebSocketReverseManager } from './connect/ws'
|
import { OB11WebSocket, OB11WebSocketReverseManager } from './connect/ws'
|
||||||
import { OB11Http, OB11HttpPost } from './connect/http'
|
import { OB11Http, OB11HttpPost } from './connect/http'
|
||||||
import { OB11BaseEvent } from './event/OB11BaseEvent'
|
import { OB11BaseEvent } from './event/OB11BaseEvent'
|
||||||
import { OB11Message } from './types'
|
|
||||||
import { OB11BaseMetaEvent } from './event/meta/OB11BaseMetaEvent'
|
import { OB11BaseMetaEvent } from './event/meta/OB11BaseMetaEvent'
|
||||||
import { postHttpEvent } from './helper/eventForHttp'
|
import { postHttpEvent } from './helper/eventForHttp'
|
||||||
import { initActionMap } from './action'
|
import { initActionMap } from './action'
|
||||||
@@ -88,9 +87,9 @@ class OneBot11Adapter extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleGroupNotify(notify: GroupNotify) {
|
private async handleGroupNotify(notify: GroupNotify, doubt: boolean) {
|
||||||
try {
|
try {
|
||||||
const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type
|
const flag = `${notify.group.groupCode}|${notify.seq}|${notify.type}|${doubt === true ? '1' : '0'}`
|
||||||
if ([GroupNotifyType.MemberLeaveNotifyAdmin, GroupNotifyType.KickMemberNotifyAdmin].includes(notify.type)) {
|
if ([GroupNotifyType.MemberLeaveNotifyAdmin, GroupNotifyType.KickMemberNotifyAdmin].includes(notify.type)) {
|
||||||
if (notify.user2.uid) {
|
if (notify.user2.uid) {
|
||||||
this.ctx.logger.info('有群成员被踢', notify.group.groupCode, notify.user1.uid, notify.user2.uid)
|
this.ctx.logger.info('有群成员被踢', notify.group.groupCode, notify.user1.uid, notify.user2.uid)
|
||||||
@@ -338,7 +337,8 @@ class OneBot11Adapter extends Service {
|
|||||||
this.handleMsg(input)
|
this.handleMsg(input)
|
||||||
})
|
})
|
||||||
this.ctx.on('nt/group-notify', input => {
|
this.ctx.on('nt/group-notify', input => {
|
||||||
this.handleGroupNotify(input)
|
const { doubt, notify } = input
|
||||||
|
this.handleGroupNotify(notify, doubt)
|
||||||
})
|
})
|
||||||
this.ctx.on('nt/friend-request', input => {
|
this.ctx.on('nt/friend-request', input => {
|
||||||
this.handleFriendRequest(input)
|
this.handleFriendRequest(input)
|
||||||
@@ -370,12 +370,6 @@ class OneBot11Adapter extends Service {
|
|||||||
const userId = Number(memberUin)
|
const userId = Number(memberUin)
|
||||||
const event = new OB11GroupDecreaseEvent(tip.groupCode, userId, userId)
|
const event = new OB11GroupDecreaseEvent(tip.groupCode, userId, userId)
|
||||||
this.dispatch(event)
|
this.dispatch(event)
|
||||||
} else if (msgType === 87) {
|
|
||||||
const tip = SysMsg.GroupInvite.decode(sysMsg.body!.msgContent!)
|
|
||||||
this.ctx.logger.info('群成员增加', tip)
|
|
||||||
const operatorUin = await this.ctx.ntUserApi.getUinByUid(tip.operatorUid)
|
|
||||||
const event = new OB11GroupIncreaseEvent(tip.groupCode, +selfInfo.uin, +operatorUin, 'invite')
|
|
||||||
this.dispatch(event)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -478,6 +478,13 @@ export namespace OB11Entities {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (groupElement.type === TipGroupElementType.MemberIncrease) {
|
||||||
|
const { memberUid, adminUid } = groupElement
|
||||||
|
if (memberUid !== selfInfo.uid) return
|
||||||
|
ctx.logger.info('收到群成员增加消息', groupElement)
|
||||||
|
const adminUin = adminUid ? await ctx.ntUserApi.getUinByUid(adminUid) : selfInfo.uin
|
||||||
|
return new OB11GroupIncreaseEvent(+msg.peerUid, +selfInfo.uin, +adminUin)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (element.fileElement) {
|
else if (element.fileElement) {
|
||||||
return new OB11GroupUploadNoticeEvent(+msg.peerUid, +msg.senderUin!, {
|
return new OB11GroupUploadNoticeEvent(+msg.peerUid, +msg.senderUin!, {
|
||||||
@@ -520,7 +527,6 @@ export namespace OB11Entities {
|
|||||||
ctx.logger.info('收到新人被邀请进群消息', xmlElement)
|
ctx.logger.info('收到新人被邀请进群消息', xmlElement)
|
||||||
const invitor = xmlElement.templParam.get('invitor')
|
const invitor = xmlElement.templParam.get('invitor')
|
||||||
const invitee = xmlElement.templParam.get('invitee')
|
const invitee = xmlElement.templParam.get('invitee')
|
||||||
if (invitee === selfInfo.uin) return
|
|
||||||
if (invitor && invitee) {
|
if (invitor && invitee) {
|
||||||
return new OB11GroupIncreaseEvent(+msg.peerUid, +invitee, +invitor, 'invite')
|
return new OB11GroupIncreaseEvent(+msg.peerUid, +invitee, +invitor, 'invite')
|
||||||
}
|
}
|
||||||
|
@@ -174,7 +174,7 @@ export class MessageEncoder {
|
|||||||
const { type, data } = segment
|
const { type, data } = segment
|
||||||
if (type === OB11MessageDataType.Node) {
|
if (type === OB11MessageDataType.Node) {
|
||||||
await this.render(data.content as OB11MessageData[])
|
await this.render(data.content as OB11MessageData[])
|
||||||
const id = data.id ?? data.user_id
|
const id = data.uin ?? data.user_id
|
||||||
this.uin = id ? +id : undefined
|
this.uin = id ? +id : undefined
|
||||||
this.name = data.name ?? data.nickname
|
this.name = data.name ?? data.nickname
|
||||||
await this.flush()
|
await this.flush()
|
||||||
@@ -221,7 +221,7 @@ export class MessageEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(content: any[]) {
|
async generate(content: OB11MessageData[]) {
|
||||||
await this.render(content)
|
await this.render(content)
|
||||||
return {
|
return {
|
||||||
multiMsgItems: [{
|
multiMsgItems: [{
|
||||||
|
@@ -11,6 +11,10 @@ function isEmpty(value: unknown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function onSettingWindowCreated(view: Element) {
|
async function onSettingWindowCreated(view: Element) {
|
||||||
|
console.log(view)
|
||||||
|
if (!view){
|
||||||
|
return
|
||||||
|
}
|
||||||
const config = await window.llonebot.getConfig()
|
const config = await window.llonebot.getConfig()
|
||||||
const ob11Config = { ...config.ob11 }
|
const ob11Config = { ...config.ob11 }
|
||||||
|
|
||||||
@@ -247,7 +251,9 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
} else {
|
} else {
|
||||||
errDom?.classList.add('show')
|
errDom?.classList.add('show')
|
||||||
}
|
}
|
||||||
errCodeDom!.innerHTML = errMsg
|
if (errCodeDom) {
|
||||||
|
errCodeDom.innerHTML = errMsg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
showError().then()
|
showError().then()
|
||||||
|
|
||||||
@@ -456,8 +462,8 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
}
|
}
|
||||||
window.llonebot.checkVersion().then(checkVersionFunc)
|
window.llonebot.checkVersion().then(checkVersionFunc)
|
||||||
window.addEventListener('beforeunload', () => {
|
window.addEventListener('beforeunload', () => {
|
||||||
window.llonebot.getConfig().then(oldConfig=>{
|
window.llonebot.getConfig().then(oldConfig => {
|
||||||
if(JSON.stringify(oldConfig) !== JSON.stringify(config)){
|
if (JSON.stringify(oldConfig) !== JSON.stringify(config)) {
|
||||||
window.llonebot.setConfig(true, config)
|
window.llonebot.setConfig(true, config)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -91,7 +91,7 @@ class SatoriAdapter extends Service {
|
|||||||
input.subMsgType === 12 &&
|
input.subMsgType === 12 &&
|
||||||
input.elements[0]?.grayTipElement?.xmlElement?.templId === '10382'
|
input.elements[0]?.grayTipElement?.xmlElement?.templId === '10382'
|
||||||
) {
|
) {
|
||||||
|
// 机器人被表情回应
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 普通的消息
|
// 普通的消息
|
||||||
@@ -99,7 +99,7 @@ class SatoriAdapter extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleGroupNotify(input: NT.GroupNotify) {
|
async handleGroupNotify(input: NT.GroupNotify, doubt: boolean) {
|
||||||
if (
|
if (
|
||||||
input.type === NT.GroupNotifyType.InvitedByMember &&
|
input.type === NT.GroupNotifyType.InvitedByMember &&
|
||||||
input.status === NT.GroupNotifyStatus.Unhandle
|
input.status === NT.GroupNotifyStatus.Unhandle
|
||||||
@@ -119,14 +119,14 @@ class SatoriAdapter extends Service {
|
|||||||
input.status === NT.GroupNotifyStatus.Unhandle
|
input.status === NT.GroupNotifyStatus.Unhandle
|
||||||
) {
|
) {
|
||||||
// 他人主动申请,需管理员同意
|
// 他人主动申请,需管理员同意
|
||||||
return await parseGuildMemberRequest(this, input)
|
return await parseGuildMemberRequest(this, input, doubt)
|
||||||
}
|
}
|
||||||
else if (
|
else if (
|
||||||
input.type === NT.GroupNotifyType.InvitedNeedAdminiStratorPass &&
|
input.type === NT.GroupNotifyType.InvitedNeedAdminiStratorPass &&
|
||||||
input.status === NT.GroupNotifyStatus.Unhandle
|
input.status === NT.GroupNotifyStatus.Unhandle
|
||||||
) {
|
) {
|
||||||
// 他人被邀请,需管理员同意
|
// 他人被邀请,需管理员同意
|
||||||
return await parseGuildMemberRequest(this, input)
|
return await parseGuildMemberRequest(this, input, doubt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +140,8 @@ class SatoriAdapter extends Service {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.ctx.on('nt/group-notify', async input => {
|
this.ctx.on('nt/group-notify', async input => {
|
||||||
const event = await this.handleGroupNotify(input)
|
const { doubt, notify } = input
|
||||||
|
const event = await this.handleGroupNotify(notify, doubt)
|
||||||
.catch(e => this.ctx.logger.error(e))
|
.catch(e => this.ctx.logger.error(e))
|
||||||
event && this.server.dispatch(event)
|
event && this.server.dispatch(event)
|
||||||
})
|
})
|
||||||
|
@@ -46,9 +46,9 @@ export async function parseGuildMemberRemoved(bot: SatoriAdapter, input: GroupNo
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseGuildMemberRequest(bot: SatoriAdapter, input: GroupNotify) {
|
export async function parseGuildMemberRequest(bot: SatoriAdapter, input: GroupNotify, doubt: boolean) {
|
||||||
const groupCode = input.group.groupCode
|
const groupCode = input.group.groupCode
|
||||||
const flag = groupCode + '|' + input.seq + '|' + input.type
|
const flag = `${groupCode}|${input.seq}|${input.type}|${doubt === true ? '1' : '0'}`
|
||||||
|
|
||||||
return bot.event('guild-member-request', {
|
return bot.event('guild-member-request', {
|
||||||
guild: decodeGuild(input.group),
|
guild: decodeGuild(input.group),
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const version = '4.1.0'
|
export const version = '4.3.0'
|
||||||
|
Reference in New Issue
Block a user