feat: go-cqhttp api get_stranger_info

feat: api send_like
fix: some image of message use base64 instead of http url
This commit is contained in:
linyuchen 2024-02-21 22:19:02 +08:00
parent 7664e746b4
commit 5044d24ee1
10 changed files with 108 additions and 18 deletions

View File

@ -4,7 +4,7 @@
"name": "LLOneBot", "name": "LLOneBot",
"slug": "LLOneBot", "slug": "LLOneBot",
"description": "LiteLoaderQQNT的OneBotApi", "description": "LiteLoaderQQNT的OneBotApi",
"version": "3.5.0", "version": "3.6.0",
"thumbnail": "./icon.png", "thumbnail": "./icon.png",
"authors": [ "authors": [
{ {

View File

@ -87,4 +87,4 @@ export function getUidByUin(uin: string) {
} }
} }
export const version = "v3.5.0" export const version = "v3.6.0"

View File

@ -17,7 +17,8 @@ export enum ReceiveCmd {
USER_INFO = "nodeIKernelProfileListener/onProfileSimpleChanged", USER_INFO = "nodeIKernelProfileListener/onProfileSimpleChanged",
GROUPS = "nodeIKernelGroupListener/onGroupListUpdate", GROUPS = "nodeIKernelGroupListener/onGroupListUpdate",
GROUPS_UNIX = "onGroupListUpdate", GROUPS_UNIX = "onGroupListUpdate",
FRIENDS = "onBuddyListChange" FRIENDS = "onBuddyListChange",
MEDIA_DOWNLOAD_COMPLETE = "nodeIKernelMsgListener/onRichMediaDownloadComplete"
} }
interface NTQQApiReturnData<PayloadType = unknown> extends Array<any> { interface NTQQApiReturnData<PayloadType = unknown> extends Array<any> {

View File

@ -3,7 +3,7 @@ import {hookApiCallbacks, ReceiveCmd, registerReceiveHook, removeReceiveHook} fr
import {log} from "../common/utils"; import {log} from "../common/utils";
import {ChatType, Friend, Group, GroupMember, RawMessage, SelfInfo, SendMessageElement, User} from "./types"; import {ChatType, Friend, Group, GroupMember, RawMessage, SelfInfo, SendMessageElement, User} from "./types";
import * as fs from "fs"; import * as fs from "fs";
import {addHistoryMsg, msgHistory, selfInfo, uidMaps} from "../common/data"; import {addHistoryMsg, msgHistory, selfInfo} from "../common/data";
import {v4 as uuidv4} from "uuid" import {v4 as uuidv4} from "uuid"
interface IPCReceiveEvent { interface IPCReceiveEvent {
@ -66,14 +66,16 @@ interface NTQQApiParams {
className?: NTQQApiClass, className?: NTQQApiClass,
channel?: NTQQApiChannel, channel?: NTQQApiChannel,
args?: unknown[], args?: unknown[],
cbCmd?: ReceiveCmd | null cbCmd?: ReceiveCmd | null,
cmdCB?: (payload: any) => boolean;
timeoutSecond?: number, timeoutSecond?: number,
} }
function callNTQQApi<ReturnType>(params: NTQQApiParams) { function callNTQQApi<ReturnType>(params: NTQQApiParams) {
let { let {
className, methodName, channel, args, className, methodName, channel, args,
cbCmd, timeoutSecond: timeout cbCmd, timeoutSecond: timeout,
cmdCB
} = params; } = params;
className = className ?? NTQQApiClass.NT_API; className = className ?? NTQQApiClass.NT_API;
channel = channel ?? NTQQApiChannel.IPC_UP_2; channel = channel ?? NTQQApiChannel.IPC_UP_2;
@ -95,12 +97,20 @@ function callNTQQApi<ReturnType>(params: NTQQApiParams) {
// 这里的callback比较特殊QQ后端先返回是否调用成功再返回一条结果数据 // 这里的callback比较特殊QQ后端先返回是否调用成功再返回一条结果数据
hookApiCallbacks[uuid] = (result: GeneralCallResult) => { hookApiCallbacks[uuid] = (result: GeneralCallResult) => {
log(`${methodName} callback`, result) log(`${methodName} callback`, result)
if (result.result == 0) { if (result?.result == 0 || result === undefined) {
const hookId = registerReceiveHook<ReturnType>(cbCmd, (payload) => { const hookId = registerReceiveHook<ReturnType>(cbCmd, (payload) => {
log(methodName, "second callback", cbCmd, payload); log(methodName, "second callback", cbCmd, payload);
removeReceiveHook(hookId); if (cmdCB) {
success = true if (cmdCB(payload)) {
resolve(payload); removeReceiveHook(hookId);
success = true
resolve(payload);
}
} else {
removeReceiveHook(hookId);
success = true
resolve(payload);
}
}) })
} else { } else {
success = true success = true
@ -138,7 +148,7 @@ interface GeneralCallResult {
export class NTQQApi { export class NTQQApi {
// static likeFriend = defineNTQQApi<void>(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.LIKE_FRIEND) // static likeFriend = defineNTQQApi<void>(NTQQApiChannel.IPC_UP_2, NTQQApiClass.NT_API, NTQQApiMethod.LIKE_FRIEND)
static likeFriend(uid: string, count = 1) { static likeFriend(uid: string, count = 1) {
return callNTQQApi({ return callNTQQApi<GeneralCallResult>({
methodName: NTQQApiMethod.LIKE_FRIEND, methodName: NTQQApiMethod.LIKE_FRIEND,
args: [{ args: [{
doLikeUserInfo: { doLikeUserInfo: {
@ -225,7 +235,7 @@ export class NTQQApi {
let values = result.result.infos.values() let values = result.result.infos.values()
let members = Array.from(values) as GroupMember[] let members = Array.from(values) as GroupMember[]
for(const member of members){ for (const member of members) {
// uidMaps[member.uid] = member.uin; // uidMaps[member.uid] = member.uin;
} }
// log(uidMaps); // log(uidMaps);
@ -328,7 +338,15 @@ export class NTQQApi {
}, },
undefined, undefined,
] ]
await callNTQQApi({methodName: NTQQApiMethod.DOWNLOAD_MEDIA, args: apiParams}) // log("需要下载media", sourcePath);
await callNTQQApi({
methodName: NTQQApiMethod.DOWNLOAD_MEDIA,
args: apiParams,
cbCmd: ReceiveCmd.MEDIA_DOWNLOAD_COMPLETE,
cmdCB:(payload: {notifyInfo: {filePath: string}})=>{
// log("media 下载完成判断", payload.notifyInfo.filePath, sourcePath);
return payload.notifyInfo.filePath == sourcePath;
}})
return sourcePath return sourcePath
} }
@ -341,7 +359,7 @@ export class NTQQApi {
}) })
} }
static sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = false, timeout=10000) { static sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = false, timeout = 10000) {
const sendTimeout = timeout const sendTimeout = timeout
return new Promise<RawMessage>((resolve, reject) => { return new Promise<RawMessage>((resolve, reject) => {

View File

@ -0,0 +1,31 @@
import BaseAction from "./BaseAction";
import {getFriend} from "../../common/data";
import {NTQQApi} from "../../ntqqapi/ntcall";
import {ActionName} from "./types";
import { log } from "../../common/utils";
interface Payload {
user_id: number,
times: number
}
export default class SendLike extends BaseAction<Payload, null> {
actionName = ActionName.SendLike
protected async _handle(payload: Payload): Promise<null> {
const qq = payload.user_id.toString();
const friend = await getFriend(qq)
if (!friend) {
throw (`点赞失败,${qq}不是好友`)
}
try {
let result = await NTQQApi.likeFriend(friend.uid, parseInt(payload.times.toString()) || 1);
if (result.result !== 0){
throw result.errMsg
}
} catch (e) {
throw `点赞失败 ${e}`
}
return null
}
}

View File

@ -0,0 +1,24 @@
import BaseAction from "../BaseAction";
import {OB11GroupMember, OB11User} from "../../types";
import {friends, getFriend, getGroupMember, groups} from "../../../common/data";
import {OB11Constructor} from "../../constructor";
import {ActionName} from "../types";
export default class GoCQHTTPGetStrangerInfo extends BaseAction<{user_id: number}, OB11User>{
actionName = ActionName.GoCQHTTP_GetStrangerInfo
protected async _handle(payload: { user_id: number }): Promise<OB11User> {
const user_id = payload.user_id.toString()
const friend = await getFriend(user_id)
if (friend){
return OB11Constructor.friend(friend);
}
for(const group of groups){
const member = await getGroupMember(group.groupCode, user_id)
if (member){
return OB11Constructor.groupMember(group.groupCode, member) as OB11User
}
}
throw ("查无此人")
}
}

View File

@ -15,8 +15,11 @@ import CanSendRecord from "./CanSendRecord";
import CanSendImage from "./CanSendImage"; import CanSendImage from "./CanSendImage";
import GetStatus from "./GetStatus"; import GetStatus from "./GetStatus";
import {GoCQHTTPSendGroupForwardMsg, GoCQHTTPSendPrivateForwardMsg} from "./go-cqhttp/SendForwardMsg"; import {GoCQHTTPSendGroupForwardMsg, GoCQHTTPSendPrivateForwardMsg} from "./go-cqhttp/SendForwardMsg";
import GoCQHTTPGetStrangerInfo from "./go-cqhttp/GetStrangerInfo";
import SendLike from "./SendLike";
export const actionHandlers = [ export const actionHandlers = [
new SendLike(),
new GetMsg(), new GetMsg(),
new GetLoginInfo(), new GetLoginInfo(),
new GetFriendList(), new GetFriendList(),
@ -31,6 +34,7 @@ export const actionHandlers = [
//以下为go-cqhttp api //以下为go-cqhttp api
new GoCQHTTPSendGroupForwardMsg(), new GoCQHTTPSendGroupForwardMsg(),
new GoCQHTTPSendPrivateForwardMsg(), new GoCQHTTPSendPrivateForwardMsg(),
new GoCQHTTPGetStrangerInfo()
] ]

View File

@ -13,6 +13,7 @@ export interface InvalidCheckResult {
export enum ActionName { export enum ActionName {
TestForwardMsg = "test_forward_msg", TestForwardMsg = "test_forward_msg",
SendLike = "send_like",
GetLoginInfo = "get_login_info", GetLoginInfo = "get_login_info",
GetFriendList = "get_friend_list", GetFriendList = "get_friend_list",
GetGroupInfo = "get_group_info", GetGroupInfo = "get_group_info",
@ -30,5 +31,6 @@ export enum ActionName {
CanSendImage = "can_send_image", CanSendImage = "can_send_image",
// 以下为go-cqhttp api // 以下为go-cqhttp api
GoCQHTTP_SendGroupForwardMsg = "send_group_forward_msg", GoCQHTTP_SendGroupForwardMsg = "send_group_forward_msg",
GoCQHTTP_SendPrivateForwardMsg = "send_private_forward_msg" GoCQHTTP_SendPrivateForwardMsg = "send_private_forward_msg",
GoCQHTTP_GetStrangerInfo = "get_stranger_info"
} }

View File

@ -7,7 +7,17 @@ import {
OB11MessageDataType, OB11MessageDataType,
OB11User OB11User
} from "./types"; } from "./types";
import {AtType, ChatType, Group, GroupMember, IMAGE_HTTP_HOST, RawMessage, SelfInfo, User} from '../ntqqapi/types'; import {
AtType,
ChatType,
Friend,
Group,
GroupMember,
IMAGE_HTTP_HOST,
RawMessage,
SelfInfo,
User
} from '../ntqqapi/types';
import {getFriend, getGroupMember, getHistoryMsgBySeq, selfInfo} from '../common/data'; import {getFriend, getGroupMember, getHistoryMsgBySeq, selfInfo} from '../common/data';
import {file2base64, getConfigUtil, log} from "../common/utils"; import {file2base64, getConfigUtil, log} from "../common/utils";
import {NTQQApi} from "../ntqqapi/ntcall"; import {NTQQApi} from "../ntqqapi/ntcall";
@ -131,7 +141,7 @@ export class OB11Constructor {
if (!enableLocalFile2Url) { if (!enableLocalFile2Url) {
message_data.data.file = "file://" + filePath message_data.data.file = "file://" + filePath
} else { // 不使用本地路径 } else { // 不使用本地路径
if (message_data.data.http_file) { if (message_data.data.http_file && !message_data.data.http_file.startsWith(IMAGE_HTTP_HOST + "/download")) {
message_data.data.file = message_data.data.http_file message_data.data.file = message_data.data.http_file
} else { } else {
let {err, data} = await file2base64(filePath); let {err, data} = await file2base64(filePath);

View File

@ -109,7 +109,7 @@ async function onSettingWindowCreated(view: Element) {
<setting-item data-direction="row" class="hostItem vertical-list-item"> <setting-item data-direction="row" class="hostItem vertical-list-item">
<div> <div>
<div></div> <div></div>
<div class="tips">http连接base64编码</div> <div class="tips">()http链接或base64编码</div>
</div> </div>
<setting-switch id="switchFileUrl" ${config.enableLocalFile2Url ? "is-active" : ""}></setting-switch> <setting-switch id="switchFileUrl" ${config.enableLocalFile2Url ? "is-active" : ""}></setting-switch>
</setting-item> </setting-item>