mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-03-13 00:18:13 -04:00
🐛 Fix: add local path picbed into delete api of http server
This commit is contained in:
parent
517348886c
commit
f585bb4d7d
@ -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<false | ImgInfo[]> => {
|
||||
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<boolean[]> => {
|
||||
const result = []
|
||||
const picBedsCanbeDeleted = ['smms', 'github', 'imgur', 'tcyun', 'aliyun', 'qiniu', 'upyun', 'aws-s3', 'webdavplist']
|
||||
for (const item of list) {
|
||||
if (item.id) {
|
||||
try {
|
||||
@ -135,6 +154,26 @@ export const deleteChoosedFiles = async (list: ImgInfo[]): Promise<boolean[]> =>
|
||||
const file = await dbStore.removeById(item.id)
|
||||
if (await picgo.getConfig('settings.deleteCloudFile')) {
|
||||
if (item.type !== undefined && picBedsCanbeDeleted.includes(item.type)) {
|
||||
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) {
|
||||
@ -154,6 +193,7 @@ export const deleteChoosedFiles = async (list: ImgInfo[]): Promise<boolean[]> =>
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
picgo.emit('remove', [file], GuiApi.getInstance())
|
||||
}, 500)
|
||||
|
@ -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
|
||||
|
@ -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 () {
|
||||
|
@ -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<any> {
|
||||
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,9 +104,8 @@ export class ManageApi extends EventEmitter implements ManageApiType {
|
||||
getConfig<T> (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 {
|
||||
|
@ -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 }
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
@ -11,6 +11,7 @@ import axios from 'axios'
|
||||
class Server {
|
||||
private httpServer: http.Server
|
||||
private config: IServerConfig
|
||||
|
||||
constructor () {
|
||||
let config = picgo.getConfig<IServerConfig>('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) => {
|
||||
|
@ -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.`
|
||||
|
64
src/main/utils/deleteFunc.ts
Normal file
64
src/main/utils/deleteFunc.ts
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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<boolean> {
|
||||
const api = apiMap[configMap.type]
|
||||
if (api) {
|
||||
return await api.delete(configMap)
|
||||
}
|
||||
return false
|
||||
return api ? await api.delete(configMap) : false
|
||||
}
|
||||
}
|
||||
|
@ -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<boolean> {
|
||||
try {
|
||||
const deleteResult = await ipcRenderer.invoke('delete-aws-s3-file',
|
||||
return ipcRenderer
|
||||
? await ipcRenderer.invoke('delete-aws-s3-file',
|
||||
getRawData(configMap)
|
||||
)
|
||||
return deleteResult
|
||||
: await removeFileFromS3InMain(getRawData(configMap))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return false
|
||||
|
@ -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<boolean> {
|
||||
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)
|
||||
|
@ -8,7 +8,7 @@ export default class LocalApi {
|
||||
static async delete (configMap: IConfigMap): Promise<boolean> {
|
||||
const { hash } = configMap
|
||||
if (!hash) {
|
||||
console.error('SmmsApi.delete: invalid params')
|
||||
console.error('Local.delete: invalid params')
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -322,7 +322,7 @@ const choosedPicBedForQRCode: Ref<string[]> = 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(() => {
|
||||
|
@ -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<ImgInfo[]>([])
|
||||
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<ImgInfo>[] = []
|
||||
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
|
||||
</style>
|
||||
@/apis
|
||||
|
@ -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']
|
||||
|
Loading…
Reference in New Issue
Block a user