From 5aecf45959598a008d974397e526806f3cb076df Mon Sep 17 00:00:00 2001 From: spring Date: Mon, 18 Mar 2024 11:32:56 +0800 Subject: [PATCH 01/13] add: support for file download --- src/onebot11/action/go-cqhttp/DownloadFile.ts | 103 ++++++++++++++++++ src/onebot11/action/index.ts | 2 + src/onebot11/action/types.ts | 1 + 3 files changed, 106 insertions(+) create mode 100644 src/onebot11/action/go-cqhttp/DownloadFile.ts diff --git a/src/onebot11/action/go-cqhttp/DownloadFile.ts b/src/onebot11/action/go-cqhttp/DownloadFile.ts new file mode 100644 index 0000000..6c457e1 --- /dev/null +++ b/src/onebot11/action/go-cqhttp/DownloadFile.ts @@ -0,0 +1,103 @@ +import BaseAction from "../BaseAction"; +import {ActionName} from "../types"; +import fs from "fs"; +import {join as joinPath} from "node:path"; +import {calculateFileMD5, DATA_DIR} from "../../../common/utils"; + +interface Payload { + thread_count?: number + url?: string + base64?: string + name?: string + headers?: string | string[] +} + +interface FileResponse { + file: string +} + +const localPath = joinPath(DATA_DIR, "file_cache") +export default class GoCQHTTPDownloadFile extends BaseAction { + actionName = ActionName.GoCQHTTP_DownloadFile + + constructor() { + super(); + if (!fs.existsSync(localPath)) { + fs.mkdirSync(localPath) + } + } + + protected async _handle(payload: Payload): Promise { + let name = payload.name || ""; + const isRandomName = !payload.name + + if (isRandomName) { + do { + name = this.generateRandomString(10); + // 使用循环防止极低概率的情况下随机出已有的文件, 导致覆盖 + } while (fs.existsSync(joinPath(localPath, name))); + } + + const filePath = joinPath(localPath, name); + + if (payload.base64) { + fs.writeFileSync(filePath, payload.base64, 'base64') + } else if (payload.url) { + const headers = this.getHeaders(payload.headers); + + const result = await fetch(payload.url, {headers}) + if (! result.ok) throw new Error(`下载文件失败: ${result.statusText}`) + + const blob = await result.blob(); + let buffer = await blob.arrayBuffer(); + fs.writeFileSync(filePath, Buffer.from(buffer), 'binary'); + } else { + throw new Error("不存在任何文件, 无法下载") + } + if (fs.existsSync(filePath)) { + + if (isRandomName) { + // 默认实现要名称未填写时文件名为文件 md5 + const md5 = await calculateFileMD5(filePath); + const newPath = joinPath(localPath, md5); + fs.renameSync(filePath, newPath); + return { file: newPath } + } + return { file: filePath } + } else { + throw new Error("文件写入失败, 检查权限") + } + } + + generateRandomString(length: number): string { + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let randomString = ''; + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * characters.length); + randomString += characters.charAt(randomIndex); + } + return randomString; + } + + getHeaders(headersIn?: string | string[]): any { + const headers = {}; + if (typeof headersIn == 'string') { + headersIn = headersIn.split('[\\r\\n]'); + } + if (Array.isArray(headersIn)) { + for (const headerItem of headersIn) { + const spilt = headerItem.indexOf('='); + if (spilt < 0) { + headers[headerItem] = ""; + } else { + const key = headerItem.substring(0, spilt); + headers[key] = headerItem.substring(0, spilt + 1); + } + } + } + if (!headers['Content-Type']) { + headers['Content-Type'] = 'application/octet-stream'; + } + return headers; + } +} \ No newline at end of file diff --git a/src/onebot11/action/index.ts b/src/onebot11/action/index.ts index af557be..def74d6 100644 --- a/src/onebot11/action/index.ts +++ b/src/onebot11/action/index.ts @@ -36,6 +36,7 @@ import GoCQHTTPUploadGroupFile from "./go-cqhttp/UploadGroupFile"; import {GetConfigAction, SetConfigAction} from "./llonebot/Config"; import GetGroupAddRequest from "./llonebot/GetGroupAddRequest"; import SetQQAvatar from './llonebot/SetQQAvatar' +import GoCQHTTPDownloadFile from "./go-cqhttp/DownloadFile"; export const actionHandlers = [ new Debug(), @@ -72,6 +73,7 @@ export const actionHandlers = [ new GoCQHTTPSendGroupForwardMsg(), new GoCQHTTPSendPrivateForwardMsg(), new GoCQHTTPGetStrangerInfo(), + new GoCQHTTPDownloadFile(), new GetGuildList(), new GoCQHTTPMarkMsgAsRead(), new GoCQHTTPUploadGroupFile(), diff --git a/src/onebot11/action/types.ts b/src/onebot11/action/types.ts index 48db8fd..a00bf13 100644 --- a/src/onebot11/action/types.ts +++ b/src/onebot11/action/types.ts @@ -54,4 +54,5 @@ export enum ActionName { GetGuildList = "get_guild_list", GoCQHTTP_MarkMsgAsRead = "mark_msg_as_read", GoCQHTTP_UploadGroupFile = "upload_group_file", + GoCQHTTP_DownloadFile = "download_file", } \ No newline at end of file From 6ea6b33e9ad9297e2b0ec3f5c0534f06f04dbac9 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 19 Mar 2024 00:33:51 +0800 Subject: [PATCH 02/13] refactor: file utils --- src/common/data.ts | 4 +- src/common/server/http.ts | 18 ++- src/common/server/websocket.ts | 9 +- src/common/types.ts | 2 + src/common/utils/file.ts | 131 +++++++++++++++++- src/common/utils/helper.ts | 24 +++- src/common/utils/index.ts | 9 +- src/main/main.ts | 26 ++-- src/main/setConfig.ts | 12 +- src/onebot11/action/GetFile.ts | 23 ++- src/onebot11/action/SendMsg.ts | 2 +- src/onebot11/action/go-cqhttp/DownloadFile.ts | 35 +---- .../action/go-cqhttp/UploadGroupFile.ts | 2 +- src/onebot11/action/llonebot/SetQQAvatar.ts | 3 +- src/onebot11/utils.ts | 130 ----------------- src/preload.ts | 2 +- src/renderer/index.ts | 83 ++++++----- src/renderer/style.css | 8 ++ 18 files changed, 281 insertions(+), 242 deletions(-) delete mode 100644 src/onebot11/utils.ts diff --git a/src/common/data.ts b/src/common/data.ts index 5bfb876..b006762 100644 --- a/src/common/data.ts +++ b/src/common/data.ts @@ -21,7 +21,9 @@ export let friends: Friend[] = [] export let friendRequests: Map = new Map() export const llonebotError: LLOneBotError = { ffmpegError: '', - otherError: '' + httpServerError: '', + wsServerError: '', + otherError: 'LLOnebot未能正常启动,请检查日志查看错误' } diff --git a/src/common/server/http.ts b/src/common/server/http.ts index 32dd4bb..ccaf49f 100644 --- a/src/common/server/http.ts +++ b/src/common/server/http.ts @@ -1,7 +1,8 @@ -import express, {Express, json, Request, Response} from "express"; +import express, {Express, Request, Response} from "express"; import http from "http"; import {log} from "../utils/log"; import {getConfigUtil} from "../config"; +import {llonebotError} from "../data"; type RegisterHandler = (res: Response, payload: any) => Promise @@ -52,13 +53,20 @@ export abstract class HttpServerBase { }; start(port: number) { - this.expressAPP.get('/', (req: Request, res: Response) => { - res.send(`${this.name}已启动`); - }) - this.listen(port); + try { + this.expressAPP.get('/', (req: Request, res: Response) => { + res.send(`${this.name}已启动`); + }) + this.listen(port); + llonebotError.httpServerError = "" + } catch (e) { + log("HTTP服务启动失败", e.toString()) + llonebotError.httpServerError = "HTTP服务启动失败, " + e.toString() + } } stop() { + llonebotError.httpServerError = "" if (this.server) { this.server.close() this.server = null; diff --git a/src/common/server/websocket.ts b/src/common/server/websocket.ts index 0920b01..a9e4d3d 100644 --- a/src/common/server/websocket.ts +++ b/src/common/server/websocket.ts @@ -3,6 +3,7 @@ import urlParse from "url"; import {IncomingMessage} from "node:http"; import {log} from "../utils/log"; import {getConfigUtil} from "../config"; +import {llonebotError} from "../data"; class WebsocketClientBase { private wsClient: WebSocket @@ -29,7 +30,12 @@ export class WebsocketServerBase { } start(port: number) { - this.ws = new WebSocketServer({port}); + try { + this.ws = new WebSocketServer({port}); + llonebotError.wsServerError = '' + }catch (e) { + llonebotError.wsServerError = "正向ws服务启动失败, " + e.toString() + } this.ws.on("connection", (wsClient, req) => { const url = req.url.split("?").shift() this.authorize(wsClient, req); @@ -41,6 +47,7 @@ export class WebsocketServerBase { } stop() { + llonebotError.wsServerError = '' this.ws.close((err) => { log("ws server close failed!", err) }); diff --git a/src/common/types.ts b/src/common/types.ts index 060a517..aa4d98b 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -28,6 +28,8 @@ export interface Config { } export interface LLOneBotError { + httpServerError?: string + wsServerError?: string ffmpegError?: string otherError?: string } diff --git a/src/common/utils/file.ts b/src/common/utils/file.ts index f473aef..e7cc046 100644 --- a/src/common/utils/file.ts +++ b/src/common/utils/file.ts @@ -5,9 +5,10 @@ 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} from "./index"; -import {log} from "./log"; +import {DATA_DIR, log, TEMP_DIR} from "./index"; import {getConfigUtil} from "../config"; +import {dbUtil} from "../db"; +import * as fileType from "file-type"; export function isGIF(path: string) { const buffer = Buffer.alloc(4); @@ -64,8 +65,11 @@ export async function file2base64(path: string) { export function checkFfmpeg(newPath: string = null): Promise { 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); @@ -75,6 +79,8 @@ export function checkFfmpeg(newPath: string = null): Promise { resolve(true); } }) + }catch (e) { + resolve(false); } }); } @@ -260,4 +266,125 @@ export function calculateFileMD5(filePath: string): Promise { reject(err); }); }); +} + +type Uri2LocalRes = { + success: boolean, + errMsg: string, + fileName: string, + ext: string, + path: string, + isLocal: boolean +} + +export async function uri2local(uri: string, fileName: string = null): Promise { + let res = { + success: false, + errMsg: "", + fileName: "", + ext: "", + path: "", + isLocal: false + } + if (!fileName) { + fileName = uuidv4(); + } + let filePath = path.join(TEMP_DIR, fileName) + let url = null; + try { + url = new URL(uri); + } catch (e) { + res.errMsg = `uri ${uri} 解析失败,` + e.toString() + ` 可能${uri}不存在` + return res + } + + // log("uri protocol", url.protocol, uri); + if (url.protocol == "base64:") { + // base64转成文件 + let base64Data = uri.split("base64://")[1] + try { + const buffer = Buffer.from(base64Data, 'base64'); + fs.writeFileSync(filePath, buffer); + + } catch (e: any) { + res.errMsg = `base64文件下载失败,` + e.toString() + return res + } + } else if (url.protocol == "http:" || url.protocol == "https:") { + // 下载文件 + let fetchRes: Response; + try { + fetchRes = await fetch(url) + } catch (e) { + res.errMsg = `${url}下载失败` + return res + } + if (!fetchRes.ok) { + res.errMsg = `${url}下载失败,` + fetchRes.statusText + return res + } + let blob = await fetchRes.blob(); + let buffer = await blob.arrayBuffer(); + try { + const pathInfo = path.parse(decodeURIComponent(url.pathname)) + if (pathInfo.name) { + fileName = pathInfo.name + if (pathInfo.ext) { + fileName += pathInfo.ext + // res.ext = pathInfo.ext + } + } + res.fileName = fileName + filePath = path.join(TEMP_DIR, uuidv4() + fileName) + fs.writeFileSync(filePath, Buffer.from(buffer)); + } catch (e: any) { + res.errMsg = `${url}下载失败,` + e.toString() + return res + } + } else { + let pathname: string; + if (url.protocol === "file:") { + // await fs.copyFile(url.pathname, filePath); + pathname = decodeURIComponent(url.pathname) + if (process.platform === "win32") { + filePath = pathname.slice(1) + } else { + filePath = pathname + } + } else { + const cache = await dbUtil.getFileCache(uri); + if (cache) { + filePath = cache.filePath + } else { + filePath = uri; + } + } + + res.isLocal = true + } + // else{ + // res.errMsg = `不支持的file协议,` + url.protocol + // return res + // } + // if (isGIF(filePath) && !res.isLocal) { + // await fs.rename(filePath, filePath + ".gif"); + // filePath += ".gif"; + // } + if (!res.isLocal && !res.ext) { + try { + let ext: string = (await fileType.fileTypeFromFile(filePath)).ext + if (ext) { + log("获取文件类型", ext, filePath) + fs.renameSync(filePath, filePath + `.${ext}`) + filePath += `.${ext}` + res.fileName += `.${ext}` + res.ext = ext + } + } catch (e) { + // log("获取文件类型失败", filePath,e.stack) + } + } + res.success = true + res.path = filePath + return res } \ No newline at end of file diff --git a/src/common/utils/helper.ts b/src/common/utils/helper.ts index 65a999a..48862b8 100644 --- a/src/common/utils/helper.ts +++ b/src/common/utils/helper.ts @@ -43,4 +43,26 @@ export function mergeNewProperties(newObj: any, oldObj: any) { export function isNull(value: any) { return value === undefined || value === null; -} \ No newline at end of file +} + +/** + * 将字符串按最大长度分割并添加换行符 + * @param str 原始字符串 + * @param maxLength 每行的最大字符数 + * @returns 处理后的字符串,超过长度的地方将会换行 + */ +export function wrapText(str: string, maxLength: number): string { + // 初始化一个空字符串用于存放结果 + let result: string = ''; + + // 循环遍历字符串,每次步进maxLength个字符 + for (let i = 0; i < str.length; i += maxLength) { + // 从i开始,截取长度为maxLength的字符串段,并添加到结果字符串 + // 如果不是第一段,先添加一个换行符 + if (i > 0) result += '\n'; + result += str.substring(i, i + maxLength); + } + + return result; +} + diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index af279cf..81ef39b 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -1,3 +1,6 @@ +import path from "node:path"; +import fs from "fs"; + export * from './file' export * from './helper' export * from './log' @@ -5,6 +8,8 @@ export * from './qqlevel' export * from './qqpkg' export * from './update' export const DATA_DIR = global.LiteLoader.plugins["LLOneBot"].path.data; +export const TEMP_DIR = path.join(DATA_DIR, "temp"); - - +if (!fs.existsSync(TEMP_DIR)) { + fs.mkdirSync(TEMP_DIR); +} \ No newline at end of file diff --git a/src/main/main.ts b/src/main/main.ts index 15da2d2..352d0ad 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -13,7 +13,7 @@ import { CHANNEL_UPDATE, } from "../common/channels"; import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer"; -import {DATA_DIR} from "../common/utils"; +import {DATA_DIR, wrapText} from "../common/utils"; import { friendRequests, getFriend, @@ -92,8 +92,14 @@ function onLoad() { if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR, {recursive: true}); } - ipcMain.handle(CHANNEL_ERROR, (event, arg) => { - return llonebotError; + ipcMain.handle(CHANNEL_ERROR, async (event, arg) => { + const ffmpegOk = await checkFfmpeg(getConfigUtil().getConfig().ffmpeg) + llonebotError.ffmpegError = ffmpegOk ? "" : "没有找到ffmpeg,音频只能发送wav和silk,视频无法发送" + let {httpServerError, wsServerError, otherError, ffmpegError} = llonebotError; + let error = `${otherError}\n${httpServerError}\n${wsServerError}\n${ffmpegError}` + error = error.replace("\n\n", "\n") + error = error.trim(); + return error; }) ipcMain.handle(CHANNEL_GET_CONFIG, async (event, arg) => { const config = getConfigUtil().getConfig() @@ -331,7 +337,7 @@ function onLoad() { async function start() { log("llonebot pid", process.pid) - + llonebotError.otherError = ""; startTime = Date.now(); dbUtil.getReceivedTempUinMap().then(m=>{ for (const [key, value] of Object.entries(m)) { @@ -341,18 +347,8 @@ function onLoad() { startReceiveHook().then(); NTQQGroupApi.getGroups(true).then() const config = getConfigUtil().getConfig() - // 检查ffmpeg - checkFfmpeg(config.ffmpeg).then(exist => { - if (!exist) { - llonebotError.ffmpegError = `没有找到ffmpeg,音频只能发送wav和silk` - } - }) if (config.ob11.enableHttp) { - try { - ob11HTTPServer.start(config.ob11.httpPort) - } catch (e) { - log("http server start failed", e); - } + ob11HTTPServer.start(config.ob11.httpPort) } if (config.ob11.enableWs) { ob11WebsocketServer.start(config.ob11.wsPort); diff --git a/src/main/setConfig.ts b/src/main/setConfig.ts index eb72ede..b82af07 100644 --- a/src/main/setConfig.ts +++ b/src/main/setConfig.ts @@ -3,7 +3,6 @@ import {ob11HTTPServer} from "../onebot11/server/http"; import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer"; import {ob11ReverseWebsockets} from "../onebot11/server/ws/ReverseWebsocket"; import {llonebotError} from "../common/data"; -import {checkFfmpeg} from "../common/utils/file"; import {getConfigUtil} from "../common/config"; export async function setConfig(config: Config) { @@ -21,6 +20,7 @@ export async function setConfig(config: Config) { // 正向ws端口变化,重启服务 if (config.ob11.wsPort != oldConfig.ob11.wsPort) { ob11WebsocketServer.restart(config.ob11.wsPort); + llonebotError.wsServerError = '' } // 判断是否启用或关闭正向ws if (config.ob11.enableWs != oldConfig.ob11.enableWs) { @@ -51,14 +51,4 @@ export async function setConfig(config: Config) { } } } - - // 检查ffmpeg - if (config.ffmpeg) { - checkFfmpeg(config.ffmpeg).then(success => { - if (success) { - llonebotError.ffmpegError = '' - } - }) - } - } \ No newline at end of file diff --git a/src/onebot11/action/GetFile.ts b/src/onebot11/action/GetFile.ts index ace5163..0687dfd 100644 --- a/src/onebot11/action/GetFile.ts +++ b/src/onebot11/action/GetFile.ts @@ -2,6 +2,7 @@ import BaseAction from "./BaseAction"; import fs from "fs/promises"; import {dbUtil} from "../../common/db"; import {getConfigUtil} from "../../common/config"; +import {log, uri2local} from "../../common/utils"; export interface GetFilePayload { file: string // 文件名 @@ -26,6 +27,18 @@ export class GetFileBase extends BaseAction { if (cache.downloadFunc) { await cache.downloadFunc() } + try { + await fs.access(cache.filePath, fs.constants.F_OK) + } catch (e) { + log("file not found", e) + const downloadResult = await uri2local(cache.url) + if (downloadResult.success) { + cache.filePath = downloadResult.path + dbUtil.addFileCache(payload.file, cache).then() + } else { + throw new Error("file download failed. " + downloadResult.errMsg) + } + } let res: GetFileResponse = { file: cache.filePath, url: cache.url, @@ -37,11 +50,11 @@ export class GetFileBase extends BaseAction { res.base64 = await fs.readFile(cache.filePath, 'base64') } } - if (autoDeleteFile) { - setTimeout(() => { - fs.unlink(cache.filePath) - }, autoDeleteFileSecond * 1000) - } + // if (autoDeleteFile) { + // setTimeout(() => { + // fs.unlink(cache.filePath) + // }, autoDeleteFileSecond * 1000) + // } return res } } \ No newline at end of file diff --git a/src/onebot11/action/SendMsg.ts b/src/onebot11/action/SendMsg.ts index b7eb2fa..b10976a 100644 --- a/src/onebot11/action/SendMsg.ts +++ b/src/onebot11/action/SendMsg.ts @@ -25,7 +25,6 @@ import { } from '../types'; import {Peer} from "../../ntqqapi/api/msg"; import {SendMsgElementConstructor} from "../../ntqqapi/constructor"; -import {uri2local} from "../utils"; import BaseAction from "./BaseAction"; import {ActionName, BaseCheckResult} from "./types"; import * as fs from "node:fs"; @@ -35,6 +34,7 @@ import {ALLOW_SEND_TEMP_MSG} from "../../common/config"; import {NTQQMsgApi} from "../../ntqqapi/api/msg"; import {log} from "../../common/utils/log"; import {sleep} from "../../common/utils/helper"; +import {uri2local} from "../../common/utils"; function checkSendMessage(sendMsgList: OB11MessageData[]) { function checkUri(uri: string): boolean { diff --git a/src/onebot11/action/go-cqhttp/DownloadFile.ts b/src/onebot11/action/go-cqhttp/DownloadFile.ts index 6c457e1..1444ad8 100644 --- a/src/onebot11/action/go-cqhttp/DownloadFile.ts +++ b/src/onebot11/action/go-cqhttp/DownloadFile.ts @@ -2,7 +2,8 @@ import BaseAction from "../BaseAction"; import {ActionName} from "../types"; import fs from "fs"; import {join as joinPath} from "node:path"; -import {calculateFileMD5, DATA_DIR} from "../../../common/utils"; +import {calculateFileMD5, TEMP_DIR} from "../../../common/utils"; +import {v4 as uuid4} from "uuid"; interface Payload { thread_count?: number @@ -16,29 +17,13 @@ interface FileResponse { file: string } -const localPath = joinPath(DATA_DIR, "file_cache") export default class GoCQHTTPDownloadFile extends BaseAction { actionName = ActionName.GoCQHTTP_DownloadFile - constructor() { - super(); - if (!fs.existsSync(localPath)) { - fs.mkdirSync(localPath) - } - } - protected async _handle(payload: Payload): Promise { - let name = payload.name || ""; const isRandomName = !payload.name - - if (isRandomName) { - do { - name = this.generateRandomString(10); - // 使用循环防止极低概率的情况下随机出已有的文件, 导致覆盖 - } while (fs.existsSync(joinPath(localPath, name))); - } - - const filePath = joinPath(localPath, name); + let name = payload.name || uuid4(); + const filePath = joinPath(TEMP_DIR, name); if (payload.base64) { fs.writeFileSync(filePath, payload.base64, 'base64') @@ -59,7 +44,7 @@ export default class GoCQHTTPDownloadFile extends BaseAction{ - let res = { - success: false, - errMsg: "", - fileName: "", - ext: "", - path: "", - isLocal: false - } - if (!fileName) { - fileName = uuidv4(); - } - let filePath = path.join(DATA_DIR, fileName) - let url = null; - try{ - url = new URL(uri); - }catch (e) { - res.errMsg = `uri ${uri} 解析失败,` + e.toString() + ` 可能${uri}不存在` - return res - } - - // log("uri protocol", url.protocol, uri); - if (url.protocol == "base64:") { - // base64转成文件 - let base64Data = uri.split("base64://")[1] - try { - const buffer = Buffer.from(base64Data, 'base64'); - await fs.writeFile(filePath, buffer); - - } catch (e: any) { - res.errMsg = `base64文件下载失败,` + e.toString() - return res - } - } else if (url.protocol == "http:" || url.protocol == "https:") { - // 下载文件 - let fetchRes: Response; - try{ - fetchRes = await fetch(url) - }catch (e) { - res.errMsg = `${url}下载失败` - return res - } - if (!fetchRes.ok) { - res.errMsg = `${url}下载失败,` + fetchRes.statusText - return res - } - let blob = await fetchRes.blob(); - let buffer = await blob.arrayBuffer(); - try { - const pathInfo = path.parse(decodeURIComponent(url.pathname)) - if (pathInfo.name){ - fileName = pathInfo.name - if (pathInfo.ext){ - fileName += pathInfo.ext - // res.ext = pathInfo.ext - } - } - res.fileName = fileName - filePath = path.join(DATA_DIR, uuidv4() + fileName) - await fs.writeFile(filePath, Buffer.from(buffer)); - } catch (e: any) { - res.errMsg = `${url}下载失败,` + e.toString() - return res - } - } else { - let pathname: string; - if (url.protocol === "file:") { - // await fs.copyFile(url.pathname, filePath); - pathname = decodeURIComponent(url.pathname) - if (process.platform === "win32") { - filePath = pathname.slice(1) - } else { - filePath = pathname - } - } else { - const cache = await dbUtil.getFileCache(uri); - if (cache) { - filePath = cache.filePath - } else { - filePath = uri; - } - } - - res.isLocal = true - } - // else{ - // res.errMsg = `不支持的file协议,` + url.protocol - // return res - // } - // if (isGIF(filePath) && !res.isLocal) { - // await fs.rename(filePath, filePath + ".gif"); - // filePath += ".gif"; - // } - if (!res.isLocal && !res.ext) { - try { - let ext: string = (await fileType.fileTypeFromFile(filePath)).ext - if (ext) { - log("获取文件类型", ext, filePath) - await fs.rename(filePath, filePath + `.${ext}`) - filePath += `.${ext}` - res.fileName += `.${ext}` - res.ext = ext - } - } catch (e) { - // log("获取文件类型失败", filePath,e.stack) - } - } - res.success = true - res.path = filePath - return res -} \ No newline at end of file diff --git a/src/preload.ts b/src/preload.ts index ed83aa0..ebdb027 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -30,7 +30,7 @@ const llonebot = { getConfig: async (): Promise => { return ipcRenderer.invoke(CHANNEL_GET_CONFIG); }, - getError: async (): Promise => { + getError: async (): Promise => { return ipcRenderer.invoke(CHANNEL_ERROR); }, selectFile: (): Promise => { diff --git a/src/renderer/index.ts b/src/renderer/index.ts index c16f12b..71a5736 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -1,11 +1,5 @@ /// -import { - SettingButton, - SettingItem, - SettingList, - SettingSelect, - SettingSwitch -} from './components'; +import {SettingButton, SettingItem, SettingList, SettingSwitch} from './components'; import StyleRaw from './style.css?raw'; // 打开设置界面时触发 @@ -14,18 +8,21 @@ async function onSettingWindowCreated(view: Element) { window.llonebot.log("setting window created"); const isEmpty = (value: any) => value === undefined || value === null || value === ''; let config = await window.llonebot.getConfig(); - let ob11Config = { ...config.ob11 }; + let ob11Config = {...config.ob11}; const setConfig = (key: string, value: any) => { const configKey = key.split('.'); if (key.indexOf('ob11') === 0) { + if (configKey[1] === "messagePostFormat") { + value = value ? "string" : "array" + } if (configKey.length === 2) ob11Config[configKey[1]] = value; else ob11Config[key] = value; } else { if (configKey.length === 2) config[configKey[0]][configKey[1]] = value; else config[key] = value; - if (!['heartInterval', 'token', 'ffmpeg'].includes(key)){ + if (!['heartInterval', 'token', 'ffmpeg'].includes(key)) { window.llonebot.setConfig(config); } } @@ -35,16 +32,19 @@ async function onSettingWindowCreated(view: Element) { const doc = parser.parseFromString([ '
', ``, + SettingList([ + '
', + ]), SettingList([ SettingItem('启用 HTTP 服务', null, - SettingSwitch('ob11.enableHttp', config.ob11.enableHttp, { 'control-display-id': 'config-ob11-httpPort' }), + SettingSwitch('ob11.enableHttp', config.ob11.enableHttp, {'control-display-id': 'config-ob11-httpPort'}), ), SettingItem('HTTP 服务监听端口', null, `
`, 'config-ob11-httpPort', config.ob11.enableHttp ), SettingItem('启用 HTTP 事件上报', null, - SettingSwitch('ob11.enableHttpPost', config.ob11.enableHttpPost, { 'control-display-id': 'config-ob11-httpHosts' }), + SettingSwitch('ob11.enableHttpPost', config.ob11.enableHttpPost, {'control-display-id': 'config-ob11-httpHosts'}), ), `
@@ -56,14 +56,14 @@ async function onSettingWindowCreated(view: Element) {
`, SettingItem('启用正向 WebSocket 服务', null, - SettingSwitch('ob11.enableWs', config.ob11.enableWs, { 'control-display-id': 'config-ob11-wsPort' }), + SettingSwitch('ob11.enableWs', config.ob11.enableWs, {'control-display-id': 'config-ob11-wsPort'}), ), SettingItem('正向 WebSocket 服务监听端口', null, `
`, 'config-ob11-wsPort', config.ob11.enableWs ), SettingItem('启用反向 WebSocket 服务', null, - SettingSwitch('ob11.enableWsReverse', config.ob11.enableWsReverse, { 'control-display-id': 'config-ob11-wsHosts' }), + SettingSwitch('ob11.enableWsReverse', config.ob11.enableWsReverse, {'control-display-id': 'config-ob11-wsHosts'}), ), `
@@ -82,12 +82,13 @@ async function onSettingWindowCreated(view: Element) { `
`, ), SettingItem( - '消息上报格式类型', + '启用CQ码上报格式,不启用则为消息段格式', '如客户端无特殊需求推荐保持默认设置,两者的详细差异可参考 OneBot v11 文档', - SettingSelect([ - { text: '消息段', value: 'array' }, - { text: 'CQ码', value: 'string' }, - ], 'ob11.messagePostFormat', config.ob11.messagePostFormat), + // SettingSelect([ + // {text: '消息段', value: 'array'}, + // {text: 'CQ码', value: 'string'}, + // ], 'ob11.messagePostFormat', config.ob11.messagePostFormat), + SettingSwitch('ob11.messagePostFormat', config.ob11.messagePostFormat === "string"), ), SettingItem( 'ffmpeg 路径,发送语音、视频需要,同时保证ffprobe和ffmpeg在一起', ` 下载地址 , 路径:${!isEmpty(config.ffmpeg) ? config.ffmpeg : '未指定'}`, @@ -122,7 +123,7 @@ async function onSettingWindowCreated(view: Element) { SettingItem( '自动删除收到的文件', '在收到文件后的指定时间内删除该文件', - SettingSwitch('autoDeleteFile', config.autoDeleteFile, { 'control-display-id': 'config-auto-delete-file-second' }), + SettingSwitch('autoDeleteFile', config.autoDeleteFile, {'control-display-id': 'config-auto-delete-file-second'}), ), SettingItem( '自动删除文件时间', @@ -166,6 +167,18 @@ async function onSettingWindowCreated(view: Element) { '
', ].join(''), "text/html"); + let errorEle = doc.querySelector("#llonebot-error"); + errorEle.style.display = 'none'; + const showError = async () => { + setTimeout(async () => { + let errMessage = await window.llonebot.getError(); + console.log(errMessage) + errMessage = errMessage.replace(/\n/g, '
') + errorEle.innerHTML = errMessage; + errorEle.style.display = errMessage ? 'flex' : 'none'; + }, 1000) + } + showError().then() // 外链按钮 doc.querySelector('#open-github').addEventListener('click', () => { window.LiteLoader.api.openExternal('https://github.com/LLOneBot/LLOneBot') @@ -180,7 +193,7 @@ async function onSettingWindowCreated(view: Element) { window.LiteLoader.api.openExternal('https://llonebot.github.io/') }) // 生成反向地址列表 - const buildHostListItem = (type: string, host: string, index: number, inputAttrs: any={}) => { + const buildHostListItem = (type: string, host: string, index: number, inputAttrs: any = {}) => { const dom = { container: document.createElement('setting-item'), input: document.createElement('input'), @@ -212,23 +225,23 @@ async function onSettingWindowCreated(view: Element) { return dom.container; }; - const buildHostList = (hosts: string[], type: string, inputAttr: any={}) => { + const buildHostList = (hosts: string[], type: string, inputAttr: any = {}) => { const result: HTMLElement[] = []; - + hosts.forEach((host, index) => { result.push(buildHostListItem(type, host, index, inputAttr)); }); - + return result; }; - const addReverseHost = (type: string, doc: Document = document, inputAttr: any={}) => { + const addReverseHost = (type: string, doc: Document = document, inputAttr: any = {}) => { const hostContainerDom = doc.body.querySelector(`#config-ob11-${type}-list`); hostContainerDom.appendChild(buildHostListItem(type, '', ob11Config[type].length, inputAttr)); ob11Config[type].push(''); }; const initReverseHost = (type: string, doc: Document = document) => { const hostContainerDom = doc.body.querySelector(`#config-ob11-${type}-list`); - [ ...hostContainerDom.childNodes ].forEach(dom => dom.remove()); + [...hostContainerDom.childNodes].forEach(dom => dom.remove()); buildHostList(ob11Config[type], type).forEach(dom => { hostContainerDom.appendChild(dom); }); @@ -236,8 +249,8 @@ async function onSettingWindowCreated(view: Element) { initReverseHost('httpHosts', doc); initReverseHost('wsHosts', doc); - doc.querySelector('#config-ob11-httpHosts-add').addEventListener('click', () => addReverseHost('httpHosts', document, {'placeholder': '如:http://127.0.0.1:5140/onebot' })); - doc.querySelector('#config-ob11-wsHosts-add').addEventListener('click', () => addReverseHost('wsHosts', document, {'placeholder': '如:ws://127.0.0.1:5140/onebot' })); + doc.querySelector('#config-ob11-httpHosts-add').addEventListener('click', () => addReverseHost('httpHosts', document, {'placeholder': '如:http://127.0.0.1:5140/onebot'})); + doc.querySelector('#config-ob11-wsHosts-add').addEventListener('click', () => addReverseHost('wsHosts', document, {'placeholder': '如:ws://127.0.0.1:5140/onebot'})); doc.querySelector('#config-ffmpeg-select').addEventListener('click', () => { window.llonebot.selectFile() @@ -297,6 +310,8 @@ async function onSettingWindowCreated(view: Element) { config.ob11 = ob11Config; window.llonebot.setConfig(config); + // window.location.reload(); + showError().then() alert('保存成功'); }); @@ -305,19 +320,19 @@ async function onSettingWindowCreated(view: Element) { }); } -function init () { - const hash = location.hash - if (hash === '#/blank') { +function init() { + const hash = location.hash + if (hash === '#/blank') { - } + } } if (location.hash === '#/blank') { - (window as any).navigation.addEventListener('navigatesuccess', init, { once: true }) + (window as any).navigation.addEventListener('navigatesuccess', init, {once: true}) } else { - init() + init() } export { - onSettingWindowCreated + onSettingWindowCreated } diff --git a/src/renderer/style.css b/src/renderer/style.css index 028aa96..675442a 100644 --- a/src/renderer/style.css +++ b/src/renderer/style.css @@ -61,4 +61,12 @@ setting-item a:hover { setting-item a:active, setting-item a:visited { color: var(--text-link); +} + +#llonebot-error{ + color: red; + height: 100px; + overflow: visible; + display: flex; + align-items: center; } \ No newline at end of file From b12d205059ddb60d51d864e150f1920fc859d61d Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 19 Mar 2024 00:37:20 +0800 Subject: [PATCH 03/13] feat: stranger info add sex & qq_level --- src/onebot11/action/go-cqhttp/GetStrangerInfo.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts b/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts index a8a21ca..bbf6c88 100644 --- a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts +++ b/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts @@ -3,6 +3,8 @@ import {OB11User} from "../../types"; import {getFriend, getGroupMember, groups} from "../../../common/data"; import {OB11Constructor} from "../../constructor"; import {ActionName} from "../types"; +import {isNull, log} from "../../../common/utils"; +import {NTQQUserApi} from "../../../ntqqapi/api/user"; export default class GoCQHTTPGetStrangerInfo extends BaseAction<{ user_id: number }, OB11User> { @@ -17,9 +19,13 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<{ user_id: numbe for (const group of groups) { const member = await getGroupMember(group.groupCode, user_id) if (member) { + if (isNull(member.sex)){ + let info = (await NTQQUserApi.getUserDetailInfo(member.uid)) + Object.assign(member, info); + } return OB11Constructor.groupMember(group.groupCode, member) as OB11User } } - throw ("查无此人") + throw new Error("查无此人") } } \ No newline at end of file From dda5ea39721f7f5eee40f1dfe5d33ddf0f0be6b4 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 19 Mar 2024 00:45:59 +0800 Subject: [PATCH 04/13] feat: stranger info add sex & qq_level --- src/onebot11/action/go-cqhttp/GetStrangerInfo.ts | 13 +++++++++---- src/onebot11/constructor.ts | 5 +++-- src/onebot11/types.ts | 4 +++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts b/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts index bbf6c88..340742f 100644 --- a/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts +++ b/src/onebot11/action/go-cqhttp/GetStrangerInfo.ts @@ -5,24 +5,29 @@ 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 { const user_id = payload.user_id.toString() const friend = await getFriend(user_id) if (friend) { + await this.refreshInfo(friend); return OB11Constructor.friend(friend); } for (const group of groups) { const member = await getGroupMember(group.groupCode, user_id) if (member) { - if (isNull(member.sex)){ - let info = (await NTQQUserApi.getUserDetailInfo(member.uid)) - Object.assign(member, info); - } + await this.refreshInfo(member); return OB11Constructor.groupMember(group.groupCode, member) as OB11User } } diff --git a/src/onebot11/constructor.ts b/src/onebot11/constructor.ts index a9e258f..2d66b9c 100644 --- a/src/onebot11/constructor.ts +++ b/src/onebot11/constructor.ts @@ -305,9 +305,10 @@ export class OB11Constructor { return { user_id: parseInt(friend.uin), nickname: friend.nick, - remark: friend.remark + remark: friend.remark, + sex: OB11Constructor.sex(friend.sex), + qq_level: friend.qqLevel && calcQQLevel(friend.qqLevel) || 0 } - } static selfInfo(selfInfo: SelfInfo): OB11User { diff --git a/src/onebot11/types.ts b/src/onebot11/types.ts index b8db420..3ebce72 100644 --- a/src/onebot11/types.ts +++ b/src/onebot11/types.ts @@ -4,7 +4,9 @@ import {EventType} from "./event/OB11BaseEvent"; export interface OB11User { user_id: number; nickname: string; - remark?: string + remark?: string; + sex?: OB11UserSex; + qq_level?: number; } export enum OB11UserSex { From 7381fb3e11f0f5c374fe34be9df14195701753a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 19 Mar 2024 10:47:58 +0800 Subject: [PATCH 05/13] feat:update renderer --- src/renderer/index.ts | 53 ++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/renderer/index.ts b/src/renderer/index.ts index c16f12b..77221b7 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -1,4 +1,5 @@ /// +import { CheckVersion } from '../common/types'; import { SettingButton, SettingItem, @@ -25,7 +26,7 @@ async function onSettingWindowCreated(view: Element) { if (configKey.length === 2) config[configKey[0]][configKey[1]] = value; else config[key] = value; - if (!['heartInterval', 'token', 'ffmpeg'].includes(key)){ + if (!['heartInterval', 'token', 'ffmpeg'].includes(key)) { window.llonebot.setConfig(config); } } @@ -35,6 +36,16 @@ async function onSettingWindowCreated(view: Element) { const doc = parser.parseFromString([ '
', ``, + ` + + + + 正在检查LLOneBot版本中 + 重新发现 + + + + `, SettingList([ SettingItem('启用 HTTP 服务', null, SettingSwitch('ob11.enableHttp', config.ob11.enableHttp, { 'control-display-id': 'config-ob11-httpPort' }), @@ -180,7 +191,7 @@ async function onSettingWindowCreated(view: Element) { window.LiteLoader.api.openExternal('https://llonebot.github.io/') }) // 生成反向地址列表 - const buildHostListItem = (type: string, host: string, index: number, inputAttrs: any={}) => { + const buildHostListItem = (type: string, host: string, index: number, inputAttrs: any = {}) => { const dom = { container: document.createElement('setting-item'), input: document.createElement('input'), @@ -212,23 +223,23 @@ async function onSettingWindowCreated(view: Element) { return dom.container; }; - const buildHostList = (hosts: string[], type: string, inputAttr: any={}) => { + const buildHostList = (hosts: string[], type: string, inputAttr: any = {}) => { const result: HTMLElement[] = []; - + hosts.forEach((host, index) => { result.push(buildHostListItem(type, host, index, inputAttr)); }); - + return result; }; - const addReverseHost = (type: string, doc: Document = document, inputAttr: any={}) => { + const addReverseHost = (type: string, doc: Document = document, inputAttr: any = {}) => { const hostContainerDom = doc.body.querySelector(`#config-ob11-${type}-list`); hostContainerDom.appendChild(buildHostListItem(type, '', ob11Config[type].length, inputAttr)); ob11Config[type].push(''); }; const initReverseHost = (type: string, doc: Document = document) => { const hostContainerDom = doc.body.querySelector(`#config-ob11-${type}-list`); - [ ...hostContainerDom.childNodes ].forEach(dom => dom.remove()); + [...hostContainerDom.childNodes].forEach(dom => dom.remove()); buildHostList(ob11Config[type], type).forEach(dom => { hostContainerDom.appendChild(dom); }); @@ -236,8 +247,8 @@ async function onSettingWindowCreated(view: Element) { initReverseHost('httpHosts', doc); initReverseHost('wsHosts', doc); - doc.querySelector('#config-ob11-httpHosts-add').addEventListener('click', () => addReverseHost('httpHosts', document, {'placeholder': '如:http://127.0.0.1:5140/onebot' })); - doc.querySelector('#config-ob11-wsHosts-add').addEventListener('click', () => addReverseHost('wsHosts', document, {'placeholder': '如:ws://127.0.0.1:5140/onebot' })); + doc.querySelector('#config-ob11-httpHosts-add').addEventListener('click', () => addReverseHost('httpHosts', document, { 'placeholder': '如:http://127.0.0.1:5140/onebot' })); + doc.querySelector('#config-ob11-wsHosts-add').addEventListener('click', () => addReverseHost('wsHosts', document, { 'placeholder': '如:ws://127.0.0.1:5140/onebot' })); doc.querySelector('#config-ffmpeg-select').addEventListener('click', () => { window.llonebot.selectFile() @@ -303,21 +314,31 @@ async function onSettingWindowCreated(view: Element) { doc.body.childNodes.forEach(node => { view.appendChild(node); }); + window.llonebot.checkVersion().then((ResultVersion: CheckVersion) => { + if (ResultVersion.result) { + view.querySelector(".llonebot-update-title").innerHTML = "当前已是最新版本 V" + ResultVersion.version; + view.querySelector(".llonebot-update-button").innerHTML = "无需更新"; + } else { + view.querySelector(".llonebot-update-title").innerHTML = "已监测到最新版本 V" + ResultVersion.version; + view.querySelector(".llonebot-update-button").innerHTML = "点击更新"; + } + }); + } -function init () { - const hash = location.hash - if (hash === '#/blank') { +function init() { + const hash = location.hash + if (hash === '#/blank') { - } + } } if (location.hash === '#/blank') { - (window as any).navigation.addEventListener('navigatesuccess', init, { once: true }) + (window as any).navigation.addEventListener('navigatesuccess', init, { once: true }) } else { - init() + init() } export { - onSettingWindowCreated + onSettingWindowCreated } From affefca19f5f0c14173c6a3f0cbf62da934ccf4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 19 Mar 2024 11:02:41 +0800 Subject: [PATCH 06/13] fix:checkVersion error --- src/renderer/index.ts | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/renderer/index.ts b/src/renderer/index.ts index 77221b7..edbd4b4 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -314,15 +314,37 @@ async function onSettingWindowCreated(view: Element) { doc.body.childNodes.forEach(node => { view.appendChild(node); }); - window.llonebot.checkVersion().then((ResultVersion: CheckVersion) => { + // 更新逻辑 + const checkVersionFunc = (ResultVersion: CheckVersion) => { + if (ResultVersion.version === "") { + view.querySelector(".llonebot-update-title").innerHTML = "检查更新失败"; + view.querySelector(".llonebot-update-button").innerHTML = "点击重试"; + view.querySelector(".llonebot-update-button").addEventListener("click", async () => { + window.llonebot.checkVersion().then(checkVersionFunc); + }); + return; + } if (ResultVersion.result) { view.querySelector(".llonebot-update-title").innerHTML = "当前已是最新版本 V" + ResultVersion.version; view.querySelector(".llonebot-update-button").innerHTML = "无需更新"; } else { view.querySelector(".llonebot-update-title").innerHTML = "已监测到最新版本 V" + ResultVersion.version; view.querySelector(".llonebot-update-button").innerHTML = "点击更新"; + const update = async () => { + view.querySelector(".llonebot-update-button").innerHTML = "正在更新中..."; + const result = await window.llonebot.updateLLOneBot(); + if (result) { + view.querySelector(".llonebot-update-button").innerHTML = "更新完成请重启"; + view.querySelector(".llonebot-update-button").removeEventListener("click", update); + } else { + view.querySelector(".llonebot-update-button").innerHTML = "更新失败前往仓库下载"; + view.querySelector(".llonebot-update-button").removeEventListener("click", update); + } + } + view.querySelector(".llonebot-update-button").addEventListener("click", update); } - }); + }; + window.llonebot.checkVersion().then(checkVersionFunc); } From 2dd5d81ffe17a88badf6cc4aa769319dcbc9892e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 19 Mar 2024 11:18:41 +0800 Subject: [PATCH 07/13] feat: update text --- src/common/utils/update.ts | 10 ++++++++-- src/renderer/index.ts | 7 ++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/common/utils/update.ts b/src/common/utils/update.ts index 8ab6184..13a3f77 100644 --- a/src/common/utils/update.ts +++ b/src/common/utils/update.ts @@ -1,6 +1,7 @@ -import {version} from "../../version"; +import { version } from "../../version"; import https from "node:https"; - +//import http from "node:http"; +import * as fs from "node:fs"; export async function checkVersion() { const latestVersionText = await getRemoteVersion(); const latestVersion = latestVersionText.split("."); @@ -18,6 +19,11 @@ export async function updateLLOneBot() { if (latestVersion && latestVersion != "") { const downloadUrl = "https://github.com/LLOneBot/LLOneBot/releases/download/v" + latestVersion + "/LLOneBot.zip"; const realUrl = mirrorGithubList[0] + downloadUrl; + /**const fileStream = fs.createWriteStream("F:\\TOOLS\\test.zip"); + https.get(realUrl, (res) => { + res.pipe(fileStream); + }) + */ } return false; } diff --git a/src/renderer/index.ts b/src/renderer/index.ts index edbd4b4..bad55be 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -41,7 +41,7 @@ async function onSettingWindowCreated(view: Element) { 正在检查LLOneBot版本中 - 重新发现 + 请稍后 @@ -315,7 +315,8 @@ async function onSettingWindowCreated(view: Element) { view.appendChild(node); }); // 更新逻辑 - const checkVersionFunc = (ResultVersion: CheckVersion) => { + async function checkVersionFunc(ResultVersion: CheckVersion) { + console.log(ResultVersion); if (ResultVersion.version === "") { view.querySelector(".llonebot-update-title").innerHTML = "检查更新失败"; view.querySelector(".llonebot-update-button").innerHTML = "点击重试"; @@ -328,7 +329,7 @@ async function onSettingWindowCreated(view: Element) { view.querySelector(".llonebot-update-title").innerHTML = "当前已是最新版本 V" + ResultVersion.version; view.querySelector(".llonebot-update-button").innerHTML = "无需更新"; } else { - view.querySelector(".llonebot-update-title").innerHTML = "已监测到最新版本 V" + ResultVersion.version; + view.querySelector(".llonebot-update-title").innerHTML = "已检测到最新版本 V" + ResultVersion.version; view.querySelector(".llonebot-update-button").innerHTML = "点击更新"; const update = async () => { view.querySelector(".llonebot-update-button").innerHTML = "正在更新中..."; From 63c2b95cbba2f8bee09ea1d02f6063f4f63057c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 19 Mar 2024 11:28:37 +0800 Subject: [PATCH 08/13] feat:download update --- src/common/utils/update.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/utils/update.ts b/src/common/utils/update.ts index 13a3f77..e29e17c 100644 --- a/src/common/utils/update.ts +++ b/src/common/utils/update.ts @@ -1,7 +1,9 @@ import { version } from "../../version"; import https from "node:https"; //import http from "node:http"; +import * as path from "node:path"; import * as fs from "node:fs"; +import { TEMP_DIR } from "."; export async function checkVersion() { const latestVersionText = await getRemoteVersion(); const latestVersion = latestVersionText.split("."); @@ -19,11 +21,11 @@ export async function updateLLOneBot() { if (latestVersion && latestVersion != "") { const downloadUrl = "https://github.com/LLOneBot/LLOneBot/releases/download/v" + latestVersion + "/LLOneBot.zip"; const realUrl = mirrorGithubList[0] + downloadUrl; - /**const fileStream = fs.createWriteStream("F:\\TOOLS\\test.zip"); + const filePath = path.join(TEMP_DIR, "./update-" + latestVersion + ".zip"); + const fileStream = fs.createWriteStream(filePath); https.get(realUrl, (res) => { res.pipe(fileStream); }) - */ } return false; } From 10c48a5b8676ef8cf066fa0a5a9ee13fe305220f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 19 Mar 2024 12:01:57 +0800 Subject: [PATCH 09/13] feat:check update --- manifest.json | 4 +- package-lock.json | 233 +++++++++++++++++++++++++++++++++++-- package.json | 2 +- src/common/utils/index.ts | 2 +- src/common/utils/update.ts | 37 +++++- 5 files changed, 261 insertions(+), 17 deletions(-) diff --git a/manifest.json b/manifest.json index c2fd582..c94e72e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { "manifest_version": 4, "type": "extension", - "name": "LLOneBot v3.16.1", + "name": "LLOneBot v3.16.0", "slug": "LLOneBot", "description": "LiteLoaderQQNT的OneBotApi,不支持商店在线更新", - "version": "3.16.1", + "version": "3.16.0", "icon": "./icon.jpg", "authors": [ { diff --git a/package-lock.json b/package-lock.json index cda8ff2..f865c6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "compressing": "^1.10.0", "express": "^4.18.2", "file-type": "^19.0.0", "fluent-ffmpeg": "^2.1.2", @@ -551,6 +552,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@eggjs/yauzl": { + "version": "2.11.0", + "resolved": "https://registry.npmmirror.com/@eggjs/yauzl/-/yauzl-2.11.0.tgz", + "integrity": "sha512-Jq+k2fCZJ3i3HShb0nxLUiAgq5pwo8JTT1TrH22JoehZQ0Nm2dvByGIja1NYfNyuE4Tx5/Dns5nVsBN/mlC8yg==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer2": "^1.2.0" + } + }, "node_modules/@electron/get": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", @@ -2151,6 +2161,47 @@ } ] }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -2281,15 +2332,33 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "engines": { "node": "*" } }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://mirrors.cloud.tencent.com/npm/buffer-from/-/buffer-from-1.1.2.tgz", @@ -2515,6 +2584,36 @@ "optional": true, "peer": true }, + "node_modules/compressing": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/compressing/-/compressing-1.10.0.tgz", + "integrity": "sha512-k2vpbZLaJoHe9euyUZjYYE8vOrbR19aU3HcWIYw5EBXiUs34ygfDVnXU+ubI41JXMriHutnoiu0ZFdwCkH6jPA==", + "dependencies": { + "@eggjs/yauzl": "^2.11.0", + "flushwritable": "^1.0.0", + "get-ready": "^1.0.0", + "iconv-lite": "^0.5.0", + "mkdirp": "^0.5.1", + "pump": "^3.0.0", + "streamifier": "^0.1.1", + "tar-stream": "^1.5.2", + "yazl": "^2.4.2" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/compressing/node_modules/iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz", @@ -2559,6 +2658,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://mirrors.cloud.tencent.com/npm/create-require/-/create-require-1.1.1.tgz", @@ -2813,7 +2917,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -3636,6 +3739,14 @@ "pend": "~1.2.0" } }, + "node_modules/fd-slicer2": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/fd-slicer2/-/fd-slicer2-1.2.0.tgz", + "integrity": "sha512-3lBUNUckhMZduCc4g+Pw4Ve16LD9vpX9b8qUkkKq2mgDRLYWzblszZH2luADnJqjJe+cypngjCuKRm/IW12rRw==", + "dependencies": { + "pend": "^1.2.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://mirrors.cloud.tencent.com/npm/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3738,6 +3849,11 @@ "node": ">=0.8.0" } }, + "node_modules/flushwritable": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/flushwritable/-/flushwritable-1.0.0.tgz", + "integrity": "sha512-3VELfuWCLVzt5d2Gblk8qcqFro6nuwvxwMzHaENVDHI7rxcBRtMCwTk/E9FXcgh+82DSpavPNDueA9+RxXJoFg==" + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://mirrors.cloud.tencent.com/npm/for-each/-/for-each-0.3.3.tgz", @@ -3763,6 +3879,11 @@ "node": ">= 0.6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -3859,6 +3980,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-ready": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/get-ready/-/get-ready-1.0.0.tgz", + "integrity": "sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==" + }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -4859,11 +4985,21 @@ "version": "1.2.8", "resolved": "https://mirrors.cloud.tencent.com/npm/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/module-error": { "version": "1.0.2", "resolved": "https://mirrors.cloud.tencent.com/npm/module-error/-/module-error-1.0.2.tgz", @@ -5052,7 +5188,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -5165,8 +5300,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "node_modules/picocolors": { "version": "1.0.0", @@ -5232,6 +5366,11 @@ "node": ">= 0.8.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5257,7 +5396,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -5833,6 +5971,14 @@ "node": ">= 0.8" } }, + "node_modules/streamifier": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/streamifier/-/streamifier-0.1.1.tgz", + "integrity": "sha512-zDgl+muIlWzXNsXeyUfOk9dChMjlpkq0DRsxujtYPgyJ676yQ8jEm6zzaaWHFDg5BNcLuif0eD2MTyJdZqXpdg==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5959,6 +6105,55 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tar-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/tar-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/terser": { "version": "5.28.1", "resolved": "https://mirrors.cloud.tencent.com/npm/terser/-/terser-5.28.1.tgz", @@ -5985,6 +6180,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -6528,8 +6728,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.16.0", @@ -6551,6 +6750,14 @@ } } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -6567,6 +6774,14 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://mirrors.cloud.tencent.com/npm/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index a3392fc..1ef7e71 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,11 @@ "author": "", "license": "ISC", "dependencies": { + "compressing": "^1.10.0", "express": "^4.18.2", "file-type": "^19.0.0", "fluent-ffmpeg": "^2.1.2", "level": "^8.0.1", - "node-stream-zip": "^1.15.0", "silk-wasm": "^3.2.3", "utf-8-validate": "^6.0.3", "uuid": "^9.0.1", diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 81ef39b..0eccb8c 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -9,7 +9,7 @@ export * from './qqpkg' export * from './update' export const DATA_DIR = global.LiteLoader.plugins["LLOneBot"].path.data; export const TEMP_DIR = path.join(DATA_DIR, "temp"); - +export const PLUGIN_DIR = global.LiteLoader.plugins["LLOneBot"].path.plugin; if (!fs.existsSync(TEMP_DIR)) { fs.mkdirSync(TEMP_DIR); } \ No newline at end of file diff --git a/src/common/utils/update.ts b/src/common/utils/update.ts index e29e17c..fefcc38 100644 --- a/src/common/utils/update.ts +++ b/src/common/utils/update.ts @@ -3,7 +3,8 @@ import https from "node:https"; //import http from "node:http"; import * as path from "node:path"; import * as fs from "node:fs"; -import { TEMP_DIR } from "."; +import { PLUGIN_DIR, TEMP_DIR } from "."; +import compressing from "compressing"; export async function checkVersion() { const latestVersionText = await getRemoteVersion(); const latestVersion = latestVersionText.split("."); @@ -23,9 +24,37 @@ export async function updateLLOneBot() { const realUrl = mirrorGithubList[0] + downloadUrl; const filePath = path.join(TEMP_DIR, "./update-" + latestVersion + ".zip"); const fileStream = fs.createWriteStream(filePath); - https.get(realUrl, (res) => { - res.pipe(fileStream); - }) + let downloadPromise = async function (filePath): Promise { + return new Promise((resolve, reject) => { + https.get(filePath, res => { + res.pipe(fileStream); + res.on('end', () => { + resolve(true); + }); + }).on('error', err => { + resolve(false); + }); + }); + } + if (!(await downloadPromise(realUrl))) { + // 下载异常 + return false; + } + let uncompressPromise = async function () { + return new Promise((resolve, reject) => { + compressing.zip.uncompress(filePath, PLUGIN_DIR).then(() => { + resolve(true); + }).catch((reason: any) => { + console.log(reason); + if (reason?.errno == -4082) { + resolve(true); + } + resolve(false); + }); + }); + } + const uncompressResult = await uncompressPromise(); + return uncompressResult; } return false; } From aad165ce5ede024d2bf3e6fd07ad4e191c44ebe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 19 Mar 2024 12:03:17 +0800 Subject: [PATCH 10/13] chore: remove test version --- manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index c94e72e..c2fd582 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { "manifest_version": 4, "type": "extension", - "name": "LLOneBot v3.16.0", + "name": "LLOneBot v3.16.1", "slug": "LLOneBot", "description": "LiteLoaderQQNT的OneBotApi,不支持商店在线更新", - "version": "3.16.0", + "version": "3.16.1", "icon": "./icon.jpg", "authors": [ { From eccf5885690ab4b1d67d6e83eeb4f2be84da2b99 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 19 Mar 2024 12:33:08 +0800 Subject: [PATCH 11/13] feat: api /get_group_msg_history --- src/ntqqapi/api/msg.ts | 11 ++++++ src/ntqqapi/ntcall.ts | 2 +- .../action/go-cqhttp/GetGroupMsgHistory.ts | 34 +++++++++++++++++++ src/onebot11/action/index.ts | 2 ++ src/onebot11/action/types.ts | 1 + 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts diff --git a/src/ntqqapi/api/msg.ts b/src/ntqqapi/api/msg.ts index bfca2be..ec79de3 100644 --- a/src/ntqqapi/api/msg.ts +++ b/src/ntqqapi/api/msg.ts @@ -23,6 +23,17 @@ export class NTQQMsgApi { args: [{peer:{peerUid: groupCode, chatType: ChatType.group}, cnt: 20}, null] }) } + static async getMsgHistory(peer: Peer, msgId: string, count: number) { + return await callNTQQApi({ + methodName: NTQQApiMethod.HISTORY_MSG, + args: [{ + peer, + msgId, + cnt: count, + queryOrder: true, + }, null] + }) + } static async fetchRecentContact(){ await callNTQQApi({ methodName: NTQQApiMethod.RECENT_CONTACT, diff --git a/src/ntqqapi/ntcall.ts b/src/ntqqapi/ntcall.ts index 20c35c6..15b86a2 100644 --- a/src/ntqqapi/ntcall.ts +++ b/src/ntqqapi/ntcall.ts @@ -17,7 +17,7 @@ export enum NTQQApiClass { export enum NTQQApiMethod { RECENT_CONTACT = "nodeIKernelRecentContactService/fetchAndSubscribeABatchOfRecentContact", ADD_ACTIVE_CHAT = "nodeIKernelMsgService/getAioFirstViewLatestMsgsAndAddActiveChat", // 激活群助手内的聊天窗口,这样才能收到消息 - ADD_ACTIVE_CHAT_2 = "nodeIKernelMsgService/getMsgsIncludeSelfAndAddActiveChat", + HISTORY_MSG = "nodeIKernelMsgService/getMsgsIncludeSelfAndAddActiveChat", LIKE_FRIEND = "nodeIKernelProfileLikeService/setBuddyProfileLike", SELF_INFO = "fetchAuthData", FRIENDS = "nodeIKernelBuddyService/getBuddyList", diff --git a/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts b/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts new file mode 100644 index 0000000..05ae6b5 --- /dev/null +++ b/src/onebot11/action/go-cqhttp/GetGroupMsgHistory.ts @@ -0,0 +1,34 @@ +import BaseAction from "../BaseAction"; +import {OB11Message, OB11User} from "../../types"; +import {groups} from "../../../common/data"; +import {ActionName} from "../types"; +import {ChatType} from "../../../ntqqapi/types"; +import {dbUtil} from "../../../common/db"; +import {NTQQMsgApi} from "../../../ntqqapi/api/msg"; +import {OB11Constructor} from "../../constructor"; +import {log} from "../../../common/utils"; + + +interface Payload { + group_id: number + message_seq: number +} + +export default class GoCQHTTPGetGroupMsgHistory extends BaseAction { + actionName = ActionName.GoCQHTTP_GetGroupMsgHistory + + protected async _handle(payload: Payload): Promise { + const group = groups.find(group => group.groupCode === payload.group_id.toString()) + if (!group) { + throw `群${payload.group_id}不存在` + } + const startMsgId = (await dbUtil.getMsgByShortId(payload.message_seq))?.msgId || "0" + // log("startMsgId", startMsgId) + let msgList = (await NTQQMsgApi.getMsgHistory({chatType: ChatType.group, peerUid: group.groupCode}, startMsgId, 20)).msgList + await Promise.all(msgList.map(async msg => { + msg.msgShortId = await dbUtil.addMsg(msg) + })) + const ob11MsgList = await Promise.all(msgList.map(msg=>OB11Constructor.message(msg))) + return ob11MsgList + } +} \ No newline at end of file diff --git a/src/onebot11/action/index.ts b/src/onebot11/action/index.ts index def74d6..8c65113 100644 --- a/src/onebot11/action/index.ts +++ b/src/onebot11/action/index.ts @@ -37,6 +37,7 @@ import {GetConfigAction, SetConfigAction} from "./llonebot/Config"; import GetGroupAddRequest from "./llonebot/GetGroupAddRequest"; import SetQQAvatar from './llonebot/SetQQAvatar' import GoCQHTTPDownloadFile from "./go-cqhttp/DownloadFile"; +import GoCQHTTPGetGroupMsgHistory from "./go-cqhttp/GetGroupMsgHistory"; export const actionHandlers = [ new Debug(), @@ -77,6 +78,7 @@ export const actionHandlers = [ new GetGuildList(), new GoCQHTTPMarkMsgAsRead(), new GoCQHTTPUploadGroupFile(), + new GoCQHTTPGetGroupMsgHistory(), ] diff --git a/src/onebot11/action/types.ts b/src/onebot11/action/types.ts index a00bf13..6ffedc0 100644 --- a/src/onebot11/action/types.ts +++ b/src/onebot11/action/types.ts @@ -55,4 +55,5 @@ export enum ActionName { GoCQHTTP_MarkMsgAsRead = "mark_msg_as_read", GoCQHTTP_UploadGroupFile = "upload_group_file", GoCQHTTP_DownloadFile = "download_file", + GoCQHTTP_GetGroupMsgHistory = "get_group_msg_history", } \ No newline at end of file From 3a964af0b01cda2b320d72213d0d2882e112de23 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 19 Mar 2024 14:36:58 +0800 Subject: [PATCH 12/13] refactor: http download function --- manifest.json | 4 +- package-lock.json | 13 ---- src/common/utils/file.ts | 24 ++++++- src/common/utils/index.ts | 2 +- src/common/utils/{update.ts => upgrade.ts} | 80 ++++++++++------------ src/main/main.ts | 4 +- src/version.ts | 2 +- 7 files changed, 65 insertions(+), 64 deletions(-) rename src/common/utils/{update.ts => upgrade.ts} (50%) diff --git a/manifest.json b/manifest.json index c2fd582..c94e72e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { "manifest_version": 4, "type": "extension", - "name": "LLOneBot v3.16.1", + "name": "LLOneBot v3.16.0", "slug": "LLOneBot", "description": "LiteLoaderQQNT的OneBotApi,不支持商店在线更新", - "version": "3.16.1", + "version": "3.16.0", "icon": "./icon.jpg", "authors": [ { diff --git a/package-lock.json b/package-lock.json index f865c6d..dc3d75e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "file-type": "^19.0.0", "fluent-ffmpeg": "^2.1.2", "level": "^8.0.1", - "node-stream-zip": "^1.15.0", "silk-wasm": "^3.2.3", "utf-8-validate": "^6.0.3", "uuid": "^9.0.1", @@ -5067,18 +5066,6 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, - "node_modules/node-stream-zip": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", - "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", - "engines": { - "node": ">=0.12.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/antelle" - } - }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", diff --git a/src/common/utils/file.ts b/src/common/utils/file.ts index e7cc046..397d495 100644 --- a/src/common/utils/file.ts +++ b/src/common/utils/file.ts @@ -9,6 +9,8 @@ import {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 ClientRequestConstructorOptions = Electron.ClientRequestConstructorOptions; export function isGIF(path: string) { const buffer = Buffer.alloc(4); @@ -79,7 +81,7 @@ export function checkFfmpeg(newPath: string = null): Promise { resolve(true); } }) - }catch (e) { + } catch (e) { resolve(false); } }); @@ -268,6 +270,26 @@ export function calculateFileMD5(filePath: string): Promise { }); } +export function httpDownload(options: ClientRequestConstructorOptions | string): Promise { + let chunks: Buffer[] = []; + let netRequest = net.request(options) + return new Promise((resolve, reject) => { + netRequest.on("response", (response) => { + if (!(response.statusCode >= 200 && response.statusCode < 300)) { + return reject(new Error(`下载失败,状态码${response.statusCode}`)) + } + response.on("data", (chunk) => { + chunks.push(chunk); + }).on("end", () => { + resolve(Buffer.concat(chunks)); + }) + }).on("error", (err) => { + reject(err); + }) + netRequest.end() + }) +} + type Uri2LocalRes = { success: boolean, errMsg: string, diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 0eccb8c..58c3afa 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -6,7 +6,7 @@ export * from './helper' export * from './log' export * from './qqlevel' export * from './qqpkg' -export * from './update' +export * from './upgrade' export const DATA_DIR = global.LiteLoader.plugins["LLOneBot"].path.data; export const TEMP_DIR = path.join(DATA_DIR, "temp"); export const PLUGIN_DIR = global.LiteLoader.plugins["LLOneBot"].path.plugin; diff --git a/src/common/utils/update.ts b/src/common/utils/upgrade.ts similarity index 50% rename from src/common/utils/update.ts rename to src/common/utils/upgrade.ts index fefcc38..97b613a 100644 --- a/src/common/utils/update.ts +++ b/src/common/utils/upgrade.ts @@ -1,46 +1,50 @@ -import { version } from "../../version"; -import https from "node:https"; -//import http from "node:http"; +import {version} from "../../version"; import * as path from "node:path"; import * as fs from "node:fs"; -import { PLUGIN_DIR, TEMP_DIR } from "."; +import {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() { 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 }; + return {result: false, version: latestVersionText}; } } - return { result: true, version: version }; + return {result: true, version: version}; } -export async function updateLLOneBot() { - let mirrorGithubList = ["https://mirror.ghproxy.com/"]; + +export async function upgradeLLOneBot() { const latestVersion = await getRemoteVersion(); if (latestVersion && latestVersion != "") { const downloadUrl = "https://github.com/LLOneBot/LLOneBot/releases/download/v" + latestVersion + "/LLOneBot.zip"; - const realUrl = mirrorGithubList[0] + downloadUrl; + const mirrorUrl = downloadMirrorHosts[0] + downloadUrl; const filePath = path.join(TEMP_DIR, "./update-" + latestVersion + ".zip"); const fileStream = fs.createWriteStream(filePath); - let downloadPromise = async function (filePath): Promise { - return new Promise((resolve, reject) => { - https.get(filePath, res => { - res.pipe(fileStream); - res.on('end', () => { - resolve(true); - }); - }).on('error', err => { - resolve(false); - }); - }); + let downloadSuccess = false; + // 多镜像下载 + for(const mirrorGithub of downloadMirrorHosts){ + try{ + const buffer = await httpDownload(mirrorGithub + downloadUrl); + fs.writeFileSync(filePath, buffer) + downloadSuccess = true; + break; + }catch (e) { + log("llonebot upgrade error", e); + } } - if (!(await downloadPromise(realUrl))) { - // 下载异常 + if (!downloadSuccess){ + log("llonebot upgrade error", "download failed"); return false; } - let uncompressPromise = async function () { + let uncompressedPromise = async function () { return new Promise((resolve, reject) => { compressing.zip.uncompress(filePath, PLUGIN_DIR).then(() => { resolve(true); @@ -53,16 +57,16 @@ export async function updateLLOneBot() { }); }); } - const uncompressResult = await uncompressPromise(); + const uncompressResult = await uncompressedPromise(); return uncompressResult; } return false; } + export async function getRemoteVersion() { - let mirrorGithubList = ["https://521github.com"]; let Version = ""; - for (let i = 0; i < mirrorGithubList.length; i++) { - let mirrorGithub = mirrorGithubList[i]; + for (let i = 0; i < checkVersionMirrorHosts.length; i++) { + let mirrorGithub = checkVersionMirrorHosts[i]; let tVersion = await getRemoteVersionByMirror(mirrorGithub); if (tVersion && tVersion != "") { Version = tVersion; @@ -71,29 +75,17 @@ export async function getRemoteVersion() { } return Version; } + export async function getRemoteVersionByMirror(mirrorGithub: string) { let releasePage = "error"; - let reqPromise = async function (): Promise { - return new Promise((resolve, reject) => { - https.get(mirrorGithub + "/LLOneBot/LLOneBot/releases", res => { - let list = []; - res.on('data', chunk => { - list.push(chunk); - }); - res.on('end', () => { - resolve(Buffer.concat(list).toString()); - }); - }).on('error', err => { - reject(); - }); - }); - } + try { - releasePage = await reqPromise(); + releasePage = (await httpDownload(mirrorGithub + "/LLOneBot/LLOneBot/releases")).toString(); + log("releasePage", releasePage); if (releasePage === "error") return ""; return releasePage.match(new RegExp('(?<=(tag/v)).*?(?=("))'))[0]; + } catch { } - catch { } return ""; } \ No newline at end of file diff --git a/src/main/main.ts b/src/main/main.ts index 352d0ad..42257d0 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -41,7 +41,7 @@ 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, updateLLOneBot} from "../common/utils/update"; +import {checkVersion, upgradeLLOneBot} from "../common/utils/upgrade"; import {checkFfmpeg} from "../common/utils/file"; import {log} from "../common/utils/log"; import {getConfigUtil} from "../common/config"; @@ -57,7 +57,7 @@ function onLoad() { return checkVersion(); }); ipcMain.handle(CHANNEL_UPDATE, async (event, arg) => { - return updateLLOneBot(); + return upgradeLLOneBot(); }); ipcMain.handle(CHANNEL_SELECT_FILE, async (event, arg) => { const selectPath = new Promise((resolve, reject) => { diff --git a/src/version.ts b/src/version.ts index 42fc3ff..93bafb5 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const version = "3.16.1" \ No newline at end of file +export const version = "3.16.0" \ No newline at end of file From 37c4f021184fcf155745840c15b0610c10bcdf35 Mon Sep 17 00:00:00 2001 From: linyuchen Date: Tue, 19 Mar 2024 16:32:12 +0800 Subject: [PATCH 13/13] refactor: upgrade --- src/common/utils/file.ts | 86 ++++++++++++------- src/common/utils/upgrade.ts | 18 ++-- src/onebot11/action/go-cqhttp/DownloadFile.ts | 11 +-- 3 files changed, 70 insertions(+), 45 deletions(-) diff --git a/src/common/utils/file.ts b/src/common/utils/file.ts index 397d495..c50b68d 100644 --- a/src/common/utils/file.ts +++ b/src/common/utils/file.ts @@ -1,4 +1,5 @@ import fs from "fs"; +import fsPromise from "fs/promises"; import crypto from "crypto"; import ffmpeg from "fluent-ffmpeg"; import util from "util"; @@ -10,7 +11,7 @@ import {getConfigUtil} from "../config"; import {dbUtil} from "../db"; import * as fileType from "file-type"; import {net} from "electron"; -import ClientRequestConstructorOptions = Electron.ClientRequestConstructorOptions; +import ClientRequestConstructorOptions = Electron.Main.ClientRequestConstructorOptions; export function isGIF(path: string) { const buffer = Buffer.alloc(4); @@ -270,24 +271,34 @@ export function calculateFileMD5(filePath: string): Promise { }); } -export function httpDownload(options: ClientRequestConstructorOptions | string): Promise { +export interface HttpDownloadOptions { + url: string; + headers?: Record | string; +} +export async function httpDownload(options: string | HttpDownloadOptions): Promise { let chunks: Buffer[] = []; - let netRequest = net.request(options) - return new Promise((resolve, reject) => { - netRequest.on("response", (response) => { - if (!(response.statusCode >= 200 && response.statusCode < 300)) { - return reject(new Error(`下载失败,状态码${response.statusCode}`)) + let url: string; + let headers: Record = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36" + }; + if (typeof options === "string") { + url = options; + } else { + url = options.url; + if (options.headers) { + if (typeof options.headers === "string") { + headers = JSON.parse(options.headers); + } else { + headers = options.headers; } - response.on("data", (chunk) => { - chunks.push(chunk); - }).on("end", () => { - resolve(Buffer.concat(chunks)); - }) - }).on("error", (err) => { - reject(err); - }) - netRequest.end() - }) + } + } + const fetchRes = await net.fetch(url, headers); + if (!fetchRes.ok) throw new Error(`下载文件失败: ${fetchRes.statusText}`) + + const blob = await fetchRes.blob(); + let buffer = await blob.arrayBuffer(); + return Buffer.from(buffer); } type Uri2LocalRes = { @@ -334,19 +345,13 @@ export async function uri2local(uri: string, fileName: string = null): Promise((resolve, reject) => { - compressing.zip.uncompress(filePath, PLUGIN_DIR).then(() => { + compressing.zip.uncompress(filePath, temp_ver_dir).then(() => { resolve(true); }).catch((reason: any) => { - console.log(reason); + log("llonebot upgrade failed, ", reason); if (reason?.errno == -4082) { resolve(true); } @@ -57,8 +56,11 @@ export async function upgradeLLOneBot() { }); }); } - const uncompressResult = await uncompressedPromise(); - return uncompressResult; + const uncompressedResult = await uncompressedPromise(); + // 复制文件 + await copyFolder(temp_ver_dir, PLUGIN_DIR); + + return uncompressedResult; } return false; } @@ -81,7 +83,7 @@ export async function getRemoteVersionByMirror(mirrorGithub: string) { try { releasePage = (await httpDownload(mirrorGithub + "/LLOneBot/LLOneBot/releases")).toString(); - log("releasePage", releasePage); + // log("releasePage", releasePage); if (releasePage === "error") return ""; return releasePage.match(new RegExp('(?<=(tag/v)).*?(?=("))'))[0]; } catch { diff --git a/src/onebot11/action/go-cqhttp/DownloadFile.ts b/src/onebot11/action/go-cqhttp/DownloadFile.ts index 1444ad8..4ca1204 100644 --- a/src/onebot11/action/go-cqhttp/DownloadFile.ts +++ b/src/onebot11/action/go-cqhttp/DownloadFile.ts @@ -2,7 +2,7 @@ import BaseAction from "../BaseAction"; import {ActionName} from "../types"; import fs from "fs"; import {join as joinPath} from "node:path"; -import {calculateFileMD5, TEMP_DIR} from "../../../common/utils"; +import {calculateFileMD5, httpDownload, TEMP_DIR} from "../../../common/utils"; import {v4 as uuid4} from "uuid"; interface Payload { @@ -29,12 +29,7 @@ export default class GoCQHTTPDownloadFile extends BaseAction { const headers = {}; if (typeof headersIn == 'string') { headersIn = headersIn.split('[\\r\\n]');