🚧 WIP(custom): v3.0.0 migrate to vite and esm

This commit is contained in:
Kuingsmile
2025-07-31 17:37:30 +08:00
parent cd76bc7c10
commit 054f4b4cff
597 changed files with 197292 additions and 13329 deletions

View File

@@ -0,0 +1,49 @@
import path from 'node:path'
import axios from 'axios'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
config: {
version: string
url: string
uploadPath: string
token: string
}
}
export default class AlistApi {
static async delete (configMap: IConfigMap): Promise<boolean> {
const { fileName, config } = configMap
try {
const { version, url, uploadPath, token } = config
if (String(version) === '2') {
deleteLog(fileName, 'Alist', false, 'Alist version 2 is not supported, deletion is skipped')
return true
}
const result = await axios.request({
method: 'post',
url: `${url}/api/fs/remove`,
headers: {
'Content-Type': 'application/json',
Authorization: token
},
data: {
dir: path.join('/', uploadPath, path.dirname(fileName)),
names: [path.basename(fileName)]
}
})
if (result.data.code === 200) {
deleteLog(fileName, 'Alist')
return true
}
deleteLog(fileName, 'Alist', false)
return false
} catch (error: any) {
deleteFailedLog(fileName, 'Alist', error)
return false
}
}
}

View File

@@ -0,0 +1,64 @@
import path from 'node:path'
import axios from 'axios'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
config: {
url: string
username: string
password: string
uploadPath: string
token: string
}
}
const getAListToken = async (url: string, username: string, password: string) => {
const res = await axios.post(`${url}/api/auth/login`, {
username,
password
})
if (res.data.code === 200 && res.data.message === 'success') {
return res.data.data.token
}
}
export default class AListplistApi {
static async delete (configMap: IConfigMap): Promise<boolean> {
const { fileName, config } = configMap
try {
const { url, username, password, uploadPath } = config
let token = config.token
if (!token) {
token = await getAListToken(url, username, password)
}
if (!url || !(token || (username && password))) {
deleteFailedLog(fileName, 'Alist', 'No valid token or username/password provided')
return false
}
const result = await axios.request({
method: 'post',
url: `${url}/api/fs/remove`,
headers: {
'Content-Type': 'application/json',
Authorization: token
},
data: {
dir: path.join('/', uploadPath, path.dirname(fileName)),
names: [path.basename(fileName)]
}
})
if (result.data.code === 200) {
deleteLog(fileName, 'Alist')
return true
}
deleteLog(fileName, 'Alist', false)
return false
} catch (error: any) {
deleteFailedLog(fileName, 'Alist', error)
return false
}
}
}

View File

@@ -0,0 +1,33 @@
import OSS from 'ali-oss'
import { IAliYunConfig, PartialKeys } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
config: PartialKeys<IAliYunConfig, 'path'>
}
export default class AliyunApi {
static #getKey (fileName: string, path?: string): string {
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${fileName}` : fileName
}
static async delete (configMap: IConfigMap): Promise<boolean> {
const { fileName, config } = configMap
try {
const client = new OSS({ ...config, region: config.area })
const key = AliyunApi.#getKey(fileName, config.path)
const result = await client.delete(key)
if (result.res.status === 204) {
deleteLog(fileName, 'Aliyun')
return true
}
deleteLog(fileName, 'Aliyun', false)
return false
} catch (error: any) {
deleteFailedLog(fileName, 'Aliyun', error)
return false
}
}
}

View File

@@ -0,0 +1,46 @@
import { IStringKeyMap } from '#/types/types'
import AlistApi from '~/apis/delete/alist'
import AlistplistApi from '~/apis/delete/alistplist'
import AliyunApi from '~/apis/delete/aliyun'
import AwsS3Api from '~/apis/delete/awss3'
import DogeCloudApi from '~/apis/delete/dogecloud'
import GithubApi from '~/apis/delete/github'
import HuaweicloudApi from '~/apis/delete/huaweiyun'
import ImgurApi from '~/apis/delete/imgur'
import LocalApi from '~/apis/delete/local'
import LskyplistApi from '~/apis/delete/lskyplist'
import PiclistApi from '~/apis/delete/piclist'
import QiniuApi from '~/apis/delete/qiniu'
import SftpPlistApi from '~/apis/delete/sftpplist'
import SmmsApi from '~/apis/delete/smms'
import TcyunApi from '~/apis/delete/tcyun'
import UpyunApi from '~/apis/delete/upyun'
import WebdavApi from '~/apis/delete/webdav'
const apiMap: IStringKeyMap = {
alist: AlistApi,
alistplist: AlistplistApi,
aliyun: AliyunApi,
'aws-s3': AwsS3Api,
'aws-s3-plist': AwsS3Api,
dogecloud: DogeCloudApi,
github: GithubApi,
'huaweicloud-uploader': HuaweicloudApi,
imgur: ImgurApi,
local: LocalApi,
lskyplist: LskyplistApi,
piclist: PiclistApi,
qiniu: QiniuApi,
sftpplist: SftpPlistApi,
smms: SmmsApi,
tcyun: TcyunApi,
upyun: UpyunApi,
webdavplist: WebdavApi
}
export default class ALLApi {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
const api = apiMap[configMap.type]
return api ? await api.delete(configMap) : false
}
}

View File

@@ -0,0 +1,15 @@
import { getRawData } from '@/utils/common'
import { IStringKeyMap } from '#/types/types'
import { removeFileFromS3InMain } from '~/utils/deleteFunc'
import { deleteFailedLog } from '~/utils/deleteLog'
export default class AwsS3Api {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
try {
return await removeFileFromS3InMain(getRawData(configMap))
} catch (error: any) {
deleteFailedLog(configMap.fileName, 'AWS S3', error)
return false
}
}
}

View File

@@ -0,0 +1,15 @@
import { getRawData } from '@/utils/common'
import { IStringKeyMap } from '#/types/types'
import { removeFileFromDogeInMain } from '~/utils/deleteFunc'
import { deleteFailedLog } from '~/utils/deleteLog'
export default class AwsS3Api {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
try {
return await removeFileFromDogeInMain(getRawData(configMap))
} catch (error: any) {
deleteFailedLog(configMap.fileName, 'DogeCloud', error)
return false
}
}
}

View File

@@ -0,0 +1,53 @@
import { Octokit } from '@octokit/rest'
import { IGitHubConfig, PartialKeys } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
hash: string
config: PartialKeys<IGitHubConfig, 'path'>
}
export default class GithubApi {
static #createOctokit (token: string) {
return new Octokit({
auth: token
})
}
static #createKey (path: string | undefined, fileName: string): string {
const formatedFileName = fileName.replace(/%2F/g, '/')
return path && path !== '/' ? `${path.replace(/^\/+|\/+$/, '')}/${formatedFileName}` : formatedFileName
}
static async delete (configMap: IConfigMap): Promise<boolean> {
const {
fileName,
hash,
config: { repo, token, branch, path }
} = configMap
const [owner, repoName] = repo.split('/')
const octokit = GithubApi.#createOctokit(token)
const key = GithubApi.#createKey(path, fileName)
try {
const { status } = await octokit.rest.repos.deleteFile({
owner,
repo: repoName,
path: key,
message: `delete ${fileName} by PicList`,
sha: hash,
branch
})
if (status === 200) {
deleteLog(fileName, 'GitHub')
return true
}
deleteLog(fileName, 'GitHub', false)
return false
} catch (error: any) {
deleteFailedLog(fileName, 'GitHub', error)
return false
}
}
}

View File

@@ -0,0 +1,15 @@
import { getRawData } from '@/utils/common'
import { IStringKeyMap } from '#/types/types'
import { removeFileFromHuaweiInMain } from '~/utils/deleteFunc'
import { deleteFailedLog } from '~/utils/deleteLog'
export default class HuaweicloudApi {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
try {
return await removeFileFromHuaweiInMain(getRawData(configMap))
} catch (error: any) {
deleteFailedLog(configMap.fileName, 'HuaweiCloud', error)
return false
}
}
}

View File

@@ -0,0 +1,44 @@
import axios, { AxiosResponse } from 'axios'
import { IImgurConfig } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
config?: Partial<IImgurConfig>
hash?: string
}
export default class ImgurApi {
static #baseUrl = 'https://api.imgur.com/3'
static async delete (configMap: IConfigMap): Promise<boolean> {
const { config: { clientId = '', username = '', accessToken = '' } = {}, hash = '' } = configMap
let Authorization: string, apiUrl: string
if (username && accessToken) {
Authorization = `Bearer ${accessToken}`
apiUrl = `${ImgurApi.#baseUrl}/account/${username}/image/${hash}`
} else if (clientId) {
Authorization = `Client-ID ${clientId}`
apiUrl = `${ImgurApi.#baseUrl}/image/${hash}`
} else {
deleteLog(hash, 'Imgur', false, 'No credentials found')
return false
}
try {
const response: AxiosResponse = await axios.delete(apiUrl, {
headers: { Authorization },
timeout: 30000
})
if (response.status === 200) {
deleteLog(hash, 'Imgur')
return true
}
deleteLog(hash, 'Imgur', false)
return false
} catch (error: any) {
deleteFailedLog(hash, 'Imgur', error)
return false
}
}
}

View File

@@ -0,0 +1,26 @@
import fs from 'fs-extra'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
hash: string
}
export default class LocalApi {
static async delete (configMap: IConfigMap): Promise<boolean> {
const { hash } = configMap
if (!hash) {
deleteLog(hash, 'Local', false, 'Local.delete: invalid params')
return false
}
try {
await fs.remove(hash)
deleteLog(hash, 'Local')
return true
} catch (error: any) {
deleteFailedLog(hash, 'Local', error)
return false
}
}
}

View File

@@ -0,0 +1,47 @@
import https from 'node:https'
import axios, { AxiosResponse } from 'axios'
import { IStringKeyMap } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
export default class LskyplistApi {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
const { hash, config } = configMap
if (!hash || !config || !config.token) {
deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid params')
return false
}
const { host, token, version } = config
if (version !== 'V2') {
deleteLog(hash, 'Lskyplist', false, 'LskyplistApi.delete: invalid version')
return false
}
const v2Headers = {
Accept: 'application/json',
Authorization: token || undefined
}
const requestAgent = new https.Agent({
rejectUnauthorized: false
})
try {
const response: AxiosResponse = await axios.delete(`${host}/api/v1/images/${hash}`, {
headers: v2Headers,
timeout: 30000,
httpsAgent: requestAgent
})
if (response.status === 200 && response.data.status === true) {
deleteLog(hash, 'Lskyplist')
return true
}
deleteLog(hash, 'Lskyplist', false)
return false
} catch (error: any) {
deleteFailedLog(hash, 'Lskyplist', error)
return false
}
}
}

View File

@@ -0,0 +1,34 @@
import axios, { AxiosResponse } from 'axios'
import { IStringKeyMap } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
export default class PiclistApi {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
const { config, fullResult } = configMap
const { host, port } = config
if (!fullResult) return true
if (!host) {
deleteLog(fullResult, 'Piclist', false, 'PiclistApi.delete: invalid params')
return false
}
const url = `http://${host || '127.0.0.1'}:${port || 36677}/delete`
try {
const response: AxiosResponse = await axios.post(url, {
list: [fullResult]
})
if (response.status === 200 && response.data?.success) {
deleteLog(fullResult, 'Piclist')
return true
}
deleteLog(fullResult, 'Piclist', false)
return false
} catch (error: any) {
deleteFailedLog(fullResult, 'Piclist', error)
return false
}
}
}

View File

@@ -0,0 +1,44 @@
import { IQiniuConfig, PartialKeys } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
config: PartialKeys<IQiniuConfig, 'path'>
}
export default class QiniuApi {
static async delete (configMap: IConfigMap): Promise<boolean> {
const {
fileName,
config: { accessKey, secretKey, bucket, path }
} = configMap
const mac = new window.node.qiniu.auth.digest.Mac(accessKey, secretKey)
const qiniuConfig = new window.node.qiniu.conf.Config()
try {
const bucketManager = new window.node.qiniu.rs.BucketManager(mac, qiniuConfig)
const formattedPath = path?.replace(/^\/+|\/+$/, '') || ''
const key = path === '/' || !path ? fileName : `${formattedPath}/${fileName}`
const res = (await new Promise((resolve, reject) => {
bucketManager.delete(bucket, key, (err, respBody, respInfo) => {
if (err) {
reject(err)
} else {
resolve({
respBody,
respInfo
})
}
})
})) as any
if (res?.respInfo?.statusCode === 200) {
deleteLog(fileName, 'Qiniu')
return true
}
deleteLog(fileName, 'Qiniu', false)
return false
} catch (error: any) {
deleteFailedLog(fileName, 'Qiniu', error)
return false
}
}
}

View File

@@ -0,0 +1,16 @@
import { getRawData } from '@/utils/common'
import { IStringKeyMap } from '#/types/types'
import { removeFileFromSFTPInMain } from '~/utils/deleteFunc'
import { deleteFailedLog } from '~/utils/deleteLog'
export default class SftpPlistApi {
static async delete (configMap: IStringKeyMap): Promise<boolean> {
const { fileName, config } = configMap
try {
return await removeFileFromSFTPInMain(getRawData(config), fileName)
} catch (error: any) {
deleteFailedLog(fileName, 'SFTP', error)
return false
}
}
}

View File

@@ -0,0 +1,45 @@
import axios, { AxiosResponse } from 'axios'
import { ISMMSConfig } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
hash?: string
config?: Partial<ISMMSConfig>
}
export default class SmmsApi {
static readonly #baseUrl = 'https://smms.app/api/v2'
static async delete (configMap: IConfigMap): Promise<boolean> {
const { hash, config } = configMap
if (!hash || !config || !config.token) {
deleteLog(hash, 'Smms', false, 'SmmsApi.delete: invalid params')
return false
}
const { token } = config
try {
const response: AxiosResponse = await axios.get(`${SmmsApi.#baseUrl}/delete/${hash}`, {
headers: {
Authorization: token
},
params: {
hash,
format: 'json'
},
timeout: 30000
})
if (response.status === 200) {
deleteLog(hash, 'Smms')
return true
}
deleteLog(hash, 'Smms', false)
return false
} catch (error: any) {
deleteFailedLog(hash, 'Smms', error)
return false
}
}
}

View File

@@ -0,0 +1,46 @@
import COS from 'cos-nodejs-sdk-v5'
import { ITcYunConfig, PartialKeys } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
config: PartialKeys<ITcYunConfig, 'path'>
}
export default class TcyunApi {
static #createCOS (SecretId: string, SecretKey: string): COS {
return new COS({
SecretId,
SecretKey
})
}
static async delete (configMap: IConfigMap): Promise<boolean> {
const {
fileName,
config: { secretId, secretKey, bucket, area, path }
} = configMap
try {
const cos = TcyunApi.#createCOS(secretId, secretKey)
let key
if (path === '/' || !path) {
key = `/${fileName}`
} else {
key = `/${path.replace(/^\/+|\/+$/, '')}/${fileName}`
}
const result = await cos.deleteObject({
Bucket: bucket,
Region: area,
Key: key
})
if (result.statusCode === 204) {
deleteLog(fileName, 'Tcyun')
return true
}
deleteLog(fileName, 'Tcyun', false)
return false
} catch (error: any) {
deleteFailedLog(fileName, 'Tcyun', error)
return false
}
}
}

View File

@@ -0,0 +1,38 @@
import Upyun from 'upyun'
import { IUpYunConfig, PartialKeys } from '#/types/types'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
config: PartialKeys<IUpYunConfig, 'path'>
}
export default class UpyunApi {
static async delete (configMap: IConfigMap): Promise<boolean> {
const {
fileName,
config: { bucket, operator, password, path }
} = configMap
try {
const service = new Upyun.Service(bucket, operator, password)
const client = new Upyun.Client(service)
let key
if (path === '/' || !path) {
key = fileName
} else {
key = `${path.replace(/^\/+|\/+$/, '')}/${fileName}`
}
const result = await client.deleteFile(key)
if (result) {
deleteLog(fileName, 'Upyun')
return true
}
deleteLog(fileName, 'Upyun', false)
return false
} catch (error: any) {
deleteFailedLog(fileName, 'Upyun', error)
return false
}
}
}

View File

@@ -0,0 +1,42 @@
import { AuthType, createClient, WebDAVClientOptions } from 'webdav'
import { IWebdavPlistConfig, PartialKeys } from '#/types/types'
import { formatEndpoint } from '#/utils/common'
import { deleteFailedLog, deleteLog } from '~/utils/deleteLog'
interface IConfigMap {
fileName: string
config: PartialKeys<IWebdavPlistConfig, 'path'>
}
export default class WebdavApi {
static async delete (configMap: IConfigMap): Promise<boolean> {
const {
fileName,
config: { host, username, password, path, sslEnabled, authType }
} = configMap
const endpoint = formatEndpoint(host, sslEnabled)
const options: WebDAVClientOptions = {
username,
password
}
if (authType === 'digest') {
options.authType = AuthType.Digest
}
const ctx = createClient(endpoint, options)
let key
if (path === '/' || !path) {
key = fileName
} else {
key = `${path.replace(/^\/+|\/+$/, '')}/${fileName}`
}
try {
await ctx.deleteFile(key)
deleteLog(fileName, 'WebDAV')
return true
} catch (error: any) {
deleteFailedLog(fileName, 'WebDAV', error)
return false
}
}
}