mirror of
https://github.com/LLOneBot/LLOneBot.git
synced 2024-11-22 01:56:33 +00:00
Merge branch 'dev'
This commit is contained in:
commit
e276d0e4f8
@ -3,5 +3,5 @@ export const CHANNEL_SET_CONFIG = 'llonebot_set_config'
|
||||
export const CHANNEL_LOG = 'llonebot_log'
|
||||
export const CHANNEL_ERROR = 'llonebot_error'
|
||||
export const CHANNEL_UPDATE = 'llonebot_update'
|
||||
export const CHANNEL_CHECKVERSION = 'llonebot_checkversion'
|
||||
export const CHANNEL_CHECK_VERSION = 'llonebot_check_version'
|
||||
export const CHANNEL_SELECT_FILE = 'llonebot_select_ffmpeg'
|
||||
|
@ -6,7 +6,7 @@ import path from "node:path";
|
||||
import {selfInfo} from "./data";
|
||||
import {DATA_DIR} from "./utils";
|
||||
|
||||
export const HOOK_LOG = true;
|
||||
export const HOOK_LOG = false;
|
||||
|
||||
export const ALLOW_SEND_TEMP_MSG = false;
|
||||
|
||||
|
@ -6,11 +6,12 @@ import util from "util";
|
||||
import {encode, getDuration, isWav} from "silk-wasm";
|
||||
import path from "node:path";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import {DATA_DIR, log, TEMP_DIR} from "./index";
|
||||
import {checkFfmpeg, DATA_DIR, log, TEMP_DIR} from "./index";
|
||||
import {getConfigUtil} from "../config";
|
||||
import {dbUtil} from "../db";
|
||||
import * as fileType from "file-type";
|
||||
import {net} from "electron";
|
||||
import config from "../../../electron.vite.config";
|
||||
|
||||
|
||||
export function isGIF(path: string) {
|
||||
@ -66,28 +67,6 @@ export async function file2base64(path: string) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function checkFfmpeg(newPath: string = null): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
log("开始检查ffmpeg", newPath);
|
||||
if (newPath) {
|
||||
ffmpeg.setFfmpegPath(newPath);
|
||||
}
|
||||
try {
|
||||
ffmpeg.getAvailableFormats((err, formats) => {
|
||||
if (err) {
|
||||
log('ffmpeg is not installed or not found in PATH:', err);
|
||||
resolve(false)
|
||||
} else {
|
||||
log('ffmpeg is installed.');
|
||||
resolve(true);
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function encodeSilk(filePath: string) {
|
||||
const fsp = require("fs").promises
|
||||
|
||||
|
@ -13,4 +13,5 @@ export const PLUGIN_DIR = global.LiteLoader.plugins["LLOneBot"].path.plugin;
|
||||
if (!fs.existsSync(TEMP_DIR)) {
|
||||
fs.mkdirSync(TEMP_DIR);
|
||||
}
|
||||
export {getVideoInfo} from "./video";
|
||||
export {getVideoInfo} from "./video";
|
||||
export {checkFfmpeg} from "./video";
|
@ -1,24 +1,29 @@
|
||||
import {version} from "../../version";
|
||||
import { version } from "../../version";
|
||||
import * as path from "node:path";
|
||||
import * as fs from "node:fs";
|
||||
import {copyFolder, httpDownload, log, PLUGIN_DIR, TEMP_DIR} from ".";
|
||||
import { copyFolder, httpDownload, log, PLUGIN_DIR, TEMP_DIR } from ".";
|
||||
import compressing from "compressing";
|
||||
|
||||
|
||||
const downloadMirrorHosts = ["https://mirror.ghproxy.com/"];
|
||||
const checkVersionMirrorHosts = ["https://521github.com"];
|
||||
|
||||
export async function checkVersion() {
|
||||
export async function checkNewVersion() {
|
||||
const latestVersionText = await getRemoteVersion();
|
||||
const latestVersion = latestVersionText.split(".");
|
||||
log("llonebot last version", latestVersion);
|
||||
const currentVersion = version.split(".");
|
||||
for (let k in [0, 1, 2]) {
|
||||
if (latestVersion[k] > currentVersion[k]) {
|
||||
return {result: false, version: latestVersionText};
|
||||
const currentVersion: string[] = version.split(".");
|
||||
log("llonebot current version", currentVersion);
|
||||
for (let k of [0, 1, 2]) {
|
||||
if (parseInt(latestVersion[k]) > parseInt(currentVersion[k])) {
|
||||
log("")
|
||||
return { result: true, version: latestVersionText };
|
||||
}
|
||||
else if (parseInt(latestVersion[k]) < parseInt(currentVersion[k])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {result: true, version: version};
|
||||
return { result: false, version: version };
|
||||
}
|
||||
|
||||
export async function upgradeLLOneBot() {
|
||||
@ -28,17 +33,17 @@ export async function upgradeLLOneBot() {
|
||||
const filePath = path.join(TEMP_DIR, "./update-" + latestVersion + ".zip");
|
||||
let downloadSuccess = false;
|
||||
// 多镜像下载
|
||||
for(const mirrorGithub of downloadMirrorHosts){
|
||||
try{
|
||||
for (const mirrorGithub of downloadMirrorHosts) {
|
||||
try {
|
||||
const buffer = await httpDownload(mirrorGithub + downloadUrl);
|
||||
fs.writeFileSync(filePath, buffer)
|
||||
downloadSuccess = true;
|
||||
break;
|
||||
}catch (e) {
|
||||
} catch (e) {
|
||||
log("llonebot upgrade error", e);
|
||||
}
|
||||
}
|
||||
if (!downloadSuccess){
|
||||
if (!downloadSuccess) {
|
||||
log("llonebot upgrade error", "download failed");
|
||||
return false;
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -7,7 +7,7 @@ import {
|
||||
CHANNEL_ERROR,
|
||||
CHANNEL_GET_CONFIG,
|
||||
CHANNEL_LOG,
|
||||
CHANNEL_CHECKVERSION,
|
||||
CHANNEL_CHECK_VERSION,
|
||||
CHANNEL_SELECT_FILE,
|
||||
CHANNEL_SET_CONFIG,
|
||||
CHANNEL_UPDATE,
|
||||
@ -41,10 +41,10 @@ import {NTQQUserApi} from "../ntqqapi/api/user";
|
||||
import {NTQQGroupApi} from "../ntqqapi/api/group";
|
||||
import {registerPokeHandler} from "../ntqqapi/external/ccpoke";
|
||||
import {OB11FriendPokeEvent, OB11GroupPokeEvent} from "../onebot11/event/notice/OB11PokeEvent";
|
||||
import {checkVersion, upgradeLLOneBot} from "../common/utils/upgrade";
|
||||
import {checkFfmpeg} from "../common/utils/file";
|
||||
import {checkNewVersion, upgradeLLOneBot} from "../common/utils/upgrade";
|
||||
import {log} from "../common/utils/log";
|
||||
import {getConfigUtil} from "../common/config";
|
||||
import {checkFfmpeg} from "../common/utils/video";
|
||||
|
||||
|
||||
let running = false;
|
||||
@ -53,8 +53,8 @@ let running = false;
|
||||
// 加载插件时触发
|
||||
function onLoad() {
|
||||
log("llonebot main onLoad");
|
||||
ipcMain.handle(CHANNEL_CHECKVERSION, async (event, arg) => {
|
||||
return checkVersion();
|
||||
ipcMain.handle(CHANNEL_CHECK_VERSION, async (event, arg) => {
|
||||
return checkNewVersion();
|
||||
});
|
||||
ipcMain.handle(CHANNEL_UPDATE, async (event, arg) => {
|
||||
return upgradeLLOneBot();
|
||||
|
@ -4,6 +4,7 @@ import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer";
|
||||
import {ob11ReverseWebsockets} from "../onebot11/server/ws/ReverseWebsocket";
|
||||
import {llonebotError} from "../common/data";
|
||||
import {getConfigUtil} from "../common/config";
|
||||
import {checkFfmpeg} from "../common/utils";
|
||||
|
||||
export async function setConfig(config: Config) {
|
||||
let oldConfig = getConfigUtil().getConfig();
|
||||
@ -51,4 +52,5 @@ export async function setConfig(config: Config) {
|
||||
}
|
||||
}
|
||||
}
|
||||
checkFfmpeg(config.ffmpeg).then()
|
||||
}
|
@ -5,6 +5,7 @@ import {uidMaps} from "../../common/data";
|
||||
import {BrowserWindow} from "electron";
|
||||
import {dbUtil} from "../../common/db";
|
||||
import {log} from "../../common/utils/log";
|
||||
import {NTQQWindowApi, NTQQWindows} from "./window";
|
||||
|
||||
export class NTQQGroupApi{
|
||||
static async getGroups(forced = false) {
|
||||
@ -74,25 +75,7 @@ export class NTQQGroupApi{
|
||||
}
|
||||
static async getGroupIgnoreNotifies() {
|
||||
await NTQQGroupApi.getGroupNotifies();
|
||||
const result = callNTQQApi<GroupNotifies>({
|
||||
className: NTQQApiClass.WINDOW_API,
|
||||
methodName: NTQQApiMethod.OPEN_EXTRA_WINDOW,
|
||||
cbCmd: ReceiveCmdS.GROUP_NOTIFY,
|
||||
afterFirstCmd: false,
|
||||
args: [
|
||||
"GroupNotifyFilterWindow"
|
||||
]
|
||||
})
|
||||
// 关闭窗口
|
||||
setTimeout(() => {
|
||||
for (const w of BrowserWindow.getAllWindows()) {
|
||||
// log("close window", w.webContents.getURL())
|
||||
if (w.webContents.getURL().indexOf("#/notify-filter/") != -1) {
|
||||
w.close();
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
return result;
|
||||
return await NTQQWindowApi.openWindow(NTQQWindows.GroupNotifyFilterWindow,[], ReceiveCmdS.GROUP_NOTIFY);
|
||||
}
|
||||
static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) {
|
||||
const notify: GroupNotify = await dbUtil.getGroupNotify(seq)
|
||||
|
7
src/ntqqapi/api/index.ts
Normal file
7
src/ntqqapi/api/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from "./file";
|
||||
export * from "./friend";
|
||||
export * from "./group";
|
||||
export * from "./msg";
|
||||
export * from "./user";
|
||||
export * from "./webapi";
|
||||
export * from "./window";
|
@ -53,5 +53,4 @@ export class NTQQUserApi{
|
||||
return info
|
||||
}
|
||||
|
||||
|
||||
}
|
87
src/ntqqapi/api/webapi.ts
Normal file
87
src/ntqqapi/api/webapi.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import {net, session} from "electron";
|
||||
import {NTQQApi} from "../ntcall";
|
||||
import {groups} from "../../common/data";
|
||||
import {log} from "../../common/utils";
|
||||
|
||||
export class WebApi{
|
||||
private static bkn: string;
|
||||
private static skey: string;
|
||||
private static pskey: string;
|
||||
private static cookie: string
|
||||
private defaultHeaders: Record<string,string> = {
|
||||
"User-Agent": "QQ/8.9.28.635 CFNetwork/1312 Darwin/21.0.0"
|
||||
}
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
public async addGroupDigest(groupCode: string, msgSeq: string){
|
||||
const url = `https://qun.qq.com/cgi-bin/group_digest/cancel_digest?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&msg_seq=${msgSeq}&msg_random=444021292`
|
||||
const res = await this.request(url)
|
||||
return await res.json()
|
||||
}
|
||||
|
||||
public async getGroupDigest(groupCode: string){
|
||||
const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&page_start=0&page_limit=20`
|
||||
const res = await this.request(url)
|
||||
log(res.headers)
|
||||
return await res.json()
|
||||
}
|
||||
|
||||
private genBkn(sKey: string){
|
||||
sKey = sKey || "";
|
||||
let hash = 5381;
|
||||
|
||||
for (let i = 0; i < sKey.length; i++) {
|
||||
const code = sKey.charCodeAt(i);
|
||||
hash = hash + (hash << 5) + code;
|
||||
}
|
||||
|
||||
return (hash & 0x7FFFFFFF).toString();
|
||||
}
|
||||
private async init(){
|
||||
if (!WebApi.bkn) {
|
||||
const group = groups[0];
|
||||
WebApi.skey = (await NTQQApi.getSkey(group.groupName, group.groupCode)).data;
|
||||
WebApi.bkn = this.genBkn(WebApi.skey);
|
||||
let cookie = await NTQQApi.getPSkey();
|
||||
const pskeyRegex = /p_skey=([^;]+)/;
|
||||
const match = cookie.match(pskeyRegex);
|
||||
const pskeyValue = match ? match[1] : null;
|
||||
WebApi.pskey = pskeyValue;
|
||||
if (cookie.indexOf("skey=;") !== -1) {
|
||||
cookie = cookie.replace("skey=;", `skey=${WebApi.skey};`);
|
||||
}
|
||||
WebApi.cookie = cookie;
|
||||
// for(const kv of WebApi.cookie.split(";")){
|
||||
// const [key, value] = kv.split("=");
|
||||
// }
|
||||
// log("set cookie", key, value)
|
||||
// await session.defaultSession.cookies.set({
|
||||
// url: 'https://qun.qq.com', // 你要请求的域名
|
||||
// name: key.trim(),
|
||||
// value: value.trim(),
|
||||
// expirationDate: Date.now() / 1000 + 300000, // Cookie 过期时间,例如设置为当前时间之后的300秒
|
||||
// });
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private async request(url: string, method: "GET" | "POST" = "GET", headers: Record<string, string> = {}){
|
||||
|
||||
await this.init();
|
||||
url += "&bkn=" + WebApi.bkn;
|
||||
let _headers: Record<string, string> = {
|
||||
...this.defaultHeaders, ...headers,
|
||||
"Cookie": WebApi.cookie,
|
||||
credentials: 'include'
|
||||
}
|
||||
log("request", url, _headers)
|
||||
const options = {
|
||||
method: method,
|
||||
headers: _headers
|
||||
}
|
||||
return fetch(url, options)
|
||||
}
|
||||
}
|
49
src/ntqqapi/api/window.ts
Normal file
49
src/ntqqapi/api/window.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import {callNTQQApi, GeneralCallResult, NTQQApiClass, NTQQApiMethod} from "../ntcall";
|
||||
import {ReceiveCmd} from "../hook";
|
||||
import {BrowserWindow} from "electron";
|
||||
|
||||
export interface NTQQWindow{
|
||||
windowName: string,
|
||||
windowUrlHash: string,
|
||||
}
|
||||
|
||||
export class NTQQWindows{
|
||||
static GroupHomeWorkWindow: NTQQWindow = {
|
||||
windowName: "GroupHomeWorkWindow",
|
||||
windowUrlHash: "#/group-home-work"
|
||||
}
|
||||
static GroupNotifyFilterWindow: NTQQWindow = {
|
||||
windowName: "GroupNotifyFilterWindow",
|
||||
windowUrlHash: "#/group-notify-filter"
|
||||
}
|
||||
static GroupEssenceWindow: NTQQWindow = {
|
||||
windowName: "GroupEssenceWindow",
|
||||
windowUrlHash: "#/group-essence"
|
||||
}
|
||||
}
|
||||
|
||||
export class NTQQWindowApi{
|
||||
|
||||
// 打开窗口并获取对应的下发事件
|
||||
static async openWindow<R=GeneralCallResult>(ntQQWindow: NTQQWindow, args: any[], cbCmd: ReceiveCmd=null, autoCloseSeconds: number=2){
|
||||
const result = await callNTQQApi<R>({
|
||||
className: NTQQApiClass.WINDOW_API,
|
||||
methodName: NTQQApiMethod.OPEN_EXTRA_WINDOW,
|
||||
cbCmd,
|
||||
afterFirstCmd: false,
|
||||
args: [
|
||||
ntQQWindow.windowName,
|
||||
...args
|
||||
]
|
||||
})
|
||||
setTimeout(() => {
|
||||
for (const w of BrowserWindow.getAllWindows()) {
|
||||
// log("close window", w.webContents.getURL())
|
||||
if (w.webContents.getURL().indexOf(ntQQWindow.windowUrlHash) != -1) {
|
||||
w.close();
|
||||
}
|
||||
}
|
||||
}, autoCloseSeconds * 1000);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ export let ReceiveCmdS = {
|
||||
SELF_STATUS: 'nodeIKernelProfileListener/onSelfStatusChanged',
|
||||
CACHE_SCAN_FINISH: "nodeIKernelStorageCleanListener/onFinishScan",
|
||||
MEDIA_UPLOAD_COMPLETE: "nodeIKernelMsgListener/onRichMediaUploadComplete",
|
||||
SKEY_UPDATE: "onSkeyUpdate"
|
||||
}
|
||||
|
||||
export type ReceiveCmd = typeof ReceiveCmdS[keyof typeof ReceiveCmdS]
|
||||
@ -60,45 +61,56 @@ let receiveHooks: Array<{
|
||||
export function hookNTQQApiReceive(window: BrowserWindow) {
|
||||
const originalSend = window.webContents.send;
|
||||
const patchSend = (channel: string, ...args: NTQQApiReturnData) => {
|
||||
// console.log("hookNTQQApiReceive", channel, args)
|
||||
let isLogger = false
|
||||
try {
|
||||
if (!args[0]?.eventName?.startsWith("ns-LoggerApi")) {
|
||||
HOOK_LOG && log(`received ntqq api message: ${channel}`, JSON.stringify(args))
|
||||
}
|
||||
isLogger = args[0]?.eventName?.startsWith("ns-LoggerApi")
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
if (args?.[1] instanceof Array) {
|
||||
for (let receiveData of args?.[1]) {
|
||||
const ntQQApiMethodName = receiveData.cmdName;
|
||||
// log(`received ntqq api message: ${channel} ${ntQQApiMethodName}`, JSON.stringify(receiveData))
|
||||
for (let hook of receiveHooks) {
|
||||
if (hook.method.includes(ntQQApiMethodName)) {
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
let _ = hook.hookFunc(receiveData.payload)
|
||||
if (hook.hookFunc.constructor.name === "AsyncFunction") {
|
||||
(_ as Promise<void>).then()
|
||||
if (!isLogger) {
|
||||
try {
|
||||
HOOK_LOG && log(`received ntqq api message: ${channel}`, args)
|
||||
}catch (e) {
|
||||
log("hook log error", e, args)
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (args?.[1] instanceof Array) {
|
||||
for (let receiveData of args?.[1]) {
|
||||
const ntQQApiMethodName = receiveData.cmdName;
|
||||
// log(`received ntqq api message: ${channel} ${ntQQApiMethodName}`, JSON.stringify(receiveData))
|
||||
for (let hook of receiveHooks) {
|
||||
if (hook.method.includes(ntQQApiMethodName)) {
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
let _ = hook.hookFunc(receiveData.payload)
|
||||
if (hook.hookFunc.constructor.name === "AsyncFunction") {
|
||||
(_ as Promise<void>).then()
|
||||
}
|
||||
} catch (e) {
|
||||
log("hook error", e, receiveData.payload)
|
||||
}
|
||||
} catch (e) {
|
||||
log("hook error", e, receiveData.payload)
|
||||
}
|
||||
}).then()
|
||||
}).then()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (args[0]?.callbackId) {
|
||||
// log("hookApiCallback", hookApiCallbacks, args)
|
||||
const callbackId = args[0].callbackId;
|
||||
if (hookApiCallbacks[callbackId]) {
|
||||
// log("callback found")
|
||||
new Promise((resolve, reject) => {
|
||||
hookApiCallbacks[callbackId](args[1]);
|
||||
}).then()
|
||||
delete hookApiCallbacks[callbackId];
|
||||
if (args[0]?.callbackId) {
|
||||
// log("hookApiCallback", hookApiCallbacks, args)
|
||||
const callbackId = args[0].callbackId;
|
||||
if (hookApiCallbacks[callbackId]) {
|
||||
// log("callback found")
|
||||
new Promise((resolve, reject) => {
|
||||
hookApiCallbacks[callbackId](args[1]);
|
||||
}).then()
|
||||
delete hookApiCallbacks[callbackId];
|
||||
}
|
||||
}
|
||||
}catch (e) {
|
||||
log("hookNTQQApiReceive error", e.stack.toString(), args)
|
||||
}
|
||||
return originalSend.call(window.webContents, channel, ...args);
|
||||
originalSend.call(window.webContents, channel, ...args);
|
||||
}
|
||||
window.webContents.send = patchSend;
|
||||
}
|
||||
@ -110,12 +122,19 @@ export function hookNTQQApiCall(window: BrowserWindow) {
|
||||
|
||||
const proxyIpcMsg = new Proxy(ipc_message_proxy, {
|
||||
apply(target, thisArg, args) {
|
||||
// console.log(thisArg, args);
|
||||
let isLogger = false
|
||||
try {
|
||||
if (args[3][1][0] !== "info") {
|
||||
HOOK_LOG && log("call NTQQ api", thisArg, args);
|
||||
}
|
||||
isLogger = args[3][0].eventName.startsWith("ns-LoggerApi")
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
if (!isLogger) {
|
||||
try{
|
||||
HOOK_LOG && log("call NTQQ api", thisArg, args);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
return target.apply(thisArg, args);
|
||||
},
|
||||
@ -137,7 +156,11 @@ export function hookNTQQApiCall(window: BrowserWindow) {
|
||||
}
|
||||
});
|
||||
let ret = target.apply(thisArg, args);
|
||||
HOOK_LOG && log("call NTQQ invoke api return", ret)
|
||||
try {
|
||||
HOOK_LOG && log("call NTQQ invoke api return", ret)
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
|
@ -1,8 +1,11 @@
|
||||
import {ipcMain} from "electron";
|
||||
import {hookApiCallbacks, ReceiveCmd, registerReceiveHook, removeReceiveHook} from "./hook";
|
||||
import {hookApiCallbacks, ReceiveCmd, ReceiveCmdS, registerReceiveHook, removeReceiveHook} from "./hook";
|
||||
|
||||
import {v4 as uuidv4} from "uuid"
|
||||
import {log} from "../common/utils/log";
|
||||
import {NTQQWindow, NTQQWindowApi, NTQQWindows} from "./api/window";
|
||||
import {WebApi} from "./api/webapi";
|
||||
import {HOOK_LOG} from "../common/config";
|
||||
|
||||
export enum NTQQApiClass {
|
||||
NT_API = "ns-ntApi",
|
||||
@ -11,7 +14,10 @@ export enum NTQQApiClass {
|
||||
WINDOW_API = "ns-WindowApi",
|
||||
HOTUPDATE_API = "ns-HotUpdateApi",
|
||||
BUSINESS_API = "ns-BusinessApi",
|
||||
GLOBAL_DATA = "ns-GlobalDataApi"
|
||||
GLOBAL_DATA = "ns-GlobalDataApi",
|
||||
SKEY_API = "ns-SkeyApi",
|
||||
GROUP_HOME_WORK = "ns-GroupHomeWork",
|
||||
GROUP_ESSENCE = "ns-GroupEssence",
|
||||
}
|
||||
|
||||
export enum NTQQApiMethod {
|
||||
@ -65,7 +71,9 @@ export enum NTQQApiMethod {
|
||||
|
||||
OPEN_EXTRA_WINDOW = 'openExternalWindow',
|
||||
|
||||
SET_QQ_AVATAR = 'nodeIKernelProfileService/setHeader'
|
||||
SET_QQ_AVATAR = 'nodeIKernelProfileService/setHeader',
|
||||
GET_SKEY = "nodeIKernelTipOffService/getPskey",
|
||||
UPDATE_SKEY = "updatePskey"
|
||||
}
|
||||
|
||||
enum NTQQApiChannel {
|
||||
@ -98,7 +106,7 @@ export function callNTQQApi<ReturnType>(params: NTQQApiParams) {
|
||||
timeout = timeout ?? 5;
|
||||
afterFirstCmd = afterFirstCmd ?? true;
|
||||
const uuid = uuidv4();
|
||||
// log("callNTQQApi", channel, className, methodName, args, uuid)
|
||||
HOOK_LOG && log("callNTQQApi", channel, className, methodName, args, uuid)
|
||||
return new Promise((resolve: (data: ReturnType) => void, reject) => {
|
||||
// log("callNTQQApiPromise", channel, className, methodName, args, uuid)
|
||||
const _timeout = timeout * 1000
|
||||
@ -178,4 +186,58 @@ export class NTQQApi {
|
||||
})
|
||||
}
|
||||
|
||||
static async getSkey(groupName: string, groupCode: string): Promise<{data: string}> {
|
||||
return await NTQQWindowApi.openWindow<{data: string}>(NTQQWindows.GroupHomeWorkWindow, [{
|
||||
groupName,
|
||||
groupCode,
|
||||
"source": "funcbar"
|
||||
}], ReceiveCmdS.SKEY_UPDATE, 1);
|
||||
// return await callNTQQApi<string>({
|
||||
// className: NTQQApiClass.GROUP_HOME_WORK,
|
||||
// methodName: NTQQApiMethod.UPDATE_SKEY,
|
||||
// args: [
|
||||
// {
|
||||
// domain: "qun.qq.com"
|
||||
// }
|
||||
// ]
|
||||
// })
|
||||
// return await callNTQQApi<GeneralCallResult>({
|
||||
// methodName: NTQQApiMethod.GET_SKEY,
|
||||
// args: [
|
||||
// {
|
||||
// "domains": [
|
||||
// "qzone.qq.com",
|
||||
// "qlive.qq.com",
|
||||
// "qun.qq.com",
|
||||
// "gamecenter.qq.com",
|
||||
// "vip.qq.com",
|
||||
// "qianbao.qq.com",
|
||||
// "qidian.qq.com"
|
||||
// ],
|
||||
// "isForNewPCQQ": false
|
||||
// },
|
||||
// null
|
||||
// ]
|
||||
// })
|
||||
}
|
||||
|
||||
static async getPSkey() {
|
||||
return await callNTQQApi<string>({
|
||||
className: NTQQApiClass.GROUP_HOME_WORK,
|
||||
methodName: NTQQApiMethod.UPDATE_SKEY,
|
||||
args: [
|
||||
{
|
||||
domain: "qun.qq.com"
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
static async addGroupDigest(groupCode: string, msgSeq: string) {
|
||||
return await new WebApi().addGroupDigest(groupCode, msgSeq);
|
||||
}
|
||||
|
||||
static async getGroupDigest(groupCode: string) {
|
||||
return await new WebApi().getGroupDigest(groupCode);
|
||||
}
|
||||
}
|
@ -18,7 +18,54 @@ export interface User {
|
||||
longNick?: string; // 签名
|
||||
remark?: string;
|
||||
sex?: Sex;
|
||||
"qqLevel"?: QQLevel
|
||||
qqLevel?: QQLevel,
|
||||
qid?: string
|
||||
"birthday_year"?: number,
|
||||
"birthday_month"?: number,
|
||||
"birthday_day"?: number,
|
||||
"topTime"?: string,
|
||||
"constellation"?: number,
|
||||
"shengXiao"?: number,
|
||||
"kBloodType"?: number,
|
||||
"homeTown"?: string, //"0-0-0",
|
||||
"makeFriendCareer"?: number,
|
||||
"pos"?: string,
|
||||
"eMail"?: string
|
||||
"phoneNum"?: string,
|
||||
"college"?: string,
|
||||
"country"?: string,
|
||||
"province"?: string,
|
||||
"city"?: string,
|
||||
"postCode"?: string,
|
||||
"address"?: string,
|
||||
"isBlock"?: boolean,
|
||||
"isSpecialCareOpen"?: boolean,
|
||||
"isSpecialCareZone"?: boolean,
|
||||
"ringId"?: string,
|
||||
"regTime"?: number,
|
||||
interest?: string,
|
||||
"labels"?: string[],
|
||||
"isHideQQLevel"?: number,
|
||||
"privilegeIcon"?: {
|
||||
"jumpUrl": string,
|
||||
"openIconList": unknown[],
|
||||
"closeIconList": unknown[]
|
||||
},
|
||||
"photoWall"?: {
|
||||
"picList": unknown[]
|
||||
},
|
||||
"vipFlag"?: boolean,
|
||||
"yearVipFlag"?: boolean,
|
||||
"svipFlag"?: boolean,
|
||||
"vipLevel"?: number,
|
||||
"status"?: number,
|
||||
"qidianMasterFlag"?: number,
|
||||
"qidianCrewFlag"?: number,
|
||||
"qidianCrewFlag2"?: number,
|
||||
"extStatus"?: number,
|
||||
"recommendImgFlag"?: number,
|
||||
"disableEmojiShortCuts"?: number,
|
||||
"pendantId"?: string,
|
||||
}
|
||||
|
||||
export interface SelfInfo extends User {
|
||||
|
@ -1,29 +0,0 @@
|
||||
import BaseAction from "./BaseAction";
|
||||
import {NTQQApi} from "../../ntqqapi/ntcall";
|
||||
import {ActionName} from "./types";
|
||||
|
||||
import {log} from "../../common/utils/log";
|
||||
|
||||
interface Payload {
|
||||
method: string,
|
||||
args: any[],
|
||||
}
|
||||
|
||||
export default class Debug extends BaseAction<Payload, any> {
|
||||
actionName = ActionName.Debug
|
||||
|
||||
protected async _handle(payload: Payload): Promise<any> {
|
||||
log("debug call ntqq api", payload);
|
||||
const method = NTQQApi[payload.method]
|
||||
if (!method) {
|
||||
throw `${method} 不存在`
|
||||
}
|
||||
const result = method(...payload.args);
|
||||
if (method.constructor.name === "AsyncFunction") {
|
||||
return await result
|
||||
}
|
||||
return result
|
||||
// const info = await NTQQApi.getUserDetailInfo(friends[0].uid);
|
||||
// return info
|
||||
}
|
||||
}
|
@ -1,36 +1,20 @@
|
||||
import BaseAction from "../BaseAction";
|
||||
import {OB11User} from "../../types";
|
||||
import {getFriend, getGroupMember, groups} from "../../../common/data";
|
||||
import {getUidByUin, uidMaps} from "../../../common/data";
|
||||
import {OB11Constructor} from "../../constructor";
|
||||
import {ActionName} from "../types";
|
||||
import {isNull, log} from "../../../common/utils";
|
||||
import {NTQQUserApi} from "../../../ntqqapi/api/user";
|
||||
import {Friend, GroupMember} from "../../../ntqqapi/types";
|
||||
|
||||
|
||||
export default class GoCQHTTPGetStrangerInfo extends BaseAction<{ user_id: number }, OB11User> {
|
||||
actionName = ActionName.GoCQHTTP_GetStrangerInfo
|
||||
|
||||
private async refreshInfo(user: Friend | GroupMember){
|
||||
if (isNull(user.sex)){
|
||||
let info = (await NTQQUserApi.getUserDetailInfo(user.uid))
|
||||
Object.assign(user, info);
|
||||
}
|
||||
}
|
||||
protected async _handle(payload: { user_id: number }): Promise<OB11User> {
|
||||
const user_id = payload.user_id.toString()
|
||||
const friend = await getFriend(user_id)
|
||||
if (friend) {
|
||||
await this.refreshInfo(friend);
|
||||
return OB11Constructor.friend(friend);
|
||||
const uid = getUidByUin(user_id)
|
||||
if (!uid) {
|
||||
throw new Error("查无此人")
|
||||
}
|
||||
for (const group of groups) {
|
||||
const member = await getGroupMember(group.groupCode, user_id)
|
||||
if (member) {
|
||||
await this.refreshInfo(member);
|
||||
return OB11Constructor.groupMember(group.groupCode, member) as OB11User
|
||||
}
|
||||
}
|
||||
throw new Error("查无此人")
|
||||
return OB11Constructor.stranger(await NTQQUserApi.getUserDetailInfo(uid))
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ import SendLike from "./SendLike";
|
||||
import SetGroupAddRequest from "./SetGroupAddRequest";
|
||||
import SetGroupLeave from "./SetGroupLeave";
|
||||
import GetGuildList from "./GetGuildList";
|
||||
import Debug from "./Debug";
|
||||
import Debug from "./llonebot/Debug";
|
||||
import SetFriendAddRequest from "./SetFriendAddRequest";
|
||||
import SetGroupWholeBan from "./SetGroupWholeBan";
|
||||
import SetGroupName from "./SetGroupName";
|
||||
|
31
src/onebot11/action/llonebot/Debug.ts
Normal file
31
src/onebot11/action/llonebot/Debug.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import BaseAction from "../BaseAction";
|
||||
import * as ntqqApi from "../../../ntqqapi/api";
|
||||
import {ActionName} from "../types";
|
||||
import {log} from "../../../common/utils/log";
|
||||
|
||||
interface Payload {
|
||||
method: string,
|
||||
args: any[],
|
||||
}
|
||||
|
||||
export default class Debug extends BaseAction<Payload, any> {
|
||||
actionName = ActionName.Debug
|
||||
|
||||
protected async _handle(payload: Payload): Promise<any> {
|
||||
log("debug call ntqq api", payload);
|
||||
for (const ntqqApiClass in ntqqApi) {
|
||||
const method = ntqqApi[ntqqApiClass][payload.method]
|
||||
if (method) {
|
||||
const result = method(...payload.args);
|
||||
if (method.constructor.name === "AsyncFunction") {
|
||||
return await result
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
throw `${payload.method}方法 不存在`
|
||||
|
||||
// const info = await NTQQApi.getUserDetailInfo(friends[0].uid);
|
||||
// return info
|
||||
}
|
||||
}
|
@ -311,14 +311,14 @@ export class OB11Constructor {
|
||||
nickname: friend.nick,
|
||||
remark: friend.remark,
|
||||
sex: OB11Constructor.sex(friend.sex),
|
||||
qq_level: friend.qqLevel && calcQQLevel(friend.qqLevel) || 0
|
||||
level: friend.qqLevel && calcQQLevel(friend.qqLevel) || 0
|
||||
}
|
||||
}
|
||||
|
||||
static selfInfo(selfInfo: SelfInfo): OB11User {
|
||||
return {
|
||||
user_id: parseInt(selfInfo.uin),
|
||||
nickname: selfInfo.nick
|
||||
nickname: selfInfo.nick,
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,6 +365,19 @@ export class OB11Constructor {
|
||||
}
|
||||
}
|
||||
|
||||
static stranger(user: User): OB11User {
|
||||
return {
|
||||
...user,
|
||||
user_id: parseInt(user.uin),
|
||||
nickname: user.nick,
|
||||
sex: OB11Constructor.sex(user.sex),
|
||||
age: 0,
|
||||
qid: user.qid,
|
||||
login_days: 0,
|
||||
level: user.qqLevel && calcQQLevel(user.qqLevel) || 0,
|
||||
}
|
||||
}
|
||||
|
||||
static groupMembers(group: Group): OB11GroupMember[] {
|
||||
log("construct ob11 group members", group)
|
||||
return group.members.map(m => OB11Constructor.groupMember(group.groupCode, m))
|
||||
|
@ -6,7 +6,10 @@ export interface OB11User {
|
||||
nickname: string;
|
||||
remark?: string;
|
||||
sex?: OB11UserSex;
|
||||
qq_level?: number;
|
||||
level?: number;
|
||||
age?: number;
|
||||
qid?: string;
|
||||
login_days?: number;
|
||||
}
|
||||
|
||||
export enum OB11UserSex {
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
CHANNEL_ERROR,
|
||||
CHANNEL_GET_CONFIG,
|
||||
CHANNEL_LOG,
|
||||
CHANNEL_CHECKVERSION,
|
||||
CHANNEL_CHECK_VERSION,
|
||||
CHANNEL_SELECT_FILE,
|
||||
CHANNEL_SET_CONFIG,
|
||||
CHANNEL_UPDATE,
|
||||
@ -19,7 +19,7 @@ const llonebot = {
|
||||
ipcRenderer.send(CHANNEL_LOG, data);
|
||||
},
|
||||
checkVersion:async (): Promise<CheckVersion> => {
|
||||
return ipcRenderer.invoke(CHANNEL_CHECKVERSION);
|
||||
return ipcRenderer.invoke(CHANNEL_CHECK_VERSION);
|
||||
},
|
||||
updateLLOneBot:async (): Promise<boolean> => {
|
||||
return ipcRenderer.invoke(CHANNEL_UPDATE);
|
||||
|
@ -336,7 +336,7 @@ async function onSettingWindowCreated(view: Element) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (ResultVersion.result) {
|
||||
if (!ResultVersion.result) {
|
||||
view.querySelector(".llonebot-update-title").innerHTML = "当前已是最新版本 V" + ResultVersion.version;
|
||||
view.querySelector(".llonebot-update-button").innerHTML = "无需更新";
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user