From f585bb4d7de74424fc5a24c15ddc29ef64797e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=8C=E8=90=8C=E5=93=92=E8=B5=AB=E8=90=9D?= Date: Thu, 10 Aug 2023 05:30:46 -0700 Subject: [PATCH] :bug: Fix: add local path picbed into delete api of http server --- src/main/apis/app/uploader/apis.ts | 76 +++++++++++++++++++++++------- src/main/events/ipcList.ts | 68 ++------------------------ src/main/lifeCycle/index.ts | 8 +--- src/main/manage/apis/aliyun.ts | 20 ++++---- src/main/manage/manageApi.ts | 3 +- src/main/manage/utils/constants.ts | 58 +++++++++++------------ src/main/manage/utils/logger.ts | 44 ++++++++--------- src/main/migrate/index.ts | 61 ------------------------ src/main/server/index.ts | 7 +-- src/main/server/routerManager.ts | 2 +- src/main/utils/deleteFunc.ts | 64 +++++++++++++++++++++++++ src/renderer/apis/allApi.ts | 35 +++++++------- src/renderer/apis/awss3.ts | 10 ++-- src/renderer/apis/imgur.ts | 22 ++++----- src/renderer/apis/local.ts | 2 +- src/renderer/apis/qiniu.ts | 2 +- src/renderer/layouts/Main.vue | 2 +- src/renderer/pages/Gallery.vue | 4 +- src/universal/utils/static.ts | 2 + 19 files changed, 228 insertions(+), 262 deletions(-) delete mode 100644 src/main/migrate/index.ts create mode 100644 src/main/utils/deleteFunc.ts diff --git a/src/main/apis/app/uploader/apis.ts b/src/main/apis/app/uploader/apis.ts index 05f8e73..2badb13 100644 --- a/src/main/apis/app/uploader/apis.ts +++ b/src/main/apis/app/uploader/apis.ts @@ -19,6 +19,11 @@ import picgo from '@core/picgo' import GuiApi from '../../gui' import uploader from '.' import { IWindowList } from '#/types/enum' +import { picBedsCanbeDeleted } from '#/utils/static' +import path from 'path' +import SSHClient from '~/main/utils/sshClient' +import { ISftpPlistConfig } from 'piclist' +import { getRawData } from '~/renderer/utils/common' const handleClipboardUploading = async (): Promise => { const useBuiltinClipboard = db.get('settings.useBuiltinClipboard') === undefined ? true : !!db.get('settings.useBuiltinClipboard') @@ -125,9 +130,23 @@ export const uploadChoosedFiles = async (webContents: WebContents, files: IFileW } } +async function deleteWebdavFile (config: ISftpPlistConfig, fileName: string) { + try { + const client = SSHClient.instance + await client.connect(config) + const uploadPath = `/${(config.uploadPath || '')}/`.replace(/\/+/g, '/') + const remote = path.join(uploadPath, fileName) + const deleteResult = await client.deleteFile(remote) + client.close() + return deleteResult + } catch (err: any) { + console.error(err) + return false + } +} + export const deleteChoosedFiles = async (list: ImgInfo[]): Promise => { const result = [] - const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist'] for (const item of list) { if (item.id) { try { @@ -135,23 +154,44 @@ export const deleteChoosedFiles = async (list: ImgInfo[]): Promise => const file = await dbStore.removeById(item.id) if (await picgo.getConfig('settings.deleteCloudFile')) { if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) { - setTimeout(() => { - ALLApi.delete(item).then((value: boolean) => { - if (value) { - const notification = new Notification({ - title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'), - body: T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED') - }) - notification.show() - } else { - const notification = new Notification({ - title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'), - body: T('GALLERY_SYNC_DELETE_NOTICE_FAILED') - }) - notification.show() - } - }) - }, 0) + if (item.type === 'webdavplist') { + const { fileName, config } = item + setTimeout(() => { + deleteWebdavFile(getRawData(config), fileName || '').then((value: boolean) => { + if (value) { + const notification = new Notification({ + title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'), + body: T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED') + }) + notification.show() + } else { + const notification = new Notification({ + title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'), + body: T('GALLERY_SYNC_DELETE_NOTICE_FAILED') + }) + notification.show() + } + }) + }, 0) + } else { + setTimeout(() => { + ALLApi.delete(item).then((value: boolean) => { + if (value) { + const notification = new Notification({ + title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'), + body: T('GALLERY_SYNC_DELETE_NOTICE_SUCCEED') + }) + notification.show() + } else { + const notification = new Notification({ + title: T('MANAGE_BUCKET_BATCH_DELETE_ERROR_MSG_MSG2'), + body: T('GALLERY_SYNC_DELETE_NOTICE_FAILED') + }) + notification.show() + } + }) + }, 0) + } } } setTimeout(() => { diff --git a/src/main/events/ipcList.ts b/src/main/events/ipcList.ts index 8483211..b3054cb 100644 --- a/src/main/events/ipcList.ts +++ b/src/main/events/ipcList.ts @@ -88,15 +88,7 @@ import SSHClient from '../utils/sshClient' // Sftp 配置类型声明 import { ISftpPlistConfig } from 'piclist' -// AWS S3 相关模块 -import { S3Client, DeleteObjectCommand, S3ClientConfig } from '@aws-sdk/client-s3' -import { NodeHttpHandler } from '@smithy/node-http-handler' -import http, { AgentOptions } from 'http' -import https from 'https' - -// 工具函数 -import { getAgent } from '../manage/utils/common' -import logger from '@core/picgo/logger' +import { removeFileFromS3InMain } from '~/main/utils/deleteFunc' const STORE_PATH = app.getPath('userData') @@ -192,62 +184,8 @@ export default { }) ipcMain.handle('delete-aws-s3-file', async (_evt: IpcMainInvokeEvent, configMap: IStringKeyMap) => { - try { - const { imgUrl, config: { accessKeyID, secretAccessKey, bucketName, region, endpoint, pathStyleAccess, rejectUnauthorized, proxy } } = configMap - const url = new URL(!/^https?:\/\//.test(imgUrl) ? `http://${imgUrl}` : imgUrl) - const fileKey = url.pathname.replace(/^\/+/, '') - const endpointUrl: string | undefined = endpoint - ? /^https?:\/\//.test(endpoint) - ? endpoint - : `http://${endpoint}` - : undefined - const sslEnabled = endpointUrl ? endpointUrl.startsWith('https') : true - const agent = getAgent(proxy, sslEnabled) - const commonOptions: AgentOptions = { - keepAlive: true, - keepAliveMsecs: 1000, - scheduling: 'lifo' as 'lifo' | 'fifo' | undefined - } - const extraOptions = sslEnabled ? { rejectUnauthorized: !!rejectUnauthorized } : {} - const handler = sslEnabled - ? new NodeHttpHandler({ - httpsAgent: agent.https - ? agent.https - : new https.Agent({ - ...commonOptions, - ...extraOptions - }) - }) - : new NodeHttpHandler({ - httpAgent: agent.http - ? agent.http - : new http.Agent({ - ...commonOptions, - ...extraOptions - }) - }) - const s3Options: S3ClientConfig = { - credentials: { - accessKeyId: accessKeyID, - secretAccessKey - }, - endpoint: endpointUrl, - tls: sslEnabled, - forcePathStyle: pathStyleAccess, - region, - requestHandler: handler - } - const client = new S3Client(s3Options) - const command = new DeleteObjectCommand({ - Bucket: bucketName, - Key: fileKey - }) - const result = await client.send(command) - return result.$metadata.httpStatusCode === 204 - } catch (err: any) { - logger.error(err) - return false - } + const result = await removeFileFromS3InMain(configMap) + return result }) // migrate from PicGo diff --git a/src/main/lifeCycle/index.ts b/src/main/lifeCycle/index.ts index 0688686..fa927d4 100644 --- a/src/main/lifeCycle/index.ts +++ b/src/main/lifeCycle/index.ts @@ -15,10 +15,6 @@ import ipcList from '~/main/events/ipcList' import busEventList from '~/main/events/busEventList' import { IRemoteNoticeTriggerHook, IWindowList } from '#/types/enum' import windowManager from 'apis/app/window/windowManager' -import { - updateShortKeyFromVersion212, - migrateGalleryFromVersion230 -} from '~/main/migrate' import { uploadChoosedFiles, uploadClipboardFiles @@ -29,7 +25,7 @@ import { import server from '~/main/server/index' import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler' import { getUploadFiles } from '~/main/utils/handleArgv' -import db, { GalleryDB } from '~/main/apis/core/datastore' +import db from '~/main/apis/core/datastore' import bus from '@core/bus' import logger from 'apis/core/picgo/logger' import picgo from 'apis/core/picgo' @@ -135,8 +131,6 @@ class LifeCycle { UpDownTaskQueue.getInstance() manageIpcList.listen() busEventList.listen() - updateShortKeyFromVersion212(db, db.get('settings.shortKey')) - await migrateGalleryFromVersion230(db, GalleryDB.getInstance(), picgo) } private onReady () { diff --git a/src/main/manage/apis/aliyun.ts b/src/main/manage/apis/aliyun.ts index 8d772e4..1d122ea 100644 --- a/src/main/manage/apis/aliyun.ts +++ b/src/main/manage/apis/aliyun.ts @@ -122,7 +122,7 @@ class AliyunApi { marker, 'max-keys': 1000 }) as IStringKeyMap - if (res.res.statusCode !== 200 || !res.buckets) return { result: [], isTruncated: false } + if (res?.res?.statusCode !== 200 || !res?.buckets) return { result: [], isTruncated: false } const formattedBuckets = res.buckets.map((item: OSS.Bucket) => ({ Name: item.name, Location: item.region, @@ -161,7 +161,7 @@ class AliyunApi { } }) - if (res.status === 200) { + if (res?.status === 200) { const parser = new XMLParser() const result = parser.parse(res.data) @@ -207,7 +207,7 @@ class AliyunApi { dataRedundancyType: 'LRS', timeout: this.timeOut }) - return res && res.res.status === 200 + return res?.res?.status === 200 } async getBucketListRecursively (configMap: IStringKeyMap): Promise { @@ -238,8 +238,8 @@ class AliyunApi { }, { timeout: this.timeOut }) - if (res && res.res.statusCode === 200) { - res.objects && res.objects.forEach((item: OSS.ObjectMeta) => { + if (res?.res?.statusCode === 200) { + res?.objects?.forEach((item: OSS.ObjectMeta) => { item.size !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix)) }) window.webContents.send(refreshDownloadFileTransferList, result) @@ -286,11 +286,11 @@ class AliyunApi { }, { timeout: this.timeOut }) - if (res && res.res.statusCode === 200) { - res.prefixes && res.prefixes.forEach((item: string) => { + if (res?.res?.statusCode === 200) { + res?.prefixes?.forEach((item: string) => { result.fullList.push(this.formatFolder(item, slicedPrefix)) }) - res.objects && res.objects.forEach((item: OSS.ObjectMeta) => { + res?.objects?.forEach((item: OSS.ObjectMeta) => { item.size !== 0 && result.fullList.push(this.formatFile(item, slicedPrefix, urlPrefix)) }) window.webContents.send('refreshFileTransferList', result) @@ -521,7 +521,7 @@ class AliyunApi { } ).then((res: any) => { const id = `${bucketName}-${region}-${key}-${filePath}` - if (res && res.res.statusCode === 200) { + if (res?.res?.statusCode === 200) { instance.updateUploadTask({ id, progress: 100, @@ -561,7 +561,7 @@ class AliyunApi { const { bucketName, region, key } = configMap const client = this.getNewCtx(region, bucketName) const res = await client.put(key, Buffer.from('')) as any - return res && res.res.statusCode === 200 + return res?.res?.statusCode === 200 } /** diff --git a/src/main/manage/manageApi.ts b/src/main/manage/manageApi.ts index f4e72f2..3bf1a80 100644 --- a/src/main/manage/manageApi.ts +++ b/src/main/manage/manageApi.ts @@ -104,9 +104,8 @@ export class ManageApi extends EventEmitter implements ManageApiType { getConfig (name?: string): T { if (!name) { return this._config as unknown as T - } else { - return get(this._config, name) } + return get(this._config, name) } saveConfig (config: IStringKeyMap): void { diff --git a/src/main/manage/utils/constants.ts b/src/main/manage/utils/constants.ts index 716e296..24178c5 100644 --- a/src/main/manage/utils/constants.ts +++ b/src/main/manage/utils/constants.ts @@ -1,32 +1,33 @@ const AliyunAreaCodeName : IStringKeyMap = { - 'oss-cn-hangzhou': '华东1(杭州)', - 'oss-cn-shanghai': '华东2(上海)', - 'oss-cn-nanjing': '华东5(南京本地地域)', - 'oss-cn-fuzhou': '华东6(福州本地地域)', - 'oss-cn-qingdao': '华北1(青岛)', - 'oss-cn-beijing': '华北2(北京)', - 'oss-cn-zhangjiakou': '华北3(张家口)', - 'oss-cn-huhehaote': '华北5(呼和浩特)', - 'oss-cn-wulanchabu': '华北6(乌兰察布)', - 'oss-cn-shenzhen': '华南1(深圳)', - 'oss-cn-heyuan': '华南2(河源)', - 'oss-cn-guangzhou': '华南3(广州)', - 'oss-cn-chengdu': '西南1(成都)', - 'oss-cn-hongkong': '中国(香港)', - 'oss-us-west-1': '美国(硅谷)', - 'oss-us-east-1': '美国(弗吉尼亚)', - 'oss-ap-northeast-1': '日本(东京)', - 'oss-ap-northeast-2': '韩国(首尔)', + 'oss-cn-hangzhou': '华东1(杭州)', + 'oss-cn-shanghai': '华东2(上海)', + 'oss-cn-nanjing': '华东5(南京)', + 'oss-cn-fuzhou': '华东6(福州)', + 'oss-cn-qingdao': '华北1(青岛)', + 'oss-cn-beijing': '华北2(北京)', + 'oss-cn-zhangjiakou': '华北3(张家口)', + 'oss-cn-huhehaote': '华北5(呼和浩特)', + 'oss-cn-wulanchabu': '华北6(乌兰察布)', + 'oss-cn-shenzhen': '华南1(深圳)', + 'oss-cn-heyuan': '华南2(河源)', + 'oss-cn-guangzhou': '华南3(广州)', + 'oss-cn-chengdu': '西南1(成都)', + 'oss-cn-hongkong': '中国香港', + 'oss-us-west-1': '美国(硅谷)', + 'oss-us-east-1': '美国(弗吉尼亚)', + 'oss-ap-northeast-1': '日本(东京)', + 'oss-ap-northeast-2': '韩国(首尔)', 'oss-ap-southeast-1': '新加坡', - 'oss-ap-southeast-2': '澳大利亚(悉尼)', - 'oss-ap-southeast-3': '马来西亚(吉隆坡)', - 'oss-ap-southeast-5': '印度尼西亚(雅加达)', - 'oss-ap-southeast-6': '菲律宾(马尼拉)', - 'oss-ap-southeast-7': '泰国(曼谷)', - 'oss-ap-south-1': '印度(孟买)', - 'oss-eu-central-1': '德国(法兰克福)', - 'oss-eu-west-1': '英国(伦敦)', - 'oss-me-east-1': '阿联酋(迪拜)' + 'oss-ap-southeast-2': '澳大利亚(悉尼)', + 'oss-ap-southeast-3': '马来西亚(吉隆坡)', + 'oss-ap-southeast-5': '印度尼西亚(雅加达)', + 'oss-ap-southeast-6': '菲律宾(马尼拉)', + 'oss-ap-southeast-7': '泰国(曼谷)', + 'oss-ap-south-1': '印度(孟买)', + 'oss-eu-central-1': '德国(法兰克福)', + 'oss-eu-west-1': '英国(伦敦)', + 'oss-me-east-1': '阿联酋(迪拜)', + 'oss-rg-china-mainland': '无地域属性' } const QiniuAreaCodeName : IStringKeyMap = { @@ -61,8 +62,7 @@ const TencentAreaCodeName : IStringKeyMap = { 'na-ashburn': '弗吉尼亚(美东)', 'na-toronto': '多伦多', 'sa-saopaulo': '圣保罗', - 'eu-frankfurt': '法兰克福', - 'eu-moscow': '莫斯科' + 'eu-frankfurt': '法兰克福' } export { AliyunAreaCodeName, QiniuAreaCodeName, TencentAreaCodeName } diff --git a/src/main/manage/utils/logger.ts b/src/main/manage/utils/logger.ts index 58991c3..6e24f24 100644 --- a/src/main/manage/utils/logger.ts +++ b/src/main/manage/utils/logger.ts @@ -92,30 +92,9 @@ export class ManageLogger implements ILogger { ): void { try { if (this.checkLogLevel(type, this.logLevel)) { - let log = `${dayjs().format( - 'YYYY-MM-DD HH:mm:ss' - )} [PicList ${type.toUpperCase()}] ` + let log = `${dayjs().format('YYYY-MM-DD HH:mm:ss')} [PicList ${type.toUpperCase()}] ` msg.forEach((item: ILogArgvTypeWithError) => { - if (item instanceof Error && type === 'error') { - log += `\n------Error Stack Begin------\n${util.format( - item?.stack - )}\n-------Error Stack End------- ` - } else { - if (typeof item === 'object') { - if (item?.stack) { - log = log + `\n------Error Stack Begin------\n${util.format( - item.stack - )}\n-------Error Stack End------- ` - } - item = JSON.stringify(item, (key, value) => { - if (key === 'stack') { - return undefined - } - return value - }, 2) - } - log += `${item as string} ` - } + log += this.formatLogItem(item, type) }) log += '\n' fs.appendFileSync(logPath, log) @@ -125,6 +104,22 @@ export class ManageLogger implements ILogger { } } + private formatLogItem (item: ILogArgvTypeWithError, type: string): string { + let result = '' + if (item instanceof Error && type === 'error') { + result += `\n------Error Stack Begin------\n${util.format(item?.stack)}\n-------Error Stack End------- ` + } else { + if (typeof item === 'object') { + if (item?.stack) { + result += `\n------Error Stack Begin------\n${util.format(item.stack)}\n-------Error Stack End------- ` + } + item = JSON.stringify(item, (key, value) => (key === 'stack' ? undefined : value), 2) + } + result += `${item as string} ` + } + return result + } + private checkLogLevel ( type: string, level: undefined | string | string[] @@ -134,9 +129,8 @@ export class ManageLogger implements ILogger { } if (Array.isArray(level)) { return level.some((item: string) => item === type || item === 'all') - } else { - return type === level } + return type === level } success (...msq: ILogArgvType[]): void { diff --git a/src/main/migrate/index.ts b/src/main/migrate/index.ts deleted file mode 100644 index f29bea6..0000000 --- a/src/main/migrate/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { DBStore } from '@picgo/store' -import ConfigStore from '~/main/apis/core/datastore' -import path from 'path' -import fse from 'fs-extra' -import { PicGo as PicGoCore } from 'piclist' -import { T } from '~/main/i18n' -// from v2.1.2 -const updateShortKeyFromVersion212 = (db: typeof ConfigStore, shortKeyConfig: IShortKeyConfigs | IOldShortKeyConfigs) => { - // #557 极端情况可能会出现配置不存在,需要重新写入 - if (shortKeyConfig === undefined) { - const defaultShortKeyConfig = { - enable: true, - key: 'CommandOrControl+Shift+P', - name: 'upload', - label: T('QUICK_UPLOAD') - } - db.set('settings.shortKey[picgo:upload]', defaultShortKeyConfig) - return true - } - if (shortKeyConfig.upload) { - // @ts-ignore - shortKeyConfig['picgo:upload'] = { - enable: true, - key: shortKeyConfig.upload, - name: 'upload', - label: T('QUICK_UPLOAD') - } - // @ts-ignore - delete shortKeyConfig.upload - db.set('settings.shortKey', shortKeyConfig) - return true - } - return false -} - -const migrateGalleryFromVersion230 = async (configDB: typeof ConfigStore, galleryDB: DBStore, picgo: PicGoCore) => { - const originGallery: ImgInfo[] = picgo.getConfig('uploaded') - // if hasMigrate, we don't need to migrate - const hasMigrate: boolean = configDB.get('__migrateUploaded') - if (hasMigrate) { - return - } - const configPath = configDB.getConfigPath() - const configBakPath = path.join(path.dirname(configPath), 'config.bak.json') - // migrate gallery from config to gallery db - if (originGallery && Array.isArray(originGallery) && originGallery?.length > 0) { - if (fse.existsSync(configBakPath)) { - fse.copyFileSync(configPath, configBakPath) - } - await galleryDB.insertMany(originGallery) - picgo.saveConfig({ - uploaded: [], - __migrateUploaded: true - }) - } -} - -export { - updateShortKeyFromVersion212, - migrateGalleryFromVersion230 -} diff --git a/src/main/server/index.ts b/src/main/server/index.ts index a586149..32f78e5 100644 --- a/src/main/server/index.ts +++ b/src/main/server/index.ts @@ -11,6 +11,7 @@ import axios from 'axios' class Server { private httpServer: http.Server private config: IServerConfig + constructor () { let config = picgo.getConfig('settings.server') const result = this.checkIfConfigIsValid(config) @@ -31,11 +32,7 @@ class Server { } private checkIfConfigIsValid (config: IObj | undefined) { - if (config && config.port && config.host && (config.enable !== undefined)) { - return true - } else { - return false - } + return config && config.port && config.host && (config.enable !== undefined) } private handleRequest = (request: http.IncomingMessage, response: http.ServerResponse) => { diff --git a/src/main/server/routerManager.ts b/src/main/server/routerManager.ts index cea8aa2..c21eed6 100644 --- a/src/main/server/routerManager.ts +++ b/src/main/server/routerManager.ts @@ -7,9 +7,9 @@ import windowManager from 'apis/app/window/windowManager' import { uploadChoosedFiles, uploadClipboardFiles, deleteChoosedFiles } from 'apis/app/uploader/apis' import path from 'path' import { dbPathDir } from 'apis/core/datastore/dbChecker' + const STORE_PATH = dbPathDir() const LOG_PATH = path.join(STORE_PATH, 'piclist.log') -// import AllAPI from '../../renderer/apis/allApi' const errorMessage = `upload error. see ${LOG_PATH} for more detail.` const deleteErrorMessage = `delete error. see ${LOG_PATH} for more detail.` diff --git a/src/main/utils/deleteFunc.ts b/src/main/utils/deleteFunc.ts new file mode 100644 index 0000000..80c42c8 --- /dev/null +++ b/src/main/utils/deleteFunc.ts @@ -0,0 +1,64 @@ +import { S3Client, DeleteObjectCommand, S3ClientConfig } from '@aws-sdk/client-s3' +import { NodeHttpHandler } from '@smithy/node-http-handler' +import http, { AgentOptions } from 'http' +import https from 'https' +import { getAgent } from '../manage/utils/common' + +export async function removeFileFromS3InMain (configMap: IStringKeyMap) { + try { + const { imgUrl, config: { accessKeyID, secretAccessKey, bucketName, region, endpoint, pathStyleAccess, rejectUnauthorized, proxy } } = configMap + const url = new URL(!/^https?:\/\//.test(imgUrl) ? `http://${imgUrl}` : imgUrl) + const fileKey = url.pathname.replace(/^\/+/, '') + const endpointUrl: string | undefined = endpoint + ? /^https?:\/\//.test(endpoint) + ? endpoint + : `http://${endpoint}` + : undefined + const sslEnabled = endpointUrl ? endpointUrl.startsWith('https') : true + const agent = getAgent(proxy, sslEnabled) + const commonOptions: AgentOptions = { + keepAlive: true, + keepAliveMsecs: 1000, + scheduling: 'lifo' as 'lifo' | 'fifo' | undefined + } + const extraOptions = sslEnabled ? { rejectUnauthorized: !!rejectUnauthorized } : {} + const handler = sslEnabled + ? new NodeHttpHandler({ + httpsAgent: agent.https + ? agent.https + : new https.Agent({ + ...commonOptions, + ...extraOptions + }) + }) + : new NodeHttpHandler({ + httpAgent: agent.http + ? agent.http + : new http.Agent({ + ...commonOptions, + ...extraOptions + }) + }) + const s3Options: S3ClientConfig = { + credentials: { + accessKeyId: accessKeyID, + secretAccessKey + }, + endpoint: endpointUrl, + tls: sslEnabled, + forcePathStyle: pathStyleAccess, + region, + requestHandler: handler + } + const client = new S3Client(s3Options) + const command = new DeleteObjectCommand({ + Bucket: bucketName, + Key: fileKey + }) + const result = await client.send(command) + return result.$metadata.httpStatusCode === 204 + } catch (err: any) { + console.log(err) + return false + } +} diff --git a/src/renderer/apis/allApi.ts b/src/renderer/apis/allApi.ts index ad4ba6d..d854783 100644 --- a/src/renderer/apis/allApi.ts +++ b/src/renderer/apis/allApi.ts @@ -1,35 +1,32 @@ +import AliyunApi from './aliyun' +import AwsS3Api from './awss3' +import GithubApi from './github' +import ImgurApi from './imgur' +import LocalApi from './local' +import QiniuApi from './qiniu' +import SftpPlistApi from './sftpplist' import SmmsApi from './smms' import TcyunApi from './tcyun' -import AliyunApi from './aliyun' -import QiniuApi from './qiniu' -import ImgurApi from './imgur' -import GithubApi from './github' import UpyunApi from './upyun' -import AwsS3Api from './awss3' import WebdavApi from './webdav' -import LocalApi from './local' -import SftpPlistApi from './sftpplist' const apiMap: IStringKeyMap = { + aliyun: AliyunApi, + 'aws-s3': AwsS3Api, + github: GithubApi, + imgur: ImgurApi, + local: LocalApi, + qiniu: QiniuApi, + sftpplist: SftpPlistApi, smms: SmmsApi, tcyun: TcyunApi, - aliyun: AliyunApi, - qiniu: QiniuApi, - imgur: ImgurApi, - github: GithubApi, upyun: UpyunApi, - 'aws-s3': AwsS3Api, - webdavplist: WebdavApi, - local: LocalApi, - sftpplist: SftpPlistApi + webdavplist: WebdavApi } export default class ALLApi { static async delete (configMap: IStringKeyMap): Promise { const api = apiMap[configMap.type] - if (api) { - return await api.delete(configMap) - } - return false + return api ? await api.delete(configMap) : false } } diff --git a/src/renderer/apis/awss3.ts b/src/renderer/apis/awss3.ts index a0fa156..72e173c 100644 --- a/src/renderer/apis/awss3.ts +++ b/src/renderer/apis/awss3.ts @@ -1,13 +1,15 @@ import { ipcRenderer } from 'electron' import { getRawData } from '~/renderer/utils/common' +import { removeFileFromS3InMain } from '~/main/utils/deleteFunc' export default class AwsS3Api { static async delete (configMap: IStringKeyMap): Promise { try { - const deleteResult = await ipcRenderer.invoke('delete-aws-s3-file', - getRawData(configMap) - ) - return deleteResult + return ipcRenderer + ? await ipcRenderer.invoke('delete-aws-s3-file', + getRawData(configMap) + ) + : await removeFileFromS3InMain(getRawData(configMap)) } catch (error) { console.log(error) return false diff --git a/src/renderer/apis/imgur.ts b/src/renderer/apis/imgur.ts index 3497b95..c184abb 100644 --- a/src/renderer/apis/imgur.ts +++ b/src/renderer/apis/imgur.ts @@ -17,6 +17,8 @@ interface IConfig { } export default class ImgurApi { + static baseUrl: 'https://api.imgur.com/3' + private static async makeRequest ( method: 'delete', url: string, @@ -35,25 +37,23 @@ export default class ImgurApi { } static async delete (configMap: IConfigMap): Promise { - const { config = {}, hash = '' } = configMap || {} - const { clientId = '', username = '', accessToken = '' } = config - const baseUrl = 'https://api.imgur.com/3' - let Authorization: string - let apiUrl: string + const { + config: { clientId = '', username = '', accessToken = '' } = {}, + hash = '' + } = configMap + let Authorization: string, apiUrl: string + if (username && accessToken) { Authorization = `Bearer ${accessToken}` - apiUrl = `${baseUrl}/account/${username}/image/${hash}` + apiUrl = `${ImgurApi.baseUrl}/account/${username}/image/${hash}` } else if (clientId) { Authorization = `Client-ID ${clientId}` - apiUrl = `${baseUrl}/image/${hash}` + apiUrl = `${ImgurApi.baseUrl}/image/${hash}` } else { return false } - const headers = { - Authorization - } const requestConfig: IConfig = { - headers, + headers: { Authorization }, timeout: 30000 } return ImgurApi.makeRequest('delete', apiUrl, requestConfig) diff --git a/src/renderer/apis/local.ts b/src/renderer/apis/local.ts index 3dcdb27..6f96849 100644 --- a/src/renderer/apis/local.ts +++ b/src/renderer/apis/local.ts @@ -8,7 +8,7 @@ export default class LocalApi { static async delete (configMap: IConfigMap): Promise { const { hash } = configMap if (!hash) { - console.error('SmmsApi.delete: invalid params') + console.error('Local.delete: invalid params') return false } diff --git a/src/renderer/apis/qiniu.ts b/src/renderer/apis/qiniu.ts index 6fcbcfb..d8fb225 100644 --- a/src/renderer/apis/qiniu.ts +++ b/src/renderer/apis/qiniu.ts @@ -31,7 +31,7 @@ export default class QiniuApi { } }) }) as any - return res && res.respInfo.statusCode === 200 + return res?.respInfo?.statusCode === 200 } catch (error) { console.error(error) return false diff --git a/src/renderer/layouts/Main.vue b/src/renderer/layouts/Main.vue index 733904a..3d7951f 100644 --- a/src/renderer/layouts/Main.vue +++ b/src/renderer/layouts/Main.vue @@ -322,7 +322,7 @@ const choosedPicBedForQRCode: Ref = ref([]) const isAlwaysOnTop = ref(false) const keepAlivePages = $router.getRoutes().filter(item => item.meta.keepAlive).map(item => item.name as string) -const progressShow = ref(true) +const progressShow = ref(false) const progressPercentage = ref(0) onBeforeMount(() => { diff --git a/src/renderer/pages/Gallery.vue b/src/renderer/pages/Gallery.vue index 75bb4de..85e107d 100644 --- a/src/renderer/pages/Gallery.vue +++ b/src/renderer/pages/Gallery.vue @@ -461,6 +461,7 @@ import ALLApi from '@/apis/allApi' // 工具函数 import { customRenameFormatTable, customStrMatch, customStrReplace } from '../manage/utils/common' +import { picBedsCanbeDeleted } from '#/utils/static' const images = ref([]) const dialogVisible = ref(false) @@ -688,7 +689,6 @@ function remove (item: ImgInfo) { type: 'warning' }).then(async () => { const file = await $$db.getById(item.id!) - const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local', 'sftpplist'] if (await getConfig('settings.deleteCloudFile')) { if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) { const result = await ALLApi.delete(item) @@ -798,7 +798,6 @@ function multiRemove () { const files: IResult[] = [] const imageIDList = Object.keys(choosedList) const isDeleteCloudFile = await getConfig('settings.deleteCloudFile') - const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist', 'local', 'sftpplist'] if (isDeleteCloudFile) { for (let i = 0; i < imageIDList.length; i++) { const key = imageIDList[i] @@ -1161,3 +1160,4 @@ export default { color #ddd margin-bottom 10px +@/apis diff --git a/src/universal/utils/static.ts b/src/universal/utils/static.ts index a7e7abb..57cbe6c 100644 --- a/src/universal/utils/static.ts +++ b/src/universal/utils/static.ts @@ -5,3 +5,5 @@ export const RELEASE_URL = 'https://api.github.com/repos/Kuingsmile/PicList/rele export const RELEASE_URL_BACKUP = 'https://release.piclist.cn' export const STABLE_RELEASE_URL = 'https://github.com/Kuingsmile/PicList/releases/latest' export const C1 = Buffer.from(C1N, 'base64').toString() + +export const picBedsCanbeDeleted = ['aliyun', 'aws-s3', 'github', 'imgur', 'local', 'sftpplist', 'smms', 'qiniu', 'tcyun', 'upyun', 'webdavplist']