Merge pull request #417 from LLOneBot/dev

release: 3.32.6
This commit is contained in:
idranme
2024-09-15 17:48:35 +08:00
committed by GitHub
82 changed files with 449 additions and 258 deletions

View File

@@ -4,7 +4,7 @@
"name": "LLOneBot",
"slug": "LLOneBot",
"description": "实现 OneBot 11 协议,用于 QQ 机器人开发",
"version": "3.32.5",
"version": "3.32.6",
"icon": "./icon.webp",
"authors": [
{

View File

@@ -41,7 +41,7 @@
"electron-vite": "^2.3.0",
"protobufjs-cli": "^1.1.3",
"typescript": "^5.6.2",
"vite": "^5.4.4",
"vite": "^5.4.5",
"vite-plugin-cp": "^4.0.8"
},
"packageManager": "yarn@4.4.1"

View File

@@ -33,7 +33,6 @@ export class ConfigUtil {
enableWsReverse: false,
messagePostFormat: 'array',
enableHttpHeart: false,
enableQOAutoQuote: false,
listenLocalhost: false
}
const defaultConfig: Config = {

View File

@@ -10,7 +10,11 @@ export interface OB11Config {
enableWsReverse?: boolean
messagePostFormat?: 'array' | 'string'
enableHttpHeart?: boolean
enableQOAutoQuote: boolean // 快速操作回复自动引用原消息
/**
* 快速操作回复自动引用原消息
* @deprecated
*/
enableQOAutoQuote?: boolean
listenLocalhost: boolean
}

View File

@@ -101,7 +101,7 @@ export async function encodeSilk(ctx: Context, filePath: string) {
type OutFormat = 'mp3' | 'amr' | 'wma' | 'm4a' | 'spx' | 'ogg' | 'wav' | 'flac'
export async function decodeSilk(ctx: Context, inputFilePath: string, outFormat: OutFormat = 'mp3') {
export async function decodeSilk(ctx: Context, inputFilePath: string, outFormat: OutFormat) {
const silk = await fsPromise.readFile(inputFilePath)
const { data } = await decode(silk, 24000)
const tmpPath = path.join(TEMP_DIR, path.basename(inputFilePath))
@@ -115,4 +115,4 @@ export async function decodeSilk(ctx: Context, inputFilePath: string, outFormat:
'-ac 1'
]
}, outFilePath)
}
}

View File

@@ -189,4 +189,9 @@ export class NTQQFriendApi extends Service {
return await invoke('nodeIKernelBuddyService/isBuddy', [{ uid }, null])
}
}
async getBuddyRecommendContact(uin: string) {
const ret = await invoke('nodeIKernelBuddyService/getBuddyRecommendContactArkJson', [{ uin }, null])
return ret.arkMsg
}
}

View File

@@ -117,17 +117,15 @@ export class NTQQGroupApi extends Service {
const type = parseInt(flagitem[2])
const session = getSession()
if (session) {
return session.getGroupService().operateSysNotify(
false,
{
'operateType': operateType, // 2 拒绝
'targetMsg': {
'seq': seq, // 通知序列号
'type': type,
'groupCode': groupCode,
'postscript': reason || ' ' // 仅传空值可能导致处理失败,故默认给个空格
}
})
return session.getGroupService().operateSysNotify(false, {
operateType, // 2 拒绝
targetMsg: {
seq, // 通知序列号
type,
groupCode,
postscript: reason || ' ' // 仅传空值可能导致处理失败,故默认给个空格
}
})
} else {
return await invoke(NTMethod.HANDLE_GROUP_REQUEST, [{
doubt: false,
@@ -265,8 +263,8 @@ export class NTQQGroupApi extends Service {
return await invoke('nodeIKernelRichMediaService/deleteGroupFolder', [{ groupId, folderId }, null])
}
async deleteGroupFile(groupId: string, fileIdList: string[]) {
return await invoke('nodeIKernelRichMediaService/deleteGroupFile', [{ groupId, busIdList: [102], fileIdList }, null])
async deleteGroupFile(groupId: string, fileIdList: string[], busIdList: number[]) {
return await invoke('nodeIKernelRichMediaService/deleteGroupFile', [{ groupId, busIdList, fileIdList }, null])
}
async getGroupFileList(groupId: string, fileListForm: GetFileListParam) {
@@ -300,4 +298,9 @@ export class NTQQGroupApi extends Service {
const psKey = (await ntUserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!
return await invoke('nodeIKernelGroupService/uploadGroupBulletinPic', [{ groupCode, psKey, path }, null])
}
async getGroupRecommendContact(groupCode: string) {
const ret = await invoke('nodeIKernelGroupService/getGroupRecommendContactArkJson', [{ groupCode }, null])
return ret.arkJson
}
}

View File

@@ -87,17 +87,6 @@ export class NTQQUserApi extends Service {
return result.info
}
async getSkey(): Promise<string> {
const clientKeyData = await this.forceFetchClientKey()
if (clientKeyData?.result !== 0) {
throw new Error('获取clientKey失败')
}
const url = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin
+ '&clientkey=' + clientKeyData.clientKey
+ '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=' + clientKeyData.keyIndex
return (await RequestUtil.HttpsGetCookies(url))?.skey
}
async getCookies(domain: string) {
const clientKeyData = await this.forceFetchClientKey()
if (clientKeyData?.result !== 0) {

View File

@@ -363,11 +363,63 @@ export namespace SysMsg {
public static getTypeUrl(typeUrlPrefix?: string): string;
}
/** Properties of a ProfileLikeSubTip. */
interface IProfileLikeSubTip {
/** ProfileLikeSubTip msg */
msg?: (SysMsg.ILikeMsg|null);
}
/** Represents a ProfileLikeSubTip. */
class ProfileLikeSubTip implements IProfileLikeSubTip {
/**
* Constructs a new ProfileLikeSubTip.
* @param [properties] Properties to set
*/
constructor(properties?: SysMsg.IProfileLikeSubTip);
/** ProfileLikeSubTip msg. */
public msg?: (SysMsg.ILikeMsg|null);
/**
* Decodes a ProfileLikeSubTip message from the specified reader or buffer.
* @param reader Reader or buffer to decode from
* @param [length] Message length if known beforehand
* @returns ProfileLikeSubTip
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): SysMsg.ProfileLikeSubTip;
/**
* Decodes a ProfileLikeSubTip message from the specified reader or buffer, length delimited.
* @param reader Reader or buffer to decode from
* @returns ProfileLikeSubTip
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): SysMsg.ProfileLikeSubTip;
/**
* Gets the default type url for ProfileLikeSubTip
* @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns The default type url
*/
public static getTypeUrl(typeUrlPrefix?: string): string;
}
/** Properties of a ProfileLikeTip. */
interface IProfileLikeTip {
/** ProfileLikeTip msg */
msg?: (SysMsg.ILikeMsg|null);
/** ProfileLikeTip msgType */
msgType?: (number|null);
/** ProfileLikeTip subType */
subType?: (number|null);
/** ProfileLikeTip content */
content?: (SysMsg.IProfileLikeSubTip|null);
}
/** Represents a ProfileLikeTip. */
@@ -379,8 +431,14 @@ export namespace SysMsg {
*/
constructor(properties?: SysMsg.IProfileLikeTip);
/** ProfileLikeTip msg. */
public msg?: (SysMsg.ILikeMsg|null);
/** ProfileLikeTip msgType. */
public msgType: number;
/** ProfileLikeTip subType. */
public subType: number;
/** ProfileLikeTip content. */
public content?: (SysMsg.IProfileLikeSubTip|null);
/**
* Decodes a ProfileLikeTip message from the specified reader or buffer.

View File

@@ -789,13 +789,111 @@ export const SysMsg = $root.SysMsg = (() => {
return LikeMsg;
})();
SysMsg.ProfileLikeSubTip = (function() {
/**
* Properties of a ProfileLikeSubTip.
* @memberof SysMsg
* @interface IProfileLikeSubTip
* @property {SysMsg.ILikeMsg|null} [msg] ProfileLikeSubTip msg
*/
/**
* Constructs a new ProfileLikeSubTip.
* @memberof SysMsg
* @classdesc Represents a ProfileLikeSubTip.
* @implements IProfileLikeSubTip
* @constructor
* @param {SysMsg.IProfileLikeSubTip=} [properties] Properties to set
*/
function ProfileLikeSubTip(properties) {
if (properties)
for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)
if (properties[keys[i]] != null)
this[keys[i]] = properties[keys[i]];
}
/**
* ProfileLikeSubTip msg.
* @member {SysMsg.ILikeMsg|null|undefined} msg
* @memberof SysMsg.ProfileLikeSubTip
* @instance
*/
ProfileLikeSubTip.prototype.msg = null;
/**
* Decodes a ProfileLikeSubTip message from the specified reader or buffer.
* @function decode
* @memberof SysMsg.ProfileLikeSubTip
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @param {number} [length] Message length if known beforehand
* @returns {SysMsg.ProfileLikeSubTip} ProfileLikeSubTip
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
ProfileLikeSubTip.decode = function decode(reader, length) {
if (!(reader instanceof $Reader))
reader = $Reader.create(reader);
let end = length === undefined ? reader.len : reader.pos + length, message = new $root.SysMsg.ProfileLikeSubTip();
while (reader.pos < end) {
let tag = reader.uint32();
switch (tag >>> 3) {
case 14: {
message.msg = $root.SysMsg.LikeMsg.decode(reader, reader.uint32());
break;
}
default:
reader.skipType(tag & 7);
break;
}
}
return message;
};
/**
* Decodes a ProfileLikeSubTip message from the specified reader or buffer, length delimited.
* @function decodeDelimited
* @memberof SysMsg.ProfileLikeSubTip
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @returns {SysMsg.ProfileLikeSubTip} ProfileLikeSubTip
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
ProfileLikeSubTip.decodeDelimited = function decodeDelimited(reader) {
if (!(reader instanceof $Reader))
reader = new $Reader(reader);
return this.decode(reader, reader.uint32());
};
/**
* Gets the default type url for ProfileLikeSubTip
* @function getTypeUrl
* @memberof SysMsg.ProfileLikeSubTip
* @static
* @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns {string} The default type url
*/
ProfileLikeSubTip.getTypeUrl = function getTypeUrl(typeUrlPrefix) {
if (typeUrlPrefix === undefined) {
typeUrlPrefix = "type.googleapis.com";
}
return typeUrlPrefix + "/SysMsg.ProfileLikeSubTip";
};
return ProfileLikeSubTip;
})();
SysMsg.ProfileLikeTip = (function() {
/**
* Properties of a ProfileLikeTip.
* @memberof SysMsg
* @interface IProfileLikeTip
* @property {SysMsg.ILikeMsg|null} [msg] ProfileLikeTip msg
* @property {number|null} [msgType] ProfileLikeTip msgType
* @property {number|null} [subType] ProfileLikeTip subType
* @property {SysMsg.IProfileLikeSubTip|null} [content] ProfileLikeTip content
*/
/**
@@ -814,12 +912,28 @@ export const SysMsg = $root.SysMsg = (() => {
}
/**
* ProfileLikeTip msg.
* @member {SysMsg.ILikeMsg|null|undefined} msg
* ProfileLikeTip msgType.
* @member {number} msgType
* @memberof SysMsg.ProfileLikeTip
* @instance
*/
ProfileLikeTip.prototype.msg = null;
ProfileLikeTip.prototype.msgType = 0;
/**
* ProfileLikeTip subType.
* @member {number} subType
* @memberof SysMsg.ProfileLikeTip
* @instance
*/
ProfileLikeTip.prototype.subType = 0;
/**
* ProfileLikeTip content.
* @member {SysMsg.IProfileLikeSubTip|null|undefined} content
* @memberof SysMsg.ProfileLikeTip
* @instance
*/
ProfileLikeTip.prototype.content = null;
/**
* Decodes a ProfileLikeTip message from the specified reader or buffer.
@@ -839,8 +953,16 @@ export const SysMsg = $root.SysMsg = (() => {
while (reader.pos < end) {
let tag = reader.uint32();
switch (tag >>> 3) {
case 14: {
message.msg = $root.SysMsg.LikeMsg.decode(reader, reader.uint32());
case 1: {
message.msgType = reader.uint32();
break;
}
case 2: {
message.subType = reader.uint32();
break;
}
case 203: {
message.content = $root.SysMsg.ProfileLikeSubTip.decode(reader, reader.uint32());
break;
}
default:

View File

@@ -2,17 +2,23 @@ syntax = "proto3";
package SysMsg;
message LikeDetail {
string txt = 1;
uint32 uin = 3;
string nickname = 5;
string txt = 1;
uint32 uin = 3;
string nickname = 5;
}
message LikeMsg {
uint32 count = 1;
uint32 time = 2;
LikeDetail detail = 3;
uint32 count = 1;
uint32 time = 2;
LikeDetail detail = 3;
}
message ProfileLikeSubTip {
LikeMsg msg = 14;
}
message ProfileLikeTip {
LikeMsg msg = 14;
}
uint32 msgType = 1;
uint32 subType = 2;
ProfileLikeSubTip content = 203;
}

View File

@@ -119,7 +119,7 @@ export interface NodeIKernelBuddyService {
reportDoubtBuddyReqUnread(): void
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<unknown>
getBuddyRecommendContactArkJson(uid: string, phoneNumber: string): Promise<GeneralCallResult & { arkMsg: string }>
isNull(): boolean
}
}

View File

@@ -52,7 +52,7 @@ export interface NodeIKernelGroupService {
//26702(其实更早 但是我不知道)
getGroupLatestEssenceList(groupCode: string): Promise<unknown>
//26702(其实更早 但是我不知道)
//26702(其实更早 但是我不知道)
shareDigest(Req: {
appId: string,
appType: number,
@@ -232,7 +232,7 @@ export interface NodeIKernelGroupService {
setMemberShutUp(groupCode: string, memberTimes: { uid: string, timeStamp: number }[]): Promise<void>
getGroupRecommendContactArkJson(groupCode: string): unknown
getGroupRecommendContactArkJson(groupCode: string): Promise<GeneralCallResult & { arkJson: string }>
getJoinGroupLink(groupCode: string): unknown
@@ -244,6 +244,7 @@ export interface NodeIKernelGroupService {
msgRandom: number,
msgSeq: number
}): Promise<unknown>
//需要提前判断是否存在 高版本新增
removeGroupEssence(param: {
groupCode: string
@@ -252,4 +253,4 @@ export interface NodeIKernelGroupService {
}): Promise<unknown>
isNull(): boolean
}
}

View File

@@ -1,44 +1,43 @@
import { ActionName, BaseCheckResult } from './types'
import { ActionName } from './types'
import { OB11Response } from './OB11Response'
import { OB11Return } from '../types'
import { Context } from 'cordis'
import { Context, Schema } from 'cordis'
import type Adapter from '../adapter'
abstract class BaseAction<PayloadType, ReturnDataType> {
abstract actionName: ActionName
protected ctx: Context
payloadSchema?: Schema<PayloadType>
constructor(protected adapter: Adapter) {
this.ctx = adapter.ctx
}
protected async check(payload: PayloadType): Promise<BaseCheckResult> {
return {
valid: true,
}
}
public async handle(payload: PayloadType): Promise<OB11Return<ReturnDataType | null>> {
const result = await this.check(payload)
if (!result.valid) {
return OB11Response.error(result.message, 400)
let params: PayloadType
try {
params = this.payloadSchema ? new this.payloadSchema(payload) : payload
} catch (e) {
return OB11Response.error((e as Error).message, 400)
}
try {
const resData = await this._handle(payload)
const resData = await this._handle(params)
return OB11Response.ok(resData)
} catch (e) {
this.ctx.logger.error('发生错误', e)
return OB11Response.error(e?.toString() || (e as Error)?.stack?.toString() || '未知错误,可能操作超时', 200)
return OB11Response.error((e as Error)?.toString() || (e as Error)?.stack?.toString() || '未知错误,可能操作超时', 200)
}
}
public async websocketHandle(payload: PayloadType, echo: unknown): Promise<OB11Return<ReturnDataType | null>> {
const result = await this.check(payload)
if (!result.valid) {
return OB11Response.error(result.message, 1400)
let params: PayloadType
try {
params = this.payloadSchema ? new this.payloadSchema(payload) : payload
} catch (e) {
return OB11Response.error((e as Error).message, 1400)
}
try {
const resData = await this._handle(payload)
const resData = await this._handle(params)
return OB11Response.ok(resData, echo)
} catch (e) {
this.ctx.logger.error('发生错误', e)
@@ -46,9 +45,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
}
}
protected async _handle(payload: PayloadType): Promise<ReturnDataType> {
throw `pleas override ${this.actionName} _handle`
}
protected abstract _handle(payload: PayloadType): Promise<ReturnDataType>
}
export default BaseAction
export { BaseAction, Schema }

View File

@@ -1,5 +1,5 @@
import BaseAction from '../BaseAction'
import fsPromise from 'node:fs/promises'
import { BaseAction, Schema } from '../BaseAction'
import { readFile } from 'node:fs/promises'
import { ActionName } from '../types'
import { Peer, ElementType } from '@/ntqqapi/types'
import { MessageUnique } from '@/common/utils/messageUnique'
@@ -17,13 +17,16 @@ export interface GetFileResponse {
}
export abstract class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
// forked from https://github.com/NapNeko/NapCatQQ/blob/6f6b258f22d7563f15d84e7172c4d4cbb547f47e/src/onebot11/action/file/GetFile.ts#L44
payloadSchema = Schema.object({
file: Schema.string().required()
})
protected async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
const { enableLocalFile2Url } = this.adapter.config
let fileCache = await MessageUnique.getFileCacheById(String(payload.file))
let fileCache = await MessageUnique.getFileCacheById(payload.file)
if (!fileCache?.length) {
fileCache = await MessageUnique.getFileCacheByName(String(payload.file))
fileCache = await MessageUnique.getFileCacheByName(payload.file)
}
if (fileCache?.length) {
@@ -62,7 +65,7 @@ export abstract class GetFileBase extends BaseAction<GetFilePayload, GetFileResp
}
if (enableLocalFile2Url && downloadPath && (res.file === res.url || res.url === undefined)) {
try {
res.base64 = await fsPromise.readFile(downloadPath, 'base64')
res.base64 = await readFile(downloadPath, 'base64')
} catch (e) {
throw new Error('文件下载失败. ' + e)
}
@@ -76,11 +79,12 @@ export abstract class GetFileBase extends BaseAction<GetFilePayload, GetFileResp
export default class GetFile extends GetFileBase {
actionName = ActionName.GetFile
payloadSchema = Schema.object({
file: Schema.string(),
file_id: Schema.string().required()
})
protected async _handle(payload: { file_id: string; file: string }): Promise<GetFileResponse> {
if (!payload.file_id) {
throw new Error('file_id 不能为空')
}
protected async _handle(payload: { file_id: string, file: string }): Promise<GetFileResponse> {
payload.file = payload.file_id
return super._handle(payload)
}

View File

@@ -3,11 +3,4 @@ import { ActionName } from '../types'
export default class GetImage extends GetFileBase {
actionName = ActionName.GetImage
protected async _handle(payload: { file: string }) {
if (!payload.file) {
throw new Error('参数 file 不能为空')
}
return super._handle(payload)
}
}

View File

@@ -1,8 +1,9 @@
import path from 'node:path'
import { GetFileBase, GetFilePayload, GetFileResponse } from './GetFile'
import { ActionName } from '../types'
import { decodeSilk } from '@/common/utils/audio'
import path from 'node:path'
import fs from 'node:fs'
import { Schema } from '../BaseAction'
import { stat, readFile } from 'node:fs/promises'
interface Payload extends GetFilePayload {
out_format: 'mp3' | 'amr' | 'wma' | 'm4a' | 'spx' | 'ogg' | 'wav' | 'flac'
@@ -10,14 +11,18 @@ interface Payload extends GetFilePayload {
export default class GetRecord extends GetFileBase {
actionName = ActionName.GetRecord
payloadSchema = Schema.object({
file: Schema.string().required(),
out_format: Schema.string().default('mp3')
})
protected async _handle(payload: Payload): Promise<GetFileResponse> {
const res = await super._handle(payload)
res.file = await decodeSilk(this.ctx, res.file!, payload.out_format)
res.file_name = path.basename(res.file)
res.file_size = fs.statSync(res.file).size.toString()
res.file_size = (await stat(res.file)).size.toString()
if (this.adapter.config.enableLocalFile2Url) {
res.base64 = fs.readFileSync(res.file, 'base64')
res.base64 = await readFile(res.file, 'base64')
}
return res
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {
@@ -9,9 +9,13 @@ interface Payload {
export class CreateGroupFileFolder extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_CreateGroupFileFolder
payloadSchema = Schema.object({
group_id: Schema.union([Number, String]).required(),
name: Schema.string().required(),
})
async _handle(payload: Payload) {
await this.ctx.ntGroupApi.createGroupFileFolder(payload.group_id.toString(), payload.name)
return null
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
import { MessageUnique } from '@/common/utils/messageUnique'
@@ -8,11 +8,11 @@ interface Payload {
export class DelEssenceMsg extends BaseAction<Payload, unknown> {
actionName = ActionName.GoCQHTTP_DelEssenceMsg
payloadSchema = Schema.object({
message_id: Schema.union([Number, String]).required()
})
protected async _handle(payload: Payload) {
if (!payload.message_id) {
throw Error('message_id不能为空')
}
const msg = await MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)
if (!msg) {
throw new Error('msg not found')

View File

@@ -1,17 +1,22 @@
import BaseAction from '../BaseAction'
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {
group_id: string | number
file_id: string
busid?: 102
busid: number
}
export class DelGroupFile extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_DelGroupFile
payloadSchema = Schema.object({
group_id: Schema.union([Number, String]).required(),
file_id: Schema.string().required(),
busid: Schema.number().default(102)
})
async _handle(payload: Payload) {
await this.ctx.ntGroupApi.deleteGroupFile(payload.group_id.toString(), [payload.file_id])
await this.ctx.ntGroupApi.deleteGroupFile(payload.group_id.toString(), [payload.file_id], [payload.busid])
return null
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {
@@ -8,9 +8,13 @@ interface Payload {
export class DelGroupFolder extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_DelGroupFolder
payloadSchema = Schema.object({
group_id: Schema.union([Number, String]).required(),
folder_id: Schema.string().required()
})
async _handle(payload: Payload) {
await this.ctx.ntGroupApi.deleteGroupFileFolder(payload.group_id.toString(), payload.folder_id)
return null
}
}
}

View File

@@ -1,7 +1,7 @@
import BaseAction from '../BaseAction'
import fs from 'fs'
import fsPromise from 'fs/promises'
import path from 'node:path'
import { BaseAction, Schema } from '../BaseAction'
import { ActionName } from '../types'
import { calculateFileMD5, fetchFile } from '@/common/utils'
import { TEMP_DIR } from '@/common/globalVars'
@@ -22,6 +22,11 @@ interface FileResponse {
export class DownloadFile extends BaseAction<Payload, FileResponse> {
actionName = ActionName.GoCQHTTP_DownloadFile
payloadSchema = Schema.object({
url: String,
base64: String,
headers: Schema.union([String, Schema.array(String)])
})
protected async _handle(payload: Payload): Promise<FileResponse> {
const isRandomName = !payload.name

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11ForwardMessage } from '../../types'
import { OB11Entities } from '../../entities'
import { ActionName } from '../types'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {
@@ -22,4 +22,4 @@ export class GetGroupAtAllRemain extends BaseAction<Payload, Response> {
remain_at_all_count_for_uin: data.atInfo.RemainAtAllCountForUin
}
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11Message } from '../../types'
import { ActionName } from '../types'
import { ChatType } from '@/ntqqapi/types'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { OB11GroupFile, OB11GroupFileFolder } from '../../types'
@@ -59,4 +59,4 @@ export class GetGroupRootFiles extends BaseAction<Payload, Response> {
})
}
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { GroupNotifyStatus } from '@/ntqqapi/types'
import { ActionName } from '../types'
@@ -56,4 +56,4 @@ export class GetGroupSystemMsg extends BaseAction<void, Response> {
}
return data
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11User } from '../../types'
import { OB11Entities } from '../../entities'
import { ActionName } from '../types'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { MessageUnique } from '@/common/utils/messageUnique'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { handleQuickOperation, QuickOperation, QuickOperationEvent } from '../../helper/quickOperation'
import { ActionName } from '../types'
@@ -13,4 +13,4 @@ export class HandleQuickOperation extends BaseAction<Payload, null> {
handleQuickOperation(this.ctx, payload.context, payload.operation).catch(e => this.ctx.logger.error(e))
return null
}
}
}

View File

@@ -1,14 +1,13 @@
import SendMsg from '../msg/SendMsg'
import { OB11PostSendMsg } from '../../types'
import { ActionName } from '../types'
import { convertMessage2List } from '../../helper/createMessage'
export class SendForwardMsg extends SendMsg {
actionName = ActionName.GoCQHTTP_SendForwardMsg
protected async check(payload: OB11PostSendMsg) {
if (payload.messages) payload.message = convertMessage2List(payload.messages)
return super.check(payload)
protected async _handle(payload: OB11PostSendMsg) {
if (payload.messages) payload.message = payload.messages
return super._handle(payload)
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { unlink } from 'fs/promises'
import { checkFileReceived, uri2local } from '@/common/utils/file'
@@ -15,7 +15,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_SendGroupNotice
async _handle(payload: Payload) {
if(!payload.content){
if (!payload.content) {
throw new Error('参数 content 不能为空')
}
const groupCode = payload.group_id.toString()
@@ -51,4 +51,4 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
}
return null
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { MessageUnique } from '@/common/utils/messageUnique'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { SendElementEntities } from '@/ntqqapi/entities'
import { uri2local } from '@/common/utils'

View File

@@ -1,5 +1,5 @@
import { GroupEssenceMsgRet } from '@/ntqqapi/api'
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface PayloadType {

View File

@@ -1,6 +1,6 @@
import { WebHonorType } from '@/ntqqapi/api'
import { ActionName } from '../types'
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
interface Payload {
group_id: number

View File

@@ -1,6 +1,6 @@
import { OB11Group } from '../../types'
import { OB11Entities } from '../../entities'
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,6 +1,6 @@
import { OB11Group } from '../../types'
import { OB11Entities } from '../../entities'
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11GroupMember } from '../../types'
import { OB11Entities } from '../../entities'
import { ActionName } from '../types'

View File

@@ -1,6 +1,6 @@
import { OB11GroupMember } from '../../types'
import { OB11Entities } from '../../entities'
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { selfInfo } from '@/common/globalVars'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
export default class GetGuildList extends BaseAction<null, null> {

View File

@@ -1,14 +1,14 @@
import SendMsg from '../msg/SendMsg'
import { ActionName, BaseCheckResult } from '../types'
import { ActionName } from '../types'
import { OB11PostSendMsg } from '../../types'
class SendGroupMsg extends SendMsg {
actionName = ActionName.SendGroupMsg
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
protected _handle(payload: OB11PostSendMsg) {
delete (payload as Partial<OB11PostSendMsg>).user_id
payload.message_type = 'group'
return super.check(payload)
return super._handle(payload)
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { GroupRequestOperateTypes } from '@/ntqqapi/types'
import { ActionName } from '../types'
@@ -14,9 +14,10 @@ export default class SetGroupAddRequest extends BaseAction<Payload, null> {
protected async _handle(payload: Payload): Promise<null> {
const flag = payload.flag.toString()
const approve = payload.approve?.toString() !== 'false'
await this.ctx.ntGroupApi.handleGroupRequest(flag,
await this.ctx.ntGroupApi.handleGroupRequest(
flag,
approve ? GroupRequestOperateTypes.approve : GroupRequestOperateTypes.reject,
payload.reason || ''
payload.reason
)
return null
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { GroupMemberRole } from '@/ntqqapi/types'
import { ActionName } from '../types'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -10,7 +10,7 @@ import SendGroupMsg from './group/SendGroupMsg'
import SendPrivateMsg from './msg/SendPrivateMsg'
import SendMsg from './msg/SendMsg'
import DeleteMsg from './msg/DeleteMsg'
import BaseAction from './BaseAction'
import { BaseAction } from './BaseAction'
import GetVersionInfo from './system/GetVersionInfo'
import CanSendRecord from './system/CanSendRecord'
import CanSendImage from './system/CanSendImage'
@@ -134,7 +134,7 @@ export function initActionMap(adapter: Adapter) {
new GetGroupRootFiles(adapter),
new SendGroupNotice(adapter)
]
const actionMap = new Map<string, BaseAction<unknown, unknown>>()
const actionMap = new Map<string, BaseAction<any, unknown>>()
for (const action of actionHandlers) {
actionMap.set(action.actionName, action)
actionMap.set(action.actionName + '_async', action)

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { Config } from '@/common/types'
import { ActionName } from '../types'
import { getConfigUtil } from '@/common/config'
@@ -13,7 +13,7 @@ export class GetConfigAction extends BaseAction<null, Config> {
export class SetConfigAction extends BaseAction<Config, void> {
actionName = ActionName.SetConfig
protected async _handle(payload: Config): Promise<void> {
getConfigUtil().setConfig(payload)
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { getHttpEvent } from '../../helper/eventForHttp'
import { OB11Message } from '../../types'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { GroupNotify, GroupNotifyStatus } from '@/ntqqapi/types'
import { ActionName } from '../types'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { selfInfo } from '@/common/globalVars'
import { Dict } from 'cosmokit'
@@ -14,4 +14,4 @@ export class GetProfileLike extends BaseAction<void, Dict[]> {
}
return listdata
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {
@@ -22,4 +22,4 @@ export class SetOnlineStatus extends BaseAction<Payload, null> {
}
return null
}
}
}

View File

@@ -1,6 +1,6 @@
import BaseAction from '../BaseAction'
import fs from 'node:fs'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import * as fs from 'node:fs'
import { checkFileReceived, uri2local } from '../../../common/utils/file'
interface Payload {

View File

@@ -1,5 +1,5 @@
import { ActionName } from '../types'
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { MessageUnique } from '@/common/utils/messageUnique'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ChatType } from '@/ntqqapi/types'
import { ActionName } from '../types'
import { Peer } from '@/ntqqapi/types'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11Message } from '../../types'
import { OB11Entities } from '../../entities'
import { ActionName } from '../types'

View File

@@ -14,8 +14,8 @@ import {
OB11PostSendMsg,
} from '../../types'
import fs from 'node:fs'
import BaseAction from '../BaseAction'
import { ActionName, BaseCheckResult } from '../types'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { CustomMusicSignPostData, IdMusicSignPostData, MusicSign, MusicSignPostData } from '@/common/utils/sign'
import { Peer } from '@/ntqqapi/types/msg'
import { MessageUnique } from '@/common/utils/messageUnique'
@@ -29,27 +29,6 @@ interface ReturnData {
export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnData> {
actionName = ActionName.SendMsg
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
const messages = convertMessage2List(payload.message)
const fmNum = this.getSpecialMsgNum(messages, OB11MessageDataType.node)
if (fmNum && fmNum != messages.length) {
return {
valid: false,
message: '转发消息不能和普通消息混在一起发送,转发需要保证message只有type为node的元素',
}
}
const musicNum = this.getSpecialMsgNum(messages, OB11MessageDataType.music)
if (musicNum && messages.length > 1) {
return {
valid: false,
message: '音乐消息不可以和其他消息混在一起发送',
}
}
return {
valid: true,
}
}
protected async _handle(payload: OB11PostSendMsg) {
let contextMode = CreatePeerMode.Normal
if (payload.message_type === 'group') {

View File

@@ -1,13 +1,13 @@
import SendMsg from './SendMsg'
import { ActionName, BaseCheckResult } from '../types'
import { ActionName } from '../types'
import { OB11PostSendMsg } from '../../types'
class SendPrivateMsg extends SendMsg {
actionName = ActionName.SendPrivateMsg
protected async check(payload: OB11PostSendMsg): Promise<BaseCheckResult> {
protected _handle(payload: OB11PostSendMsg) {
payload.message_type = 'private'
return super.check(payload)
return super._handle(payload)
}
}

View File

@@ -1,5 +1,5 @@
import { ActionName } from '../types'
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { MessageUnique } from '@/common/utils/messageUnique'
interface Payload {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface ReturnType {

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import fs from 'node:fs'
import Path from 'node:path'
@@ -82,4 +82,4 @@ function deleteCachePath(pathList: string[]) {
for (const path of pathList) {
emptyPath(path)
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11User } from '../../types'
import { ActionName } from '../types'
import { selfInfo } from '@/common/globalVars'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11Status } from '../../types'
import { ActionName } from '../types'
import { selfInfo } from '@/common/globalVars'

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11Version } from '../../types'
import { ActionName } from '../types'
import { version } from '../../../version'

View File

@@ -1,26 +1,26 @@
import BaseAction from '../BaseAction'
import { ActionName } from '../types'
interface Response {
cookies: string
bkn: string
}
interface Payload {
domain: string
}
export class GetCookies extends BaseAction<Payload, Response> {
actionName = ActionName.GetCookies
protected async _handle(payload: Payload) {
if (!payload.domain) {
throw '缺少参数 domain'
}
const cookiesObject = await this.ctx.ntUserApi.getCookies(payload.domain)
//把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起
const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; ')
const bkn = cookiesObject.skey ? this.ctx.ntWebApi.genBkn(cookiesObject.skey) : ''
return { cookies, bkn }
}
}
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Response {
cookies: string
bkn: string
}
interface Payload {
domain: string
}
export class GetCookies extends BaseAction<Payload, Response> {
actionName = ActionName.GetCookies
protected async _handle(payload: Payload) {
if (!payload.domain) {
throw '缺少参数 domain'
}
const cookiesObject = await this.ctx.ntUserApi.getCookies(payload.domain)
//把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起
const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; ')
const bkn = cookiesObject.skey ? this.ctx.ntWebApi.genBkn(cookiesObject.skey) : ''
return { cookies, bkn }
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { OB11User } from '../../types'
import { OB11Entities } from '../../entities'
import { ActionName } from '../types'
@@ -32,4 +32,4 @@ export class GetFriendWithCategory extends BaseAction<void, OB11User[]> {
throw new Error('this ntqq version not support, must be 26702 or later')
}
}
}
}

View File

@@ -1,4 +1,4 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
interface Payload {

View File

@@ -1,6 +1,5 @@
import BaseAction from '../BaseAction'
import { BaseAction } from '../BaseAction'
import { ActionName } from '../types'
import { NTQQFriendApi } from '../../../ntqqapi/api/friend'
interface Payload {
flag: string

View File

@@ -419,8 +419,9 @@ class OneBot11Adapter extends Service {
const sysMsg = SysMsg.SystemMessage.decode(input)
const { msgType, subType, subSubType } = sysMsg.msgSpec[0] ?? {}
if (msgType === 528 && subType === 39 && subSubType === 39) {
const tip = SysMsg.ProfileLikeTip.decode(sysMsg.bodyWrapper!.body!.slice(12))
const detail = tip.msg?.detail
const tip = SysMsg.ProfileLikeTip.decode(sysMsg.bodyWrapper!.body!)
if (tip.msgType !== 0 || tip.subType !== 203) return
const detail = tip.content?.msg?.detail
if (!detail) return
const [times] = detail.txt?.match(/\d+/) ?? ['0']
const profileLikeEvent = new OB11ProfileLikeEvent(detail.uin!, detail.nickname!, +times)

View File

@@ -1,8 +1,8 @@
import BaseAction from '../action/BaseAction'
import http from 'node:http'
import cors from 'cors'
import crypto from 'node:crypto'
import express, { Express, Request, Response } from 'express'
import { BaseAction } from '../action/BaseAction'
import { Context } from 'cordis'
import { llonebotError, selfInfo } from '@/common/globalVars'
import { OB11Response } from '../action/OB11Response'
@@ -211,4 +211,4 @@ namespace OB11HttpPost {
}
}
export { OB11Http, OB11HttpPost }
export { OB11Http, OB11HttpPost }

View File

@@ -1,4 +1,4 @@
import BaseAction from '../action/BaseAction'
import { BaseAction } from '../action/BaseAction'
import { Context } from 'cordis'
import { WebSocket, WebSocketServer } from 'ws'
import { llonebotError } from '@/common/globalVars'
@@ -339,4 +339,4 @@ namespace OB11WebSocketReverseManager {
}
}
export { OB11WebSocket, OB11WebSocketReverseManager }
export { OB11WebSocket, OB11WebSocketReverseManager }

View File

@@ -165,7 +165,7 @@ export namespace OB11Entities {
// 284840486: 合并消息内侧 消息具体定位不到
if (!replyMsg && msg.peerUin !== '284840486') {
ctx.logger.info('queryMsgs', msgList.map(e => pick(e, ['msgSeq', 'msgRandom'])))
ctx.logger.info('queryMsgs', msgList.map(e => pick(e, ['msgSeq', 'msgRandom'])), records.msgRandom)
throw new Error('回复消息验证失败')
}
messageSegment = {
@@ -394,7 +394,8 @@ export namespace OB11Entities {
}
// 好友增加事件
if (msg.msgType === 5 && msg.subMsgType === 12) {
const event = new OB11FriendAddNoticeEvent(parseInt(msg.peerUin))
const uin = +msg.peerUin || +(await ctx.ntUserApi.getUinByUid(msg.peerUid))
const event = new OB11FriendAddNoticeEvent(uin)
return event
}
}

View File

@@ -174,6 +174,12 @@ export async function createSendElements(
sendElements.push(SendElementEntities.rps(resultId))
}
break
case OB11MessageDataType.contact: {
const { type, id } = sendMsg.data
const data = type === 'qq' ? ctx.ntFriendApi.getBuddyRecommendContact(id) : ctx.ntGroupApi.getGroupRecommendContact(id)
sendElements.push(SendElementEntities.ark(await data))
}
break
}
}
@@ -301,4 +307,4 @@ export async function createPeer(ctx: Context, payload: CreatePeerPayload, mode:
}
}
throw new Error('请指定 group_id 或 user_id')
}
}

View File

@@ -1,4 +1,4 @@
import { OB11Message, OB11MessageAt, OB11MessageData, OB11MessageDataType } from '../types'
import { OB11Message, OB11MessageData, OB11MessageDataType } from '../types'
import { OB11FriendRequestEvent } from '../event/request/OB11FriendRequest'
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest'
import { GroupRequestOperateTypes } from '@/ntqqapi/types'
@@ -6,7 +6,6 @@ import { convertMessage2List, createSendElements, sendMsg, createPeer, CreatePee
import { MessageUnique } from '@/common/utils/messageUnique'
import { isNullable } from 'cosmokit'
import { Context } from 'cordis'
import { OB11Config } from '@/common/types'
interface QuickOperationPrivateMessage {
reply?: string
@@ -57,7 +56,6 @@ export async function handleQuickOperation(ctx: Context, event: QuickOperationEv
async function handleMsg(ctx: Context, msg: OB11Message, quickAction: QuickOperationPrivateMessage | QuickOperationGroupMessage) {
const reply = quickAction.reply
const ob11Config: OB11Config = ctx.config
let contextMode = CreatePeerMode.Normal
if (msg.message_type === 'group') {
contextMode = CreatePeerMode.Group
@@ -67,23 +65,21 @@ async function handleMsg(ctx: Context, msg: OB11Message, quickAction: QuickOpera
const peer = await createPeer(ctx, msg, contextMode)
if (reply) {
let replyMessage: OB11MessageData[] = []
if (ob11Config.enableQOAutoQuote) {
replyMessage.push({
type: OB11MessageDataType.reply,
data: {
id: msg.message_id.toString(),
},
})
}
replyMessage.push({
type: OB11MessageDataType.reply,
data: {
id: msg.message_id.toString(),
},
})
if (msg.message_type == 'group') {
if ((quickAction as QuickOperationGroupMessage).at_sender) {
replyMessage.push({
type: 'at',
type: OB11MessageDataType.at,
data: {
qq: msg.user_id.toString(),
},
} as OB11MessageAt)
})
}
}
replyMessage = replyMessage.concat(convertMessage2List(reply, quickAction.auto_escape))
@@ -130,4 +126,4 @@ async function handleGroupRequest(ctx: Context, request: OB11GroupRequestEvent,
quickAction.reason,
).catch(e => ctx.logger.error(e))
}
}
}

View File

@@ -130,6 +130,7 @@ export enum OB11MessageDataType {
poke = 'poke',
dice = 'dice',
RPS = 'rps',
contact = 'contact',
}
export interface OB11MessageMFace {
@@ -276,6 +277,14 @@ export interface OB11MessageForward {
}
}
export interface OB11MessageContact {
type: OB11MessageDataType.contact
data: {
type: 'qq' | 'group'
id: string
}
}
export type OB11MessageData =
| OB11MessageText
| OB11MessageFace
@@ -295,6 +304,7 @@ export type OB11MessageData =
| OB11MessageRPS
| OB11MessageMarkdown
| OB11MessageForward
| OB11MessageContact
export interface OB11PostSendMsg {
message_type?: 'private' | 'group'

View File

@@ -160,11 +160,6 @@ async function onSettingWindowCreated(view: Element) {
`<div class="q-input" style="width:210px;"><input class="q-input__inner" data-config-key="musicSignUrl" type="text" value="${config.musicSignUrl}" placeholder="未设置" /></div>`,
'config-musicSignUrl',
),
SettingItem(
'快速操作回复自动引用原消息',
null,
SettingSwitch('ob11.enableQOAutoQuote', config.ob11.enableQOAutoQuote),
),
SettingItem(
'HTTP、正向 WebSocket 服务仅监听 127.0.0.1',
'而不是 0.0.0.0',

View File

@@ -1 +1 @@
export const version = '3.32.5'
export const version = '3.32.6'