mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
@@ -4,7 +4,7 @@
|
|||||||
"name": "LLOneBot",
|
"name": "LLOneBot",
|
||||||
"slug": "LLOneBot",
|
"slug": "LLOneBot",
|
||||||
"description": "实现 OneBot 11 和 Satori 协议,用于 QQ 机器人开发",
|
"description": "实现 OneBot 11 和 Satori 协议,用于 QQ 机器人开发",
|
||||||
"version": "4.0.0",
|
"version": "4.0.1",
|
||||||
"icon": "./icon.webp",
|
"icon": "./icon.webp",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -62,9 +62,10 @@ class Store extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createMsgShortId(peer: Peer, msgId: string): number {
|
createMsgShortId(peer: Peer, msgId: string): number {
|
||||||
|
// OneBot 11 要求 message_id 为 int32
|
||||||
const cacheKey = `${msgId}|${peer.chatType}|${peer.peerUid}`
|
const cacheKey = `${msgId}|${peer.chatType}|${peer.peerUid}`
|
||||||
const hash = createHash('md5').update(cacheKey).digest()
|
const hash = createHash('md5').update(cacheKey).digest()
|
||||||
hash[0] &= 0x7f //设置第一个bit为0 保证shortId为正数
|
hash[0] &= 0x7f //保证shortId为正数
|
||||||
const shortId = hash.readInt32BE()
|
const shortId = hash.readInt32BE()
|
||||||
this.cache.set(cacheKey, shortId)
|
this.cache.set(cacheKey, shortId)
|
||||||
this.ctx.database.upsert('message', [{
|
this.ctx.database.upsert('message', [{
|
||||||
|
@@ -16,7 +16,7 @@ import path from 'node:path'
|
|||||||
import { existsSync } from 'node:fs'
|
import { existsSync } from 'node:fs'
|
||||||
import { ReceiveCmdS } from '../hook'
|
import { ReceiveCmdS } from '../hook'
|
||||||
import { RkeyManager } from '@/ntqqapi/helper/rkey'
|
import { RkeyManager } from '@/ntqqapi/helper/rkey'
|
||||||
import { OnRichMediaDownloadCompleteParams, Peer } from '@/ntqqapi/types/msg'
|
import { RichMediaDownloadCompleteNotify, Peer } from '@/ntqqapi/types/msg'
|
||||||
import { calculateFileMD5 } from '@/common/utils/file'
|
import { calculateFileMD5 } from '@/common/utils/file'
|
||||||
import { copyFile, stat, unlink } from 'node:fs/promises'
|
import { copyFile, stat, unlink } from 'node:fs/promises'
|
||||||
import { Time } from 'cosmokit'
|
import { Time } from 'cosmokit'
|
||||||
@@ -113,7 +113,7 @@ export class NTQQFileApi extends Service {
|
|||||||
return sourcePath
|
return sourcePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const data = await invoke<{ notifyInfo: OnRichMediaDownloadCompleteParams }>(
|
const data = await invoke<{ notifyInfo: RichMediaDownloadCompleteNotify }>(
|
||||||
'nodeIKernelMsgService/downloadRichMedia',
|
'nodeIKernelMsgService/downloadRichMedia',
|
||||||
[{
|
[{
|
||||||
getReq: {
|
getReq: {
|
||||||
@@ -185,7 +185,7 @@ export class NTQQFileApi extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async downloadFileForModelId(peer: Peer, fileModelId: string, timeout = 2 * Time.minute) {
|
async downloadFileForModelId(peer: Peer, fileModelId: string, timeout = 2 * Time.minute) {
|
||||||
const data = await invoke<{ notifyInfo: OnRichMediaDownloadCompleteParams }>(
|
const data = await invoke<{ notifyInfo: RichMediaDownloadCompleteNotify }>(
|
||||||
'nodeIKernelRichMediaService/downloadFileForModelId',
|
'nodeIKernelRichMediaService/downloadFileForModelId',
|
||||||
[{
|
[{
|
||||||
peer,
|
peer,
|
||||||
|
@@ -116,4 +116,14 @@ export class NTQQFriendApi extends Service {
|
|||||||
remarkParams: { uid, remark }
|
remarkParams: { uid, remark }
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async delBuddy(friendUid: string) {
|
||||||
|
return await invoke('nodeIKernelBuddyService/delBuddy', [{
|
||||||
|
delInfo: {
|
||||||
|
friendUid,
|
||||||
|
tempBlock: false,
|
||||||
|
tempBothDel: true
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,6 +37,7 @@ export class NTQQMsgApi extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async activateChatAndGetHistory(peer: Peer, cnt: number) {
|
async activateChatAndGetHistory(peer: Peer, cnt: number) {
|
||||||
|
// 消息从旧到新
|
||||||
return await invoke(NTMethod.ACTIVE_CHAT_HISTORY, [{ peer, cnt, msgId: '0', queryOrder: true }])
|
return await invoke(NTMethod.ACTIVE_CHAT_HISTORY, [{ peer, cnt, msgId: '0', queryOrder: true }])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -124,10 +124,15 @@ class Core extends Service {
|
|||||||
activatedPeerUids.push(contact.id)
|
activatedPeerUids.push(contact.id)
|
||||||
const peer = { peerUid: contact.id, chatType: contact.chatType }
|
const peer = { peerUid: contact.id, chatType: contact.chatType }
|
||||||
if (contact.chatType === ChatType.TempC2CFromGroup) {
|
if (contact.chatType === ChatType.TempC2CFromGroup) {
|
||||||
this.ctx.ntMsgApi.activateChatAndGetHistory(peer, 1).then(res => {
|
this.ctx.ntMsgApi.activateChatAndGetHistory(peer, 2).then(res => {
|
||||||
const lastTempMsg = res.msgList[0]
|
for (const msg of res.msgList) {
|
||||||
if (Date.now() / 1000 - Number(lastTempMsg?.msgTime) < 5) {
|
if (Date.now() / 1000 - Number(msg.msgTime) > 3) {
|
||||||
this.ctx.parallel('nt/message-created', lastTempMsg!)
|
continue
|
||||||
|
}
|
||||||
|
if (msg.senderUin && msg.senderUin !== '0') {
|
||||||
|
this.ctx.store.addMsgCache(msg)
|
||||||
|
}
|
||||||
|
this.ctx.parallel('nt/message-created', msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@@ -476,7 +476,7 @@ export interface MessageElement {
|
|||||||
actionBarElement?: unknown
|
actionBarElement?: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OnRichMediaDownloadCompleteParams {
|
export interface RichMediaDownloadCompleteNotify {
|
||||||
fileModelId: string
|
fileModelId: string
|
||||||
msgElementId: string
|
msgElementId: string
|
||||||
msgId: string
|
msgId: string
|
||||||
|
21
src/onebot11/action/go-cqhttp/DeleteFriend.ts
Normal file
21
src/onebot11/action/go-cqhttp/DeleteFriend.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { BaseAction, Schema } from '../BaseAction'
|
||||||
|
import { ActionName } from '../types'
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
user_id: number | string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DeleteFriend extends BaseAction<Payload, null> {
|
||||||
|
actionName = ActionName.GoCQHTTP_DeleteFriend
|
||||||
|
payloadSchema = Schema.object({
|
||||||
|
user_id: Schema.union([Number, String]).required()
|
||||||
|
})
|
||||||
|
|
||||||
|
protected async _handle(payload: Payload) {
|
||||||
|
const uin = payload.user_id.toString()
|
||||||
|
const uid = await this.ctx.ntUserApi.getUidByUin(uin)
|
||||||
|
if (!uid) throw new Error('无法获取用户信息')
|
||||||
|
await this.ctx.ntFriendApi.delBuddy(uid)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@@ -72,6 +72,7 @@ import { UploadPrivateFile } from './go-cqhttp/UploadPrivateFile'
|
|||||||
import { GetGroupFileUrl } from './go-cqhttp/GetGroupFileUrl'
|
import { GetGroupFileUrl } from './go-cqhttp/GetGroupFileUrl'
|
||||||
import { GetGroupNotice } from './go-cqhttp/GetGroupNotice'
|
import { GetGroupNotice } from './go-cqhttp/GetGroupNotice'
|
||||||
import { GetRobotUinRange } from './llonebot/GetRobotUinRange'
|
import { GetRobotUinRange } from './llonebot/GetRobotUinRange'
|
||||||
|
import { DeleteFriend } from './go-cqhttp/DeleteFriend'
|
||||||
|
|
||||||
export function initActionMap(adapter: Adapter) {
|
export function initActionMap(adapter: Adapter) {
|
||||||
const actionHandlers = [
|
const actionHandlers = [
|
||||||
@@ -149,6 +150,7 @@ export function initActionMap(adapter: Adapter) {
|
|||||||
new GetGroupFilesByFolder(adapter),
|
new GetGroupFilesByFolder(adapter),
|
||||||
new GetGroupFileUrl(adapter),
|
new GetGroupFileUrl(adapter),
|
||||||
new GetGroupNotice(adapter),
|
new GetGroupNotice(adapter),
|
||||||
|
new DeleteFriend(adapter),
|
||||||
]
|
]
|
||||||
const actionMap = new Map<string, BaseAction<any, unknown>>()
|
const actionMap = new Map<string, BaseAction<any, unknown>>()
|
||||||
for (const action of actionHandlers) {
|
for (const action of actionHandlers) {
|
||||||
|
@@ -85,4 +85,5 @@ export enum ActionName {
|
|||||||
GoCQHTTP_GetGroupFilesByFolder = 'get_group_files_by_folder',
|
GoCQHTTP_GetGroupFilesByFolder = 'get_group_files_by_folder',
|
||||||
GoCQHTTP_GetGroupFileUrl = 'get_group_file_url',
|
GoCQHTTP_GetGroupFileUrl = 'get_group_file_url',
|
||||||
GoCQHTTP_GetGroupNotice = '_get_group_notice',
|
GoCQHTTP_GetGroupNotice = '_get_group_notice',
|
||||||
|
GoCQHTTP_DeleteFriend = 'delete_friend',
|
||||||
}
|
}
|
||||||
|
@@ -33,13 +33,6 @@ function decodeMessageUser(data: NT.RawMessage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeMessageMember(user: Universal.User, data: NT.RawMessage) {
|
|
||||||
return {
|
|
||||||
user: user,
|
|
||||||
nick: data.sendMemberName || data.sendNickName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function decodeElement(ctx: Context, data: NT.RawMessage, quoted = false) {
|
async function decodeElement(ctx: Context, data: NT.RawMessage, quoted = false) {
|
||||||
const buffer: h[] = []
|
const buffer: h[] = []
|
||||||
for (const v of data.elements) {
|
for (const v of data.elements) {
|
||||||
@@ -169,12 +162,22 @@ export async function decodeMessage(
|
|||||||
message.user.nick = info.remark || info.nick
|
message.user.nick = info.remark || info.nick
|
||||||
}
|
}
|
||||||
if (guildId) {
|
if (guildId) {
|
||||||
|
let nick = data.sendMemberName || data.sendNickName
|
||||||
|
if (!data.sendNickName) {
|
||||||
|
const info = await ctx.ntGroupApi.getGroupMember(guildId, data.senderUid)
|
||||||
|
message.user.name = info.nick
|
||||||
|
message.user.nick = info.remark || info.nick
|
||||||
|
nick = info.cardName || info.nick
|
||||||
|
}
|
||||||
message.guild = {
|
message.guild = {
|
||||||
id: guildId,
|
id: guildId,
|
||||||
name: data.peerName,
|
name: data.peerName,
|
||||||
avatar: `https://p.qlogo.cn/gh/${guildId}/${guildId}/640`
|
avatar: `https://p.qlogo.cn/gh/${guildId}/${guildId}/640`
|
||||||
}
|
}
|
||||||
message.member = decodeMessageMember(message.user, data)
|
message.member = {
|
||||||
|
user: message.user,
|
||||||
|
nick
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const version = '4.0.0'
|
export const version = '4.0.1'
|
||||||
|
Reference in New Issue
Block a user