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_LOG = 'llonebot_log'
|
||||||
export const CHANNEL_ERROR = 'llonebot_error'
|
export const CHANNEL_ERROR = 'llonebot_error'
|
||||||
export const CHANNEL_UPDATE = 'llonebot_update'
|
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'
|
export const CHANNEL_SELECT_FILE = 'llonebot_select_ffmpeg'
|
||||||
|
@ -6,7 +6,7 @@ import path from "node:path";
|
|||||||
import {selfInfo} from "./data";
|
import {selfInfo} from "./data";
|
||||||
import {DATA_DIR} from "./utils";
|
import {DATA_DIR} from "./utils";
|
||||||
|
|
||||||
export const HOOK_LOG = true;
|
export const HOOK_LOG = false;
|
||||||
|
|
||||||
export const ALLOW_SEND_TEMP_MSG = false;
|
export const ALLOW_SEND_TEMP_MSG = false;
|
||||||
|
|
||||||
|
@ -6,11 +6,12 @@ import util from "util";
|
|||||||
import {encode, getDuration, isWav} from "silk-wasm";
|
import {encode, getDuration, isWav} from "silk-wasm";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import {v4 as uuidv4} from "uuid";
|
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 {getConfigUtil} from "../config";
|
||||||
import {dbUtil} from "../db";
|
import {dbUtil} from "../db";
|
||||||
import * as fileType from "file-type";
|
import * as fileType from "file-type";
|
||||||
import {net} from "electron";
|
import {net} from "electron";
|
||||||
|
import config from "../../../electron.vite.config";
|
||||||
|
|
||||||
|
|
||||||
export function isGIF(path: string) {
|
export function isGIF(path: string) {
|
||||||
@ -66,28 +67,6 @@ export async function file2base64(path: string) {
|
|||||||
return result;
|
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) {
|
export async function encodeSilk(filePath: string) {
|
||||||
const fsp = require("fs").promises
|
const fsp = require("fs").promises
|
||||||
|
|
||||||
|
@ -14,3 +14,4 @@ if (!fs.existsSync(TEMP_DIR)) {
|
|||||||
fs.mkdirSync(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 path from "node:path";
|
||||||
import * as fs from "node:fs";
|
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";
|
import compressing from "compressing";
|
||||||
|
|
||||||
|
|
||||||
const downloadMirrorHosts = ["https://mirror.ghproxy.com/"];
|
const downloadMirrorHosts = ["https://mirror.ghproxy.com/"];
|
||||||
const checkVersionMirrorHosts = ["https://521github.com"];
|
const checkVersionMirrorHosts = ["https://521github.com"];
|
||||||
|
|
||||||
export async function checkVersion() {
|
export async function checkNewVersion() {
|
||||||
const latestVersionText = await getRemoteVersion();
|
const latestVersionText = await getRemoteVersion();
|
||||||
const latestVersion = latestVersionText.split(".");
|
const latestVersion = latestVersionText.split(".");
|
||||||
log("llonebot last version", latestVersion);
|
log("llonebot last version", latestVersion);
|
||||||
const currentVersion = version.split(".");
|
const currentVersion: string[] = version.split(".");
|
||||||
for (let k in [0, 1, 2]) {
|
log("llonebot current version", currentVersion);
|
||||||
if (latestVersion[k] > currentVersion[k]) {
|
for (let k of [0, 1, 2]) {
|
||||||
return {result: false, version: latestVersionText};
|
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() {
|
export async function upgradeLLOneBot() {
|
||||||
@ -28,17 +33,17 @@ export async function upgradeLLOneBot() {
|
|||||||
const filePath = path.join(TEMP_DIR, "./update-" + latestVersion + ".zip");
|
const filePath = path.join(TEMP_DIR, "./update-" + latestVersion + ".zip");
|
||||||
let downloadSuccess = false;
|
let downloadSuccess = false;
|
||||||
// 多镜像下载
|
// 多镜像下载
|
||||||
for(const mirrorGithub of downloadMirrorHosts){
|
for (const mirrorGithub of downloadMirrorHosts) {
|
||||||
try{
|
try {
|
||||||
const buffer = await httpDownload(mirrorGithub + downloadUrl);
|
const buffer = await httpDownload(mirrorGithub + downloadUrl);
|
||||||
fs.writeFileSync(filePath, buffer)
|
fs.writeFileSync(filePath, buffer)
|
||||||
downloadSuccess = true;
|
downloadSuccess = true;
|
||||||
break;
|
break;
|
||||||
}catch (e) {
|
} catch (e) {
|
||||||
log("llonebot upgrade error", e);
|
log("llonebot upgrade error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!downloadSuccess){
|
if (!downloadSuccess) {
|
||||||
log("llonebot upgrade error", "download failed");
|
log("llonebot upgrade error", "download failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -7,7 +7,7 @@ import {
|
|||||||
CHANNEL_ERROR,
|
CHANNEL_ERROR,
|
||||||
CHANNEL_GET_CONFIG,
|
CHANNEL_GET_CONFIG,
|
||||||
CHANNEL_LOG,
|
CHANNEL_LOG,
|
||||||
CHANNEL_CHECKVERSION,
|
CHANNEL_CHECK_VERSION,
|
||||||
CHANNEL_SELECT_FILE,
|
CHANNEL_SELECT_FILE,
|
||||||
CHANNEL_SET_CONFIG,
|
CHANNEL_SET_CONFIG,
|
||||||
CHANNEL_UPDATE,
|
CHANNEL_UPDATE,
|
||||||
@ -41,10 +41,10 @@ import {NTQQUserApi} from "../ntqqapi/api/user";
|
|||||||
import {NTQQGroupApi} from "../ntqqapi/api/group";
|
import {NTQQGroupApi} from "../ntqqapi/api/group";
|
||||||
import {registerPokeHandler} from "../ntqqapi/external/ccpoke";
|
import {registerPokeHandler} from "../ntqqapi/external/ccpoke";
|
||||||
import {OB11FriendPokeEvent, OB11GroupPokeEvent} from "../onebot11/event/notice/OB11PokeEvent";
|
import {OB11FriendPokeEvent, OB11GroupPokeEvent} from "../onebot11/event/notice/OB11PokeEvent";
|
||||||
import {checkVersion, upgradeLLOneBot} from "../common/utils/upgrade";
|
import {checkNewVersion, upgradeLLOneBot} from "../common/utils/upgrade";
|
||||||
import {checkFfmpeg} from "../common/utils/file";
|
|
||||||
import {log} from "../common/utils/log";
|
import {log} from "../common/utils/log";
|
||||||
import {getConfigUtil} from "../common/config";
|
import {getConfigUtil} from "../common/config";
|
||||||
|
import {checkFfmpeg} from "../common/utils/video";
|
||||||
|
|
||||||
|
|
||||||
let running = false;
|
let running = false;
|
||||||
@ -53,8 +53,8 @@ let running = false;
|
|||||||
// 加载插件时触发
|
// 加载插件时触发
|
||||||
function onLoad() {
|
function onLoad() {
|
||||||
log("llonebot main onLoad");
|
log("llonebot main onLoad");
|
||||||
ipcMain.handle(CHANNEL_CHECKVERSION, async (event, arg) => {
|
ipcMain.handle(CHANNEL_CHECK_VERSION, async (event, arg) => {
|
||||||
return checkVersion();
|
return checkNewVersion();
|
||||||
});
|
});
|
||||||
ipcMain.handle(CHANNEL_UPDATE, async (event, arg) => {
|
ipcMain.handle(CHANNEL_UPDATE, async (event, arg) => {
|
||||||
return upgradeLLOneBot();
|
return upgradeLLOneBot();
|
||||||
|
@ -4,6 +4,7 @@ import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer";
|
|||||||
import {ob11ReverseWebsockets} from "../onebot11/server/ws/ReverseWebsocket";
|
import {ob11ReverseWebsockets} from "../onebot11/server/ws/ReverseWebsocket";
|
||||||
import {llonebotError} from "../common/data";
|
import {llonebotError} from "../common/data";
|
||||||
import {getConfigUtil} from "../common/config";
|
import {getConfigUtil} from "../common/config";
|
||||||
|
import {checkFfmpeg} from "../common/utils";
|
||||||
|
|
||||||
export async function setConfig(config: Config) {
|
export async function setConfig(config: Config) {
|
||||||
let oldConfig = getConfigUtil().getConfig();
|
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 {BrowserWindow} from "electron";
|
||||||
import {dbUtil} from "../../common/db";
|
import {dbUtil} from "../../common/db";
|
||||||
import {log} from "../../common/utils/log";
|
import {log} from "../../common/utils/log";
|
||||||
|
import {NTQQWindowApi, NTQQWindows} from "./window";
|
||||||
|
|
||||||
export class NTQQGroupApi{
|
export class NTQQGroupApi{
|
||||||
static async getGroups(forced = false) {
|
static async getGroups(forced = false) {
|
||||||
@ -74,25 +75,7 @@ export class NTQQGroupApi{
|
|||||||
}
|
}
|
||||||
static async getGroupIgnoreNotifies() {
|
static async getGroupIgnoreNotifies() {
|
||||||
await NTQQGroupApi.getGroupNotifies();
|
await NTQQGroupApi.getGroupNotifies();
|
||||||
const result = callNTQQApi<GroupNotifies>({
|
return await NTQQWindowApi.openWindow(NTQQWindows.GroupNotifyFilterWindow,[], ReceiveCmdS.GROUP_NOTIFY);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) {
|
static async handleGroupRequest(seq: string, operateType: GroupRequestOperateTypes, reason?: string) {
|
||||||
const notify: GroupNotify = await dbUtil.getGroupNotify(seq)
|
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
|
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',
|
SELF_STATUS: 'nodeIKernelProfileListener/onSelfStatusChanged',
|
||||||
CACHE_SCAN_FINISH: "nodeIKernelStorageCleanListener/onFinishScan",
|
CACHE_SCAN_FINISH: "nodeIKernelStorageCleanListener/onFinishScan",
|
||||||
MEDIA_UPLOAD_COMPLETE: "nodeIKernelMsgListener/onRichMediaUploadComplete",
|
MEDIA_UPLOAD_COMPLETE: "nodeIKernelMsgListener/onRichMediaUploadComplete",
|
||||||
|
SKEY_UPDATE: "onSkeyUpdate"
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ReceiveCmd = typeof ReceiveCmdS[keyof typeof ReceiveCmdS]
|
export type ReceiveCmd = typeof ReceiveCmdS[keyof typeof ReceiveCmdS]
|
||||||
@ -60,13 +61,21 @@ let receiveHooks: Array<{
|
|||||||
export function hookNTQQApiReceive(window: BrowserWindow) {
|
export function hookNTQQApiReceive(window: BrowserWindow) {
|
||||||
const originalSend = window.webContents.send;
|
const originalSend = window.webContents.send;
|
||||||
const patchSend = (channel: string, ...args: NTQQApiReturnData) => {
|
const patchSend = (channel: string, ...args: NTQQApiReturnData) => {
|
||||||
|
// console.log("hookNTQQApiReceive", channel, args)
|
||||||
|
let isLogger = false
|
||||||
try {
|
try {
|
||||||
if (!args[0]?.eventName?.startsWith("ns-LoggerApi")) {
|
isLogger = args[0]?.eventName?.startsWith("ns-LoggerApi")
|
||||||
HOOK_LOG && log(`received ntqq api message: ${channel}`, JSON.stringify(args))
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
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) {
|
if (args?.[1] instanceof Array) {
|
||||||
for (let receiveData of args?.[1]) {
|
for (let receiveData of args?.[1]) {
|
||||||
const ntQQApiMethodName = receiveData.cmdName;
|
const ntQQApiMethodName = receiveData.cmdName;
|
||||||
@ -98,7 +107,10 @@ export function hookNTQQApiReceive(window: BrowserWindow) {
|
|||||||
delete hookApiCallbacks[callbackId];
|
delete hookApiCallbacks[callbackId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return originalSend.call(window.webContents, channel, ...args);
|
}catch (e) {
|
||||||
|
log("hookNTQQApiReceive error", e.stack.toString(), args)
|
||||||
|
}
|
||||||
|
originalSend.call(window.webContents, channel, ...args);
|
||||||
}
|
}
|
||||||
window.webContents.send = patchSend;
|
window.webContents.send = patchSend;
|
||||||
}
|
}
|
||||||
@ -110,12 +122,19 @@ export function hookNTQQApiCall(window: BrowserWindow) {
|
|||||||
|
|
||||||
const proxyIpcMsg = new Proxy(ipc_message_proxy, {
|
const proxyIpcMsg = new Proxy(ipc_message_proxy, {
|
||||||
apply(target, thisArg, args) {
|
apply(target, thisArg, args) {
|
||||||
|
// console.log(thisArg, args);
|
||||||
|
let isLogger = false
|
||||||
try {
|
try {
|
||||||
if (args[3][1][0] !== "info") {
|
isLogger = args[3][0].eventName.startsWith("ns-LoggerApi")
|
||||||
HOOK_LOG && log("call NTQQ api", thisArg, args);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!isLogger) {
|
||||||
|
try{
|
||||||
|
HOOK_LOG && log("call NTQQ api", thisArg, args);
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return target.apply(thisArg, args);
|
return target.apply(thisArg, args);
|
||||||
},
|
},
|
||||||
@ -137,7 +156,11 @@ export function hookNTQQApiCall(window: BrowserWindow) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
let ret = target.apply(thisArg, args);
|
let ret = target.apply(thisArg, args);
|
||||||
|
try {
|
||||||
HOOK_LOG && log("call NTQQ invoke api return", ret)
|
HOOK_LOG && log("call NTQQ invoke api return", ret)
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import {ipcMain} from "electron";
|
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 {v4 as uuidv4} from "uuid"
|
||||||
import {log} from "../common/utils/log";
|
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 {
|
export enum NTQQApiClass {
|
||||||
NT_API = "ns-ntApi",
|
NT_API = "ns-ntApi",
|
||||||
@ -11,7 +14,10 @@ export enum NTQQApiClass {
|
|||||||
WINDOW_API = "ns-WindowApi",
|
WINDOW_API = "ns-WindowApi",
|
||||||
HOTUPDATE_API = "ns-HotUpdateApi",
|
HOTUPDATE_API = "ns-HotUpdateApi",
|
||||||
BUSINESS_API = "ns-BusinessApi",
|
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 {
|
export enum NTQQApiMethod {
|
||||||
@ -65,7 +71,9 @@ export enum NTQQApiMethod {
|
|||||||
|
|
||||||
OPEN_EXTRA_WINDOW = 'openExternalWindow',
|
OPEN_EXTRA_WINDOW = 'openExternalWindow',
|
||||||
|
|
||||||
SET_QQ_AVATAR = 'nodeIKernelProfileService/setHeader'
|
SET_QQ_AVATAR = 'nodeIKernelProfileService/setHeader',
|
||||||
|
GET_SKEY = "nodeIKernelTipOffService/getPskey",
|
||||||
|
UPDATE_SKEY = "updatePskey"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NTQQApiChannel {
|
enum NTQQApiChannel {
|
||||||
@ -98,7 +106,7 @@ export function callNTQQApi<ReturnType>(params: NTQQApiParams) {
|
|||||||
timeout = timeout ?? 5;
|
timeout = timeout ?? 5;
|
||||||
afterFirstCmd = afterFirstCmd ?? true;
|
afterFirstCmd = afterFirstCmd ?? true;
|
||||||
const uuid = uuidv4();
|
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) => {
|
return new Promise((resolve: (data: ReturnType) => void, reject) => {
|
||||||
// log("callNTQQApiPromise", channel, className, methodName, args, uuid)
|
// log("callNTQQApiPromise", channel, className, methodName, args, uuid)
|
||||||
const _timeout = timeout * 1000
|
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; // 签名
|
longNick?: string; // 签名
|
||||||
remark?: string;
|
remark?: string;
|
||||||
sex?: Sex;
|
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 {
|
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 BaseAction from "../BaseAction";
|
||||||
import {OB11User} from "../../types";
|
import {OB11User} from "../../types";
|
||||||
import {getFriend, getGroupMember, groups} from "../../../common/data";
|
import {getUidByUin, uidMaps} from "../../../common/data";
|
||||||
import {OB11Constructor} from "../../constructor";
|
import {OB11Constructor} from "../../constructor";
|
||||||
import {ActionName} from "../types";
|
import {ActionName} from "../types";
|
||||||
import {isNull, log} from "../../../common/utils";
|
|
||||||
import {NTQQUserApi} from "../../../ntqqapi/api/user";
|
import {NTQQUserApi} from "../../../ntqqapi/api/user";
|
||||||
import {Friend, GroupMember} from "../../../ntqqapi/types";
|
|
||||||
|
|
||||||
|
|
||||||
export default class GoCQHTTPGetStrangerInfo extends BaseAction<{ user_id: number }, OB11User> {
|
export default class GoCQHTTPGetStrangerInfo extends BaseAction<{ user_id: number }, OB11User> {
|
||||||
actionName = ActionName.GoCQHTTP_GetStrangerInfo
|
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> {
|
protected async _handle(payload: { user_id: number }): Promise<OB11User> {
|
||||||
const user_id = payload.user_id.toString()
|
const user_id = payload.user_id.toString()
|
||||||
const friend = await getFriend(user_id)
|
const uid = getUidByUin(user_id)
|
||||||
if (friend) {
|
if (!uid) {
|
||||||
await this.refreshInfo(friend);
|
|
||||||
return OB11Constructor.friend(friend);
|
|
||||||
}
|
|
||||||
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("查无此人")
|
throw new Error("查无此人")
|
||||||
}
|
}
|
||||||
|
return OB11Constructor.stranger(await NTQQUserApi.getUserDetailInfo(uid))
|
||||||
|
}
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ import SendLike from "./SendLike";
|
|||||||
import SetGroupAddRequest from "./SetGroupAddRequest";
|
import SetGroupAddRequest from "./SetGroupAddRequest";
|
||||||
import SetGroupLeave from "./SetGroupLeave";
|
import SetGroupLeave from "./SetGroupLeave";
|
||||||
import GetGuildList from "./GetGuildList";
|
import GetGuildList from "./GetGuildList";
|
||||||
import Debug from "./Debug";
|
import Debug from "./llonebot/Debug";
|
||||||
import SetFriendAddRequest from "./SetFriendAddRequest";
|
import SetFriendAddRequest from "./SetFriendAddRequest";
|
||||||
import SetGroupWholeBan from "./SetGroupWholeBan";
|
import SetGroupWholeBan from "./SetGroupWholeBan";
|
||||||
import SetGroupName from "./SetGroupName";
|
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,
|
nickname: friend.nick,
|
||||||
remark: friend.remark,
|
remark: friend.remark,
|
||||||
sex: OB11Constructor.sex(friend.sex),
|
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 {
|
static selfInfo(selfInfo: SelfInfo): OB11User {
|
||||||
return {
|
return {
|
||||||
user_id: parseInt(selfInfo.uin),
|
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[] {
|
static groupMembers(group: Group): OB11GroupMember[] {
|
||||||
log("construct ob11 group members", group)
|
log("construct ob11 group members", group)
|
||||||
return group.members.map(m => OB11Constructor.groupMember(group.groupCode, m))
|
return group.members.map(m => OB11Constructor.groupMember(group.groupCode, m))
|
||||||
|
@ -6,7 +6,10 @@ export interface OB11User {
|
|||||||
nickname: string;
|
nickname: string;
|
||||||
remark?: string;
|
remark?: string;
|
||||||
sex?: OB11UserSex;
|
sex?: OB11UserSex;
|
||||||
qq_level?: number;
|
level?: number;
|
||||||
|
age?: number;
|
||||||
|
qid?: string;
|
||||||
|
login_days?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OB11UserSex {
|
export enum OB11UserSex {
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
CHANNEL_ERROR,
|
CHANNEL_ERROR,
|
||||||
CHANNEL_GET_CONFIG,
|
CHANNEL_GET_CONFIG,
|
||||||
CHANNEL_LOG,
|
CHANNEL_LOG,
|
||||||
CHANNEL_CHECKVERSION,
|
CHANNEL_CHECK_VERSION,
|
||||||
CHANNEL_SELECT_FILE,
|
CHANNEL_SELECT_FILE,
|
||||||
CHANNEL_SET_CONFIG,
|
CHANNEL_SET_CONFIG,
|
||||||
CHANNEL_UPDATE,
|
CHANNEL_UPDATE,
|
||||||
@ -19,7 +19,7 @@ const llonebot = {
|
|||||||
ipcRenderer.send(CHANNEL_LOG, data);
|
ipcRenderer.send(CHANNEL_LOG, data);
|
||||||
},
|
},
|
||||||
checkVersion:async (): Promise<CheckVersion> => {
|
checkVersion:async (): Promise<CheckVersion> => {
|
||||||
return ipcRenderer.invoke(CHANNEL_CHECKVERSION);
|
return ipcRenderer.invoke(CHANNEL_CHECK_VERSION);
|
||||||
},
|
},
|
||||||
updateLLOneBot:async (): Promise<boolean> => {
|
updateLLOneBot:async (): Promise<boolean> => {
|
||||||
return ipcRenderer.invoke(CHANNEL_UPDATE);
|
return ipcRenderer.invoke(CHANNEL_UPDATE);
|
||||||
|
@ -336,7 +336,7 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ResultVersion.result) {
|
if (!ResultVersion.result) {
|
||||||
view.querySelector(".llonebot-update-title").innerHTML = "当前已是最新版本 V" + ResultVersion.version;
|
view.querySelector(".llonebot-update-title").innerHTML = "当前已是最新版本 V" + ResultVersion.version;
|
||||||
view.querySelector(".llonebot-update-button").innerHTML = "无需更新";
|
view.querySelector(".llonebot-update-button").innerHTML = "无需更新";
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user